Move zooming into its own component, imported via HTML Imports.

Also, start building our own polyfill library (polyfill.js) using Grunt and Bower.

Finally, refactor all the web pages so that the common header and footer material comes from templates.

BUG=skia:
R=mtklein@google.com

Author: jcgregorio@google.com

Review URL: https://codereview.chromium.org/292433002

git-svn-id: http://skia.googlecode.com/svn/trunk@14783 2bbb7eff-a529-9590-31e7-b0007b416f81
This commit is contained in:
commit-bot@chromium.org 2014-05-19 16:40:08 +00:00
parent 99bd7d8174
commit 015c08e5ca
19 changed files with 520 additions and 406 deletions

View File

@ -89,5 +89,6 @@ Do this step only once, but only after running webtry_setup.sh the first time
Third Party Code
----------------
* res/js/pointerevents.min.js - obtained from https://github.com/components/pointerevents-polyfill
* res/js/polyfill.js - Various JS polyfill libraries. To rebuild or update
see polyfill/README.md.

View File

@ -0,0 +1,3 @@
{
"directory": "../../../out/bower"
}

View File

@ -0,0 +1,64 @@
module.exports = function(grunt) {
// Project configuration.
grunt.initConfig({
pkg: grunt.file.readJSON('package.json'),
// Install all the packages listed in the bower.json file.
shell: {
bower_install: {
command: 'bower install'
}
},
// Copy all the bower files into a single directory.
bower: {
dev: {
dest: '../../../out/grunt/third_party'
}
},
// Concatenate all the files in third_party into a single file.
concat: {
dist: {
src: [
'../../../out/grunt/third_party/WeakMap.js',
'../../../out/grunt/third_party/classlist.js',
'../../../out/grunt/third_party/pointerevents-polyfill.js',
'../../../out/grunt/third_party/MutationObserver.js',
'../../../out/grunt/third_party/CustomElements.js',
'../../../out/grunt/third_party/HTMLImports.js',
],
dest: '../../../out/grunt/src/<%= pkg.name %>.js'
}
},
// Uglify the one big file into one smaller file.
uglify: {
options: {
banner: '/*! <%= pkg.name %> built from /exerimental/webtry/poly <%= grunt.template.today("yyyy-mm-dd") %> */\n'
},
build: {
src: '../../../out/grunt/src/<%= pkg.name %>.js',
dest: '../res/js/<%= pkg.name %>.js'
}
},
copy: {
simple: {
src: '../../../out/grunt/src/<%= pkg.name %>.js',
dest: '../res/js/<%= pkg.name %>.js'
}
}
});
// Load the plugins for the above commands.
grunt.loadNpmTasks('grunt-bower');
grunt.loadNpmTasks('grunt-contrib-concat');
grunt.loadNpmTasks('grunt-contrib-copy');
grunt.loadNpmTasks('grunt-contrib-cssmin');
grunt.loadNpmTasks('grunt-contrib-uglify');
grunt.loadNpmTasks('grunt-shell');
// By default run all the commands in the right sequence to build our custom minified polyfill.
grunt.registerTask('default', ['shell:bower_install', 'bower', 'concat', 'uglify']);
// A target to build an unminified version, for debugging.
grunt.registerTask('notmin', ['shell:bower_install', 'bower', 'concat', 'copy:simple']);
};

View File

