| Index: experimental/webtry/res/js/webtry.js
|
| diff --git a/experimental/webtry/res/js/webtry.js b/experimental/webtry/res/js/webtry.js
|
| index f0a5bb5327213383c051cdf4ff42c9a7aad46705..b1fe3dd8065228b162cb400361d35dec8644d343 100644
|
| --- a/experimental/webtry/res/js/webtry.js
|
| +++ b/experimental/webtry/res/js/webtry.js
|
| @@ -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,
|
| + });
|
| +
|
| + // 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;
|
| + }
|
|
|
| - 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);
|
| + function endWait() {
|
| + document.body.classList.remove('waiting');
|
| + run.disabled = false;
|
| + }
|
|
|
| - function beginWait() {
|
| - document.body.classList.add('waiting');
|
| - run.disabled = true;
|
| - }
|
|
|
| + /**
|
| + * Callback when there's an XHR error.
|
| + * @param e The callback event.
|
| + */
|
| + function xhrError(e) {
|
| + endWait();
|
| + alert('Something bad happened: ' + e);
|
| + }
|
|
|
| - function endWait() {
|
| - document.body.classList.remove('waiting');
|
| - run.disabled = false;
|
| - }
|
| + 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 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 = "";
|
| + /**
|
| + * 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;
|
| + }
|
| }
|
| - 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);
|
| }
|
| - }
|
|
|
|
|
| - /**
|
| - * 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');
|
| + }
|
| + }
|
|
|
|
|
| - /**
|
| - * 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;"/>'
|
| + 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}));
|
| }
|
| - if (embedButton && embedButton.hasAttribute('disabled')) {
|
| - embedButton.removeAttribute('disabled');
|
| - }
|
| - }
|
| + run.addEventListener('click', onSubmitCode);
|
|
|
|
|
| - 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';
|
| + }
|
|
|
| - function onEmbedClick() {
|
| - embed.style.display='inline';
|
| - }
|
| + if (embedButton) {
|
| + embedButton.addEventListener('click', onEmbedClick);
|
| + }
|
|
|
| - 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 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") {
|
| + onLoad();
|
| + } else {
|
| + this.addEventListener('DOMContentLoaded', onLoad);
|
| }
|
|
|
| -})(workspaceName);
|
| +})();
|
|
|