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:
parent
99bd7d8174
commit
015c08e5ca
@ -89,5 +89,6 @@ Do this step only once, but only after running webtry_setup.sh the first time
|
|||||||
Third Party Code
|
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.
|
||||||
|
|
||||||
|
3
experimental/webtry/poly/.bowerrc
Normal file
3
experimental/webtry/poly/.bowerrc
Normal file
@ -0,0 +1,3 @@
|
|||||||
|
{
|
||||||
|
"directory": "../../../out/bower"
|
||||||
|
}
|
64
experimental/webtry/poly/Gruntfile.js
Normal file
64
experimental/webtry/poly/Gruntfile.js
Normal 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']);
|
||||||
|
|
||||||
|
};
|
18
experimental/webtry/poly/README.md
Normal file
18
experimental/webtry/poly/README.md
Normal 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
|
22
experimental/webtry/poly/bower.json
Normal file
22
experimental/webtry/poly/bower.json
Normal 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"
|
||||||
|
}
|
||||||
|
}
|
17
experimental/webtry/poly/package.json
Normal file
17
experimental/webtry/poly/package.json
Normal 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"
|
||||||
|
}
|
||||||
|
}
|
@ -9,26 +9,6 @@ img {
|
|||||||
background-image: url("data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAABAAAAAQCAAAAAA6mKC9AAAAAXNSR0IArs4c6QAAAAJiS0dEAP+Hj8y/AAAACXBIWXMAAA7DAAAOwwHHb6hkAAAAB3RJTUUH3gUBEi4DGRAQYgAAAB1JREFUGNNjfMoAAVJQmokBDdBHgPE/lPFsYN0BABdaAwN6tehMAAAAAElFTkSuQmCC");
|
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 {
|
h1 {
|
||||||
font-size: 18px;
|
font-size: 18px;
|
||||||
|
169
experimental/webtry/res/imp/zoom.html
Normal file
169
experimental/webtry/res/imp/zoom.html
Normal 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>
|
||||||
|
|
28
experimental/webtry/res/js/pointerevents.min.js
vendored
28
experimental/webtry/res/js/pointerevents.min.js
vendored
File diff suppressed because one or more lines are too long
3
experimental/webtry/res/js/polyfill.js
Normal file
3
experimental/webtry/res/js/polyfill.js
Normal file
File diff suppressed because one or more lines are too long
@ -3,157 +3,6 @@
|
|||||||
* the results.
|
* 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
|
* 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
|
* that are included in this workspace. That variable is used to
|
||||||
* populate the history list.
|
* populate the history list.
|
||||||
*/
|
*/
|
||||||
(function(workspaceName) {
|
(function() {
|
||||||
var run = document.getElementById('run');
|
function onLoad() {
|
||||||
var permalink = document.getElementById('permalink');
|
var run = document.getElementById('run');
|
||||||
var embed = document.getElementById('embed');
|
var permalink = document.getElementById('permalink');
|
||||||
var embedButton = document.getElementById('embedButton');
|
var embed = document.getElementById('embed');
|
||||||
var code = document.getElementById('code');
|
var embedButton = document.getElementById('embedButton');
|
||||||
var output = document.getElementById('output');
|
var code = document.getElementById('code');
|
||||||
var stdout = document.getElementById('stdout');
|
var output = document.getElementById('output');
|
||||||
var img = document.getElementById('img');
|
var stdout = document.getElementById('stdout');
|
||||||
var tryHistory = document.getElementById('tryHistory');
|
var img = document.getElementById('img');
|
||||||
var parser = new DOMParser();
|
var tryHistory = document.getElementById('tryHistory');
|
||||||
var tryTemplate = document.getElementById('tryTemplate');
|
var parser = new DOMParser();
|
||||||
|
var tryTemplate = document.getElementById('tryTemplate');
|
||||||
|
|
||||||
var editor = CodeMirror.fromTextArea(code, {
|
var editor = CodeMirror.fromTextArea(code, {
|
||||||
theme: "default",
|
theme: "default",
|
||||||
lineNumbers: true,
|
lineNumbers: true,
|
||||||
matchBrackets: true,
|
matchBrackets: true,
|
||||||
mode: "text/x-c++src",
|
mode: "text/x-c++src",
|
||||||
indentUnit: 4,
|
indentUnit: 4,
|
||||||
});
|
});
|
||||||
|
|
||||||
// Match the initial textarea size.
|
// Match the initial textarea size.
|
||||||
editor.setSize(editor.defaultCharWidth() * code.cols,
|
editor.setSize(editor.defaultCharWidth() * code.cols,
|
||||||
editor.defaultTextHeight() * code.rows);
|
editor.defaultTextHeight() * code.rows);
|
||||||
|
|
||||||
function beginWait() {
|
function beginWait() {
|
||||||
document.body.classList.add('waiting');
|
document.body.classList.add('waiting');
|
||||||
run.disabled = true;
|
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 = "";
|
|
||||||
}
|
}
|
||||||
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();
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
/**
|
function endWait() {
|
||||||
* Callback for when the XHR kicked off in historyClick() returns.
|
document.body.classList.remove('waiting');
|
||||||
*/
|
run.disabled = false;
|
||||||
function historyComplete(e) {
|
}
|
||||||
// The response is JSON of the form:
|
|
||||||
// {
|
|
||||||
// "hash": "unique id for a try",
|
/**
|
||||||
// "code": "source code for try"
|
* Callback when there's an XHR error.
|
||||||
// }
|
* @param e The callback event.
|
||||||
endWait();
|
*/
|
||||||
body = JSON.parse(e.target.response);
|
function xhrError(e) {
|
||||||
code.value = body.code;
|
endWait();
|
||||||
editor.setValue(body.code);
|
alert('Something bad happened: ' + e);
|
||||||
img.src = '/i/'+body.hash+'.png';
|
}
|
||||||
if (permalink) {
|
|
||||||
permalink.href = '/c/' + body.hash;
|
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');
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// If loaded via HTML Imports then DOMContentLoaded will be long done.
|
||||||
/**
|
if (document.readyState != "loading") {
|
||||||
* Add the given try image to the history of a workspace.
|
onLoad();
|
||||||
*/
|
} else {
|
||||||
function addToHistory(hash, imgUrl) {
|
this.addEventListener('DOMContentLoaded', onLoad);
|
||||||
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');
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
})(workspaceName);
|
|
||||||
|
@ -1,8 +1,5 @@
|
|||||||
|
|
||||||
<section id=content>
|
<section id=content>
|
||||||
<script src="/res/js/cm/codemirror.js"></script>
|
|
||||||
<script src="/res/js/cm/clike.js"></script>
|
|
||||||
|
|
||||||
<pre>
|
<pre>
|
||||||
<textarea spellcheck=false name='code' id='code' rows='15' cols='100'>{{.Code}}</textarea>
|
<textarea spellcheck=false name='code' id='code' rows='15' cols='100'>{{.Code}}</textarea>
|
||||||
</pre>
|
</pre>
|
||||||
|
6
experimental/webtry/templates/footercommon.html
Normal file
6
experimental/webtry/templates/footercommon.html
Normal 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>
|
2
experimental/webtry/templates/headercommon.html
Normal file
2
experimental/webtry/templates/headercommon.html
Normal file
@ -0,0 +1,2 @@
|
|||||||
|
<meta charset='utf-8' />
|
||||||
|
<meta name=viewport content='width=device-width, initial-scale=1'>
|
@ -2,17 +2,15 @@
|
|||||||
<html>
|
<html>
|
||||||
<head>
|
<head>
|
||||||
<title>Skia WebTry</title>
|
<title>Skia WebTry</title>
|
||||||
<meta charset='utf-8' />
|
{{template "headercommon.html" .}}
|
||||||
<script src="/res/js/pointerevents.min.js" type="text/javascript" charset="utf-8"></script>
|
<link rel='import' type='text/html' href='/res/imp/zoom.html'>
|
||||||
<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">
|
|
||||||
</head>
|
</head>
|
||||||
<body class=iframe>
|
<body class=iframe>
|
||||||
{{template "content.html" .}}
|
{{template "content.html" .}}
|
||||||
<script type='text/javascript' charset='utf-8'>
|
<script type='text/javascript'>
|
||||||
// Not running in a workspace.
|
// Not running in a workspace.
|
||||||
var workspaceName = '';
|
var workspaceName = '';
|
||||||
</script>
|
</script>
|
||||||
<script src="/res/js/webtry.js" type="text/javascript" charset="utf-8"></script>
|
{{template "footercommon.html" .}}
|
||||||
</body>
|
</body>
|
||||||
</html>
|
</html>
|
||||||
|
@ -2,19 +2,17 @@
|
|||||||
<html>
|
<html>
|
||||||
<head>
|
<head>
|
||||||
<title>Skia WebTry</title>
|
<title>Skia WebTry</title>
|
||||||
<meta charset='utf-8' />
|
{{template "headercommon.html" .}}
|
||||||
<script src="/res/js/pointerevents.min.js" type="text/javascript" charset="utf-8"></script>
|
<link rel='import' type='text/html' href='/res/imp/zoom.html'>
|
||||||
<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">
|
|
||||||
</head>
|
</head>
|
||||||
<body>
|
<body>
|
||||||
{{template "titlebar.html" .}}
|
{{template "titlebar.html" .}}
|
||||||
{{template "content.html" .}}
|
{{template "content.html" .}}
|
||||||
|
|
||||||
<script type='text/javascript' charset='utf-8'>
|
<script type='text/javascript'>
|
||||||
// Not running in a workspace.
|
// Not running in a workspace.
|
||||||
var workspaceName = "";
|
var workspaceName = '';
|
||||||
</script>
|
</script>
|
||||||
<script src="/res/js/webtry.js" type="text/javascript" charset="utf-8"></script>
|
{{template "footercommon.html" .}}
|
||||||
</body>
|
</body>
|
||||||
</html>
|
</html>
|
||||||
|
@ -3,22 +3,23 @@
|
|||||||
<head>
|
<head>
|
||||||
<title>Recent SkFiddles</title>
|
<title>Recent SkFiddles</title>
|
||||||
<meta charset='utf-8' />
|
<meta charset='utf-8' />
|
||||||
<link rel="stylesheet" href="/res/css/webtry.css" type="text/css" media="screen">
|
{{template "headercommon.html" .}}
|
||||||
</head>
|
</head>
|
||||||
<body>
|
<body>
|
||||||
{{template "titlebar.html" .}}
|
{{template "titlebar.html" .}}
|
||||||
<section id=content>
|
<section id=content>
|
||||||
<h1>Recent Activity</h1>
|
<h1>Recent Activity</h1>
|
||||||
<section>
|
<section>
|
||||||
{{range .Tries}}
|
{{range .Tries}}
|
||||||
<div class=tries>
|
<div class=tries>
|
||||||
<h2><a href="/c/{{.Hash}}">{{.CreateTS}}</a></h2>
|
<h2><a href="/c/{{.Hash}}">{{.CreateTS}}</a></h2>
|
||||||
<a href="/c/{{.Hash}}">
|
<a href="/c/{{.Hash}}">
|
||||||
<img width=128 height=128 src="/i/{{.Hash}}.png">
|
<img width=128 height=128 src="/i/{{.Hash}}.png">
|
||||||
</a>
|
</a>
|
||||||
</div>
|
</div>
|
||||||
{{end}}
|
{{end}}
|
||||||
</section>
|
</section>
|
||||||
</section>
|
</section>
|
||||||
|
{{template "footercommon.html" .}}
|
||||||
</body>
|
</body>
|
||||||
</html>
|
</html>
|
||||||
|
@ -2,15 +2,13 @@
|
|||||||
<html>
|
<html>
|
||||||
<head>
|
<head>
|
||||||
<title>Workspace</title>
|
<title>Workspace</title>
|
||||||
<meta charset='utf-8' />
|
{{template "headercommon.html" .}}
|
||||||
<script src="/res/js/pointerevents.min.js" type="text/javascript" charset="utf-8"></script>
|
<link rel='import' type='text/html' href='/res/imp/zoom.html'>
|
||||||
<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">
|
|
||||||
</head>
|
</head>
|
||||||
<body>
|
<body>
|
||||||
<template id=tryTemplate>
|
<template id=tryTemplate>
|
||||||
<div class=tries data-try="">
|
<div class=tries data-try=''>
|
||||||
<img width=64 height=64 src="">
|
<img width=64 height=64 src=''>
|
||||||
</div>
|
</div>
|
||||||
</template>
|
</template>
|
||||||
{{template "titlebar.html" .}}
|
{{template "titlebar.html" .}}
|
||||||
@ -20,22 +18,22 @@
|
|||||||
<section id=tryHistory>
|
<section id=tryHistory>
|
||||||
</section>
|
</section>
|
||||||
|
|
||||||
<script type="text/javascript" charset="utf-8">
|
<script type='text/javascript'>
|
||||||
var history = {{.Tries}};
|
var history = {{.Tries}};
|
||||||
</script>
|
</script>
|
||||||
<script type='text/javascript' charset='utf-8'>
|
<script type='text/javascript'>
|
||||||
// Set the workspace name so run.js also updates the history.
|
// Set the workspace name so run.js also updates the history.
|
||||||
var workspaceName = "{{.Name}}";
|
var workspaceName = '{{.Name}}';
|
||||||
</script>
|
</script>
|
||||||
<script src="/res/js/webtry.js" type="text/javascript" charset="utf-8"></script>
|
|
||||||
{{else}}
|
{{else}}
|
||||||
<section id=content>
|
<section id=content>
|
||||||
<h1>Create</h1>
|
<h1>Create</h1>
|
||||||
Create a new workspace:
|
Create a new workspace:
|
||||||
<form action="." method="POST" accept-charset="utf-8">
|
<form action='.' method='POST'>
|
||||||
<p><input type="submit" value="Create"></p>
|
<p><input type='submit' value='Create'></p>
|
||||||
</form>
|
</form>
|
||||||
</section>
|
</section>
|
||||||
{{end}}
|
{{end}}
|
||||||
|
{{template "footercommon.html" .}}
|
||||||
</body>
|
</body>
|
||||||
</html>
|
</html>
|
||||||
|
@ -140,6 +140,8 @@ func init() {
|
|||||||
filepath.Join(cwd, "templates/index.html"),
|
filepath.Join(cwd, "templates/index.html"),
|
||||||
filepath.Join(cwd, "templates/titlebar.html"),
|
filepath.Join(cwd, "templates/titlebar.html"),
|
||||||
filepath.Join(cwd, "templates/content.html"),
|
filepath.Join(cwd, "templates/content.html"),
|
||||||
|
filepath.Join(cwd, "templates/headercommon.html"),
|
||||||
|
filepath.Join(cwd, "templates/footercommon.html"),
|
||||||
)
|
)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
panic(err)
|
panic(err)
|
||||||
@ -147,6 +149,8 @@ func init() {
|
|||||||
iframeTemplate, err = htemplate.ParseFiles(
|
iframeTemplate, err = htemplate.ParseFiles(
|
||||||
filepath.Join(cwd, "templates/iframe.html"),
|
filepath.Join(cwd, "templates/iframe.html"),
|
||||||
filepath.Join(cwd, "templates/content.html"),
|
filepath.Join(cwd, "templates/content.html"),
|
||||||
|
filepath.Join(cwd, "templates/headercommon.html"),
|
||||||
|
filepath.Join(cwd, "templates/footercommon.html"),
|
||||||
)
|
)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
panic(err)
|
panic(err)
|
||||||
@ -154,6 +158,8 @@ func init() {
|
|||||||
recentTemplate, err = htemplate.ParseFiles(
|
recentTemplate, err = htemplate.ParseFiles(
|
||||||
filepath.Join(cwd, "templates/recent.html"),
|
filepath.Join(cwd, "templates/recent.html"),
|
||||||
filepath.Join(cwd, "templates/titlebar.html"),
|
filepath.Join(cwd, "templates/titlebar.html"),
|
||||||
|
filepath.Join(cwd, "templates/headercommon.html"),
|
||||||
|
filepath.Join(cwd, "templates/footercommon.html"),
|
||||||
)
|
)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
panic(err)
|
panic(err)
|
||||||
@ -162,6 +168,8 @@ func init() {
|
|||||||
filepath.Join(cwd, "templates/workspace.html"),
|
filepath.Join(cwd, "templates/workspace.html"),
|
||||||
filepath.Join(cwd, "templates/titlebar.html"),
|
filepath.Join(cwd, "templates/titlebar.html"),
|
||||||
filepath.Join(cwd, "templates/content.html"),
|
filepath.Join(cwd, "templates/content.html"),
|
||||||
|
filepath.Join(cwd, "templates/headercommon.html"),
|
||||||
|
filepath.Join(cwd, "templates/footercommon.html"),
|
||||||
)
|
)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
panic(err)
|
panic(err)
|
||||||
|
Loading…
Reference in New Issue
Block a user