@ -0,0 +1,18 @@
polyfill.js
===========
To rebuild or update res/js/polyfill.js you will need to have
[node.js](http://nodejs.org/) installed. Once you have it installed run the
following:
cd polyfill
npm install
grunt
If you want to create a verion of the polyfill.js that hasn't been minified,
say for debugging purposes, then run:
cd polyfill
npm install
grunt notmin

View File

@ -0,0 +1,22 @@
{
"name": "polyfill",
"version": "0.0.1",
"authors": [
"Joe Gregorio <jcgregorio@google.com>"
],
"description": "All the third party polyfills we use.",
"license": "MIT",
"private": true,
"ignore": [
"**/.*",
"node_modules",
"bower_components",
"test",
"tests"
],
"dependencies": {
"pointerevents-polyfill": "~0.2.0",
"CustomElements": "~0.2.3",
"HTMLImports": "~0.2.3"
}
}

View File

@ -0,0 +1,17 @@
{
"name": "polyfill",
"version": "0.0.1",
"description": "All the dependencies we need to run grunt and build our minified polyfill JS library.",
"main": "polyfill.js",
"author": "jcgregorio@google.com",
"license": "MIT",
"devDependencies": {
"grunt": "~0.4.5",
"grunt-contrib-uglify": "~0.4.0",
"grunt-bower": "~0.13.1",
"grunt-contrib-concat": "~0.4.0",
"grunt-shell": "~0.7.0",
"grunt-contrib-copy": "~0.5.0",
"grunt-contrib-cssmin": "~0.9.0"
}
}

View File

@ -9,26 +9,6 @@ img {
background-image: url("data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAABAAAAAQCAAAAAA6mKC9AAAAAXNSR0IArs4c6QAAAAJiS0dEAP+Hj8y/AAAACXBIWXMAAA7DAAAOwwHHb6hkAAAAB3RJTUUH3gUBEi4DGRAQYgAAAB1JREFUGNNjfMoAAVJQmokBDdBHgPE/lPFsYN0BABdaAwN6tehMAAAAAElFTkSuQmCC");
}
.zoom {
cursor: crosshair;
}
.zoomCanvas {
position: absolute;
width: vmin;
height: vmin;
top: 3em;
right: 1em;
z-index: -1;
}
#zoomCopy {
display: none;
}
#zoomHex {
text-shadow: 1px 1px #eee;
}
h1 {
font-size: 18px;

View File

@ -0,0 +1,169 @@
<script type="text/javascript" charset="utf-8">
/**
* A reusable HTML Import to enable zooming on images.
*
* To use, simply include this HTML Import and add the class 'zoom' to any
* images you want zoomable.
*
* <link rel='import' type='text/html' href='/res/imp/zoom.html'>
*
* <img src="http://..." class="zoom"/>
*
* Any number of images on a page can be zoomable.
*
* If you want to display the rgb colors of the pixel at the center of the
* zoom then add an id of 'zoomHex' to any element that supports
* textContent, such as a div, p, span, etc.
*
* <p id=zoomHex></p>
*
* Note that HTML Imports need to be polyfilled in the near term.
*/
(function () {
function onLoad() {
var PIXELS = 20; // The number of pixels in width and height in a zoom.
var clientX = 0;
var clientY = 0;
var lastClientX = 0;
var lastClientY = 0;
var ctx = null; // The 2D canvas context of the zoom.
var currentImage = null; // The img node we are zooming for, otherwise null.
var hex = document.getElementById('zoomHex');
var canvasCopy = null;
function zoomMove(e) {
clientX = e.clientX;
clientY = e.clientY;
}
function zoomMouseDown(e) {
e.preventDefault();
// Only do zooming on the primary mouse button.
if (e.button != 0) {
return
}
currentImage = e.target;
clientX = e.clientX;
clientY = e.clientY;
lastClientX = clientX-1;
lastClientY = clientY-1;
document.body.style.cursor = 'crosshair';
canvas = document.createElement('canvas');
canvas.width = 1024;
canvas.height = 1024;
canvas.classList.add('zoomCanvas');
ctx = canvas.getContext('2d');
ctx.imageSmoothingEnabled = false;
this.parentNode.insertBefore(canvas, this);
// Copy the image over to a canvas so we can read RGBA values for each point.
if (hex) {
canvasCopy = document.createElement('canvas');
canvasCopy.width = currentImage.width;
canvasCopy.height = currentImage.height;
canvasCopy.id = 'zoomCopy';
canvasCopy.getContext('2d').drawImage(currentImage, 0, 0, currentImage.width, currentImage.height);
this.parentNode.insertBefore(canvasCopy, this);
}
document.body.addEventListener('pointermove', zoomMove, true);
document.body.addEventListener('pointerup', zoomFinished);
document.body.addEventListener('pointerleave', zoomFinished);
// Kick off the drawing.
setTimeout(drawZoom, 1);
}
function hexify(i) {
var s = i.toString(16).toUpperCase();
// Pad out to two hex digits if necessary.
if (s.length < 2) {
s = '0' + s;
}
return s;
}
function drawZoom() {
if (currentImage) {
// Only draw if the mouse has moved from the last time we drew.
if (lastClientX != clientX || lastClientY != clientY) {
ctx.clearRect(0, 0, ctx.canvas.width, ctx.canvas.height);
var x = clientX - currentImage.x;
var y = clientY - currentImage.y;
var dx = Math.floor(ctx.canvas.width/PIXELS);
var dy = Math.floor(ctx.canvas.height/PIXELS);
ctx.lineWidth = 1;
ctx.strokeStyle = '#000';
// Draw out each pixel as a rect on the target canvas, as this works around
// FireFox doing a blur as it copies from one canvas to another.
var colors = canvasCopy.getContext('2d').getImageData(x, y, PIXELS, PIXELS).data;
for (var i=0; i<PIXELS; i++) {
for (var j=0; j<PIXELS; j++) {
var offset = (j*PIXELS+i)*4; // Offset into the colors array.
ctx.fillStyle = 'rgba(' + colors[offset] + ', ' + colors[offset+1] + ', ' + colors[offset+2] + ', ' + colors[offset+3]/255.0 + ')';
ctx.fillRect(i*dx, j*dy, dx-1, dy-1);
// Box and label one selected pixel with its rgba values.
if (hex && i==PIXELS/2 && j == PIXELS/2) {
ctx.strokeRect(i*dx, j*dy, dx-1, dy-1);
hex.textContent = 'rgba('
+ colors[offset] + ', '
+ colors[offset+1] + ', '
+ colors[offset+2] + ', '
+ colors[offset+3] + ') '
+ hexify(colors[offset])
+ hexify(colors[offset+1])
+ hexify(colors[offset+2])
+ hexify(colors[offset+3]);
}
}
}
lastClientX = clientX;
lastClientY = clientY;
}
setTimeout(drawZoom, 1000/30);
}
}
function zoomFinished() {
currentImage = null;
if (hex) {
hex.textContent = '';
}
document.body.style.cursor = 'default';
ctx.canvas.parentNode.removeChild(ctx.canvas);
canvasCopy.parentNode.removeChild(canvasCopy);
document.body.removeEventListener('pointermove', zoomMove, true);
document.body.removeEventListener('pointerup', zoomFinished);
document.body.removeEventListener('pointerleave', zoomFinished);
}
var zoomables = document.body.querySelectorAll('.zoom');
for (var i=0; i<zoomables.length; i++) {
zoomables[i].addEventListener('pointerdown', zoomMouseDown);
}
}
// If loaded via HTML Imports then DOMContentLoaded will be long done.
if (document.readyState != "loading") {
onLoad();
} else {
this.addEventListener('DOMContentLoaded', onLoad);
}
})();
</script>
<style type="text/css" media="screen">
.zoom {
cursor: crosshair;
}
.zoomCanvas {
position: absolute;
width: vmin;
height: vmin;
top: 3em;
right: 1em;
z-index: -1;
}
#zoomCopy {
display: none;
}
#zoomHex {
text-shadow: 1px 1px #eee;
}
</style>

File diff suppressed because one or more lines are too long

File diff suppressed because one or more lines are too long

View File

@ -3,157 +3,6 @@
* the results.
*/
/**
* A polyfill for HTML Templates.
*
* This just adds in the content attribute, it doesn't stop scripts
* from running nor does it stop other side-effects.
*/
(function polyfillTemplates() {
if('content' in document.createElement('template')) {
return false;
}
var templates = document.getElementsByTagName('template');
for (var i=0; i<templates.length; i++) {
var content = document.createDocumentFragment();
while (templates[i].firstChild) {
content.appendChild(templates[i].firstChild);
}
templates[i].content = content;
}
})();
/**
* Enable zooming for any images with a class of 'zoom'.
*/
(function () {
var PIXELS = 20; // The number of pixels in width and height in a zoom.
var clientX = 0;
var clientY = 0;
var lastClientX = 0;
var lastClientY = 0;
var ctx = null; // The 2D canvas context of the zoom.
var currentImage = null; // The img node we are zooming for, otherwise null.
var hex = document.getElementById('zoomHex');
var canvasCopy = null;
function zoomMove(e) {
clientX = e.clientX;
clientY = e.clientY;
}
function zoomMouseDown(e) {
e.preventDefault();
// Only do zooming on the primary mouse button.
if (e.button != 0) {
return
}
currentImage = e.target;
clientX = e.clientX;
clientY = e.clientY;
lastClientX = clientX-1;
lastClientY = clientY-1;
document.body.style.cursor = 'crosshair';
canvas = document.createElement('canvas');
canvas.width = 1024;
canvas.height = 1024;
canvas.classList.add('zoomCanvas');
ctx = canvas.getContext('2d');
ctx.imageSmoothingEnabled = false;
this.parentNode.insertBefore(canvas, this);
// Copy the image over to a canvas so we can read RGBA values for each point.
if (hex) {
canvasCopy = document.createElement('canvas');
canvasCopy.width = currentImage.width;
canvasCopy.height = currentImage.height;
canvasCopy.id = 'zoomCopy';
canvasCopy.getContext('2d').drawImage(currentImage, 0, 0, currentImage.width, currentImage.height);
this.parentNode.insertBefore(canvasCopy, this);
}
document.body.addEventListener('pointermove', zoomMove, true);
document.body.addEventListener('pointerup', zoomFinished);
document.body.addEventListener('pointerleave', zoomFinished);
// Kick off the drawing.
setTimeout(drawZoom, 1);
}
function hexify(i) {
var s = i.toString(16).toUpperCase();
// Pad out to two hex digits if necessary.
if (s.length < 2) {
s = '0' + s;
}
return s;
}
function drawZoom() {
if (currentImage) {
// Only draw if the mouse has moved from the last time we drew.
if (lastClientX != clientX || lastClientY != clientY) {
ctx.clearRect(0, 0, ctx.canvas.width, ctx.canvas.height);
var x = clientX - currentImage.x;
var y = clientY - currentImage.y;
var dx = Math.floor(ctx.canvas.width/PIXELS);
var dy = Math.floor(ctx.canvas.height/PIXELS);
ctx.lineWidth = 1;
ctx.strokeStyle = '#000';
// Draw out each pixel as a rect on the target canvas, as this works around
// FireFox doing a blur as it copies from one canvas to another.
var colors = canvasCopy.getContext('2d').getImageData(x, y, PIXELS, PIXELS).data;
for (var i=0; i<PIXELS; i++) {
for (var j=0; j<PIXELS; j++) {
var offset = (j*PIXELS+i)*4; // Offset into the colors array.
ctx.fillStyle = 'rgba(' + colors[offset] + ', ' + colors[offset+1] + ', ' + colors[offset+2] + ', ' + colors[offset+3]/255.0 + ')';
ctx.fillRect(i*dx, j*dy, dx-1, dy-1);
// Box and label one selected pixel with its rgba values.
if (hex && i==PIXELS/2 && j == PIXELS/2) {
ctx.strokeRect(i*dx, j*dy, dx-1, dy-1);
hex.textContent = 'rgba('
+ colors[offset] + ', '
+ colors[offset+1] + ', '
+ colors[offset+2] + ', '
+ colors[offset+3] + ') '
+ hexify(colors[offset])
+ hexify(colors[offset+1])
+ hexify(colors[offset+2])
+ hexify(colors[offset+3]);
}
}
}
lastClientX = clientX;
lastClientY = clientY;
}
setTimeout(drawZoom, 1000/30);
}
}
function zoomFinished() {
currentImage = null;
if (hex) {
hex.textContent = '';
}
document.body.style.cursor = 'default';
ctx.canvas.parentNode.removeChild(ctx.canvas);
canvasCopy.parentNode.removeChild(canvasCopy);
document.body.removeEventListener('pointermove', zoomMove, true);
document.body.removeEventListener('pointerup', zoomFinished);
document.body.removeEventListener('pointerleave', zoomFinished);
}
this.addEventListener('DOMContentLoaded', function() {
var zoomables = document.body.querySelectorAll('.zoom');
for (var i=0; i<zoomables.length; i++) {
zoomables[i].addEventListener('pointerdown', zoomMouseDown);
}
});
})();
/**
* All the functionality is wrapped up in this anonymous closure, but we need
@ -167,180 +16,188 @@
* that are included in this workspace. That variable is used to
* populate the history list.
*/
(function(workspaceName) {
var run = document.getElementById('run');
var permalink = document.getElementById('permalink');
var embed = document.getElementById('embed');
var embedButton = document.getElementById('embedButton');
var code = document.getElementById('code');
var output = document.getElementById('output');
var stdout = document.getElementById('stdout');
var img = document.getElementById('img');
var tryHistory = document.getElementById('tryHistory');
var parser = new DOMParser();
var tryTemplate = document.getElementById('tryTemplate');
(function() {
function onLoad() {
var run = document.getElementById('run');
var permalink = document.getElementById('permalink');
var embed = document.getElementById('embed');
var embedButton = document.getElementById('embedButton');
var code = document.getElementById('code');
var output = document.getElementById('output');
var stdout = document.getElementById('stdout');
var img = document.getElementById('img');
var tryHistory = document.getElementById('tryHistory');
var parser = new DOMParser();
var tryTemplate = document.getElementById('tryTemplate');
var editor = CodeMirror.fromTextArea(code, {
theme: "default",
lineNumbers: true,
matchBrackets: true,
mode: "text/x-c++src",
indentUnit: 4,
});
var editor = CodeMirror.fromTextArea(code, {
theme: "default",
lineNumbers: true,
matchBrackets: true,
mode: "text/x-c++src",
indentUnit: 4,
});
// Match the initial textarea size.
editor.setSize(editor.defaultCharWidth() * code.cols,
editor.defaultTextHeight() * code.rows);
// Match the initial textarea size.
editor.setSize(editor.defaultCharWidth() * code.cols,
editor.defaultTextHeight() * code.rows);
function beginWait() {
document.body.classList.add('waiting');
run.disabled = true;
}
function endWait() {
document.body.classList.remove('waiting');
run.disabled = false;
}
/**
* Callback when there's an XHR error.
* @param e The callback event.
*/
function xhrError(e) {
endWait();
alert('Something bad happened: ' + e);
}
function clearOutput() {
output.textContent = "";
if (stdout) {
stdout.textContent = "";
function beginWait() {
document.body.classList.add('waiting');
run.disabled = true;
}
embed.style.display='none';
}
/**
* Called when an image in the workspace history is clicked.
*/
function historyClick() {
beginWait();
clearOutput();
var req = new XMLHttpRequest();
req.addEventListener('load', historyComplete);
req.addEventListener('error', xhrError);
req.overrideMimeType('application/json');
req.open('GET', this.getAttribute('data-try'), true);
req.send();
}
/**
* Callback for when the XHR kicked off in historyClick() returns.
*/
function historyComplete(e) {
// The response is JSON of the form:
// {
// "hash": "unique id for a try",
// "code": "source code for try"
// }
endWait();
body = JSON.parse(e.target.response);
code.value = body.code;
editor.setValue(body.code);
img.src = '/i/'+body.hash+'.png';
if (permalink) {
permalink.href = '/c/' + body.hash;
function endWait() {
document.body.classList.remove('waiting');
run.disabled = false;
}
/**
* Callback when there's an XHR error.
* @param e The callback event.
*/
function xhrError(e) {
endWait();
alert('Something bad happened: ' + e);
}
function clearOutput() {
output.textContent = "";
if (stdout) {
stdout.textContent = "";
}
embed.style.display='none';
}
/**
* Called when an image in the workspace history is clicked.
*/
function historyClick() {
beginWait();
clearOutput();
var req = new XMLHttpRequest();
req.addEventListener('load', historyComplete);
req.addEventListener('error', xhrError);
req.overrideMimeType('application/json');
req.open('GET', this.getAttribute('data-try'), true);
req.send();
}
/**
* Callback for when the XHR kicked off in historyClick() returns.
*/
function historyComplete(e) {
// The response is JSON of the form:
// {
// "hash": "unique id for a try",
// "code": "source code for try"
// }
endWait();
body = JSON.parse(e.target.response);
code.value = body.code;
editor.setValue(body.code);
img.src = '/i/'+body.hash+'.png';
if (permalink) {
permalink.href = '/c/' + body.hash;
}
}
/**
* Add the given try image to the history of a workspace.
*/
function addToHistory(hash, imgUrl) {
var clone = tryTemplate.content.cloneNode(true);
clone.querySelector('img').src = imgUrl;
clone.querySelector('.tries').setAttribute('data-try', '/json/' + hash);
tryHistory.insertBefore(clone, tryHistory.firstChild);
tryHistory.querySelector('.tries').addEventListener('click', historyClick, true);
}
/**
* Callback for when the XHR returns after attempting to run the code.
* @param e The callback event.
*/
function codeComplete(e) {
// The response is JSON of the form:
// {
// "message": "you had an error...",
// "img": "<base64 encoded image but only on success>"
// }
//
// The img is optional and only appears if there is a valid
// image to display.
endWait();
console.log(e.target.response);
body = JSON.parse(e.target.response);
output.textContent = body.message;
if (stdout) {
stdout.textContent = body.stdout;
}
if (body.hasOwnProperty('img')) {
img.src = 'data:image/png;base64,' + body.img;
} else {
img.src = '';
}
// Add the image to the history if we are on a workspace page.
if (tryHistory) {
addToHistory(body.hash, 'data:image/png;base64,' + body.img);
} else {
window.history.pushState(null, null, '/c/' + body.hash);
}
if (permalink) {
permalink.href = '/c/' + body.hash;
}
if (embed) {
var url = document.URL;
url = url.replace('/c/', '/iframe/');
embed.value = '<iframe src="' + url + '" width="740" height="550" style="border: solid #00a 5px; border-radius: 5px;"/>'
}
if (embedButton && embedButton.hasAttribute('disabled')) {
embedButton.removeAttribute('disabled');
}
}
function onSubmitCode() {
beginWait();
clearOutput();
var req = new XMLHttpRequest();
req.addEventListener('load', codeComplete);
req.addEventListener('error', xhrError);
req.overrideMimeType('application/json');
req.open('POST', '/', true);
req.setRequestHeader('content-type', 'application/json');
req.send(JSON.stringify({'code': editor.getValue(), 'name': workspaceName}));
}
run.addEventListener('click', onSubmitCode);
function onEmbedClick() {
embed.style.display='inline';
}
if (embedButton) {
embedButton.addEventListener('click', onEmbedClick);
}
// Add the images to the history if we are on a workspace page.
if (tryHistory && history) {
for (var i=0; i<history.length; i++) {
addToHistory(history[i].hash, '/i/'+history[i].hash+'.png');
}
}
}
/**
* Add the given try image to the history of a workspace.
*/
function addToHistory(hash, imgUrl) {
var clone = tryTemplate.content.cloneNode(true);
clone.querySelector('img').src = imgUrl;
clone.querySelector('.tries').setAttribute('data-try', '/json/' + hash);
tryHistory.insertBefore(clone, tryHistory.firstChild);
tryHistory.querySelector('.tries').addEventListener('click', historyClick, true);
// If loaded via HTML Imports then DOMContentLoaded will be long done.
if (document.readyState != "loading") {
onLoad();
} else {
this.addEventListener('DOMContentLoaded', onLoad);
}
/**
* Callback for when the XHR returns after attempting to run the code.
* @param e The callback event.
*/
function codeComplete(e) {
// The response is JSON of the form:
// {
// "message": "you had an error...",
// "img": "<base64 encoded image but only on success>"
// }
//
// The img is optional and only appears if there is a valid
// image to display.
endWait();
console.log(e.target.response);
body = JSON.parse(e.target.response);
output.textContent = body.message;
if (stdout) {
stdout.textContent = body.stdout;
}
if (body.hasOwnProperty('img')) {
img.src = 'data:image/png;base64,' + body.img;
} else {
img.src = '';
}
// Add the image to the history if we are on a workspace page.
if (tryHistory) {
addToHistory(body.hash, 'data:image/png;base64,' + body.img);
} else {
window.history.pushState(null, null, '/c/' + body.hash);
}
if (permalink) {
permalink.href = '/c/' + body.hash;
}
if (embed) {
var url = document.URL;
url = url.replace('/c/', '/iframe/');
embed.value = '<iframe src="' + url + '" width="740" height="550" style="border: solid #00a 5px; border-radius: 5px;"/>'
}
if (embedButton && embedButton.hasAttribute('disabled')) {
embedButton.removeAttribute('disabled');
}
}
function onSubmitCode() {
beginWait();
clearOutput();
var req = new XMLHttpRequest();
req.addEventListener('load', codeComplete);
req.addEventListener('error', xhrError);
req.overrideMimeType('application/json');
req.open('POST', '/', true);
req.setRequestHeader('content-type', 'application/json');
req.send(JSON.stringify({'code': editor.getValue(), 'name': workspaceName}));
}
run.addEventListener('click', onSubmitCode);
function onEmbedClick() {
embed.style.display='inline';
}
if (embedButton) {
embedButton.addEventListener('click', onEmbedClick);
}
// Add the images to the history if we are on a workspace page.
if (tryHistory && history) {
for (var i=0; i<history.length; i++) {
addToHistory(history[i].hash, '/i/'+history[i].hash+'.png');
}
}
})(workspaceName);
})();

View File

@ -1,8 +1,5 @@
<section id=content>
<script src="/res/js/cm/codemirror.js"></script>
<script src="/res/js/cm/clike.js"></script>
<pre>
<textarea spellcheck=false name='code' id='code' rows='15' cols='100'>{{.Code}}</textarea>
</pre>

View File

@ -0,0 +1,6 @@
<link rel='stylesheet' href='/res/css/webtry.css' type='text/css'>
<link rel='stylesheet' href='/res/css/cm/codemirror.css' type='text/css'>
<script src='/res/js/polyfill.js' type='text/javascript'></script>
<script src='/res/js/cm/codemirror.js' type='text/javascript'></script>
<script src='/res/js/cm/clike.js' type='text/javascript'></script>
<script src='/res/js/webtry.js' type='text/javascript'></script>

View File

@ -0,0 +1,2 @@
<meta charset='utf-8' />
<meta name=viewport content='width=device-width, initial-scale=1'>

View File

@ -2,17 +2,15 @@
<html>
<head>
<title>Skia WebTry</title>
<meta charset='utf-8' />
<script src="/res/js/pointerevents.min.js" type="text/javascript" charset="utf-8"></script>
<link rel='stylesheet' href='/res/css/webtry.css' type='text/css' media='screen'>
<link rel="stylesheet" href="/res/css/cm/codemirror.css" type="text/css" media="screen">
{{template "headercommon.html" .}}
<link rel='import' type='text/html' href='/res/imp/zoom.html'>
</head>
<body class=iframe>
{{template "content.html" .}}
<script type='text/javascript' charset='utf-8'>
<script type='text/javascript'>
// Not running in a workspace.
var workspaceName = '';
</script>
<script src="/res/js/webtry.js" type="text/javascript" charset="utf-8"></script>
{{template "footercommon.html" .}}
</body>
</html>

View File

@ -2,19 +2,17 @@
<html>
<head>
<title>Skia WebTry</title>
<meta charset='utf-8' />
<script src="/res/js/pointerevents.min.js" type="text/javascript" charset="utf-8"></script>
<link rel="stylesheet" href="/res/css/webtry.css" type="text/css" media="screen">
<link rel="stylesheet" href="/res/css/cm/codemirror.css" type="text/css" media="screen">
{{template "headercommon.html" .}}
<link rel='import' type='text/html' href='/res/imp/zoom.html'>
</head>
<body>
{{template "titlebar.html" .}}
{{template "content.html" .}}
<script type='text/javascript' charset='utf-8'>
<script type='text/javascript'>
// Not running in a workspace.
var workspaceName = "";
var workspaceName = '';
</script>
<script src="/res/js/webtry.js" type="text/javascript" charset="utf-8"></script>
{{template "footercommon.html" .}}
</body>
</html>

View File

@ -3,22 +3,23 @@
<head>
<title>Recent SkFiddles</title>
<meta charset='utf-8' />
<link rel="stylesheet" href="/res/css/webtry.css" type="text/css" media="screen">
{{template "headercommon.html" .}}
</head>
<body>
{{template "titlebar.html" .}}
<section id=content>
<h1>Recent Activity</h1>
<section>
{{range .Tries}}
<div class=tries>
<h2><a href="/c/{{.Hash}}">{{.CreateTS}}</a></h2>
<a href="/c/{{.Hash}}">
<img width=128 height=128 src="/i/{{.Hash}}.png">
</a>
</div>
{{end}}
</section>
<h1>Recent Activity</h1>
<section>
{{range .Tries}}
<div class=tries>
<h2><a href="/c/{{.Hash}}">{{.CreateTS}}</a></h2>
<a href="/c/{{.Hash}}">
<img width=128 height=128 src="/i/{{.Hash}}.png">
</a>
</div>
{{end}}
</section>
</section>
{{template "footercommon.html" .}}
</body>
</html>

View File

@ -2,15 +2,13 @@
<html>
<head>
<title>Workspace</title>
<meta charset='utf-8' />
<script src="/res/js/pointerevents.min.js" type="text/javascript" charset="utf-8"></script>
<link rel='stylesheet' href='/res/css/webtry.css' type='text/css' media='screen'>
<link rel="stylesheet" href="/res/css/cm/codemirror.css" type="text/css" media="screen">
{{template "headercommon.html" .}}
<link rel='import' type='text/html' href='/res/imp/zoom.html'>
</head>
<body>
<template id=tryTemplate>
<div class=tries data-try="">
<img width=64 height=64 src="">
<div class=tries data-try=''>
<img width=64 height=64 src=''>
</div>
</template>
{{template "titlebar.html" .}}
@ -20,22 +18,22 @@
<section id=tryHistory>
</section>
<script type="text/javascript" charset="utf-8">
<script type='text/javascript'>
var history = {{.Tries}};
</script>
<script type='text/javascript' charset='utf-8'>
<script type='text/javascript'>
// Set the workspace name so run.js also updates the history.
var workspaceName = "{{.Name}}";
var workspaceName = '{{.Name}}';
</script>
<script src="/res/js/webtry.js" type="text/javascript" charset="utf-8"></script>
{{else}}
<section id=content>
<h1>Create</h1>
Create a new workspace:
<form action="." method="POST" accept-charset="utf-8">
<p><input type="submit" value="Create"></p>
<form action='.' method='POST'>
<p><input type='submit' value='Create'></p>
</form>
</section>
{{end}}
{{template "footercommon.html" .}}
</body>
</html>

View File

@ -140,6 +140,8 @@ func init() {
filepath.Join(cwd, "templates/index.html"),
filepath.Join(cwd, "templates/titlebar.html"),
filepath.Join(cwd, "templates/content.html"),
filepath.Join(cwd, "templates/headercommon.html"),
filepath.Join(cwd, "templates/footercommon.html"),
)
if err != nil {
panic(err)
@ -147,6 +149,8 @@ func init() {
iframeTemplate, err = htemplate.ParseFiles(
filepath.Join(cwd, "templates/iframe.html"),
filepath.Join(cwd, "templates/content.html"),
filepath.Join(cwd, "templates/headercommon.html"),
filepath.Join(cwd, "templates/footercommon.html"),
)
if err != nil {
panic(err)
@ -154,6 +158,8 @@ func init() {
recentTemplate, err = htemplate.ParseFiles(
filepath.Join(cwd, "templates/recent.html"),
filepath.Join(cwd, "templates/titlebar.html"),
filepath.Join(cwd, "templates/headercommon.html"),
filepath.Join(cwd, "templates/footercommon.html"),
)
if err != nil {
panic(err)
@ -162,6 +168,8 @@ func init() {
filepath.Join(cwd, "templates/workspace.html"),
filepath.Join(cwd, "templates/titlebar.html"),
filepath.Join(cwd, "templates/content.html"),
filepath.Join(cwd, "templates/headercommon.html"),
filepath.Join(cwd, "templates/footercommon.html"),
)
if err != nil {
panic(err)