forked from cory/tildefriends
Merge the editor and the terminal view. I think it will be nicer to work with them always side-by-side.
git-svn-id: https://www.unprompted.com/svn/projects/tildefriends/trunk@3380 ed5197a5-7fde-0310-b194-c3ffbd925b24
This commit is contained in:
210
core/client.js
210
core/client.js
@ -8,8 +8,30 @@ var gSendKeyEvents = false;
|
||||
var gSendDeviceOrientationEvents = false;
|
||||
var gGeolocatorWatch;
|
||||
|
||||
var gEditor;
|
||||
var gBackup;
|
||||
|
||||
var kMaxCommandHistory = 16;
|
||||
|
||||
window.addEventListener("keydown", function(event) {
|
||||
if (event.keyCode == 69 && event.altKey) {
|
||||
if (!editing()) {
|
||||
edit();
|
||||
event.preventDefault();
|
||||
}
|
||||
} else if (event.keyCode == 83 && (event.altKey || event.ctrlKey)) {
|
||||
if (editing()) {
|
||||
save();
|
||||
event.preventDefault();
|
||||
}
|
||||
} else if (event.keyCode == 66 && event.altKey) {
|
||||
if (editing()) {
|
||||
closeEditor();
|
||||
event.preventDefault();
|
||||
}
|
||||
}
|
||||
});
|
||||
|
||||
function keydown(event) {
|
||||
if (event.keyCode == 13) {
|
||||
gCommandHistory.push(document.getElementById("input").value);
|
||||
@ -32,9 +54,181 @@ function keydown(event) {
|
||||
input.value = gCommandHistory.shift();
|
||||
event.preventDefault();
|
||||
}
|
||||
} else if (event.keyCode == 69 && event.altKey) {
|
||||
window.location.href = url() + "/edit";
|
||||
event.preventDefault();
|
||||
}
|
||||
}
|
||||
|
||||
function ensureLoaded(nodes, callback) {
|
||||
if (!nodes.length) {
|
||||
callback();
|
||||
return;
|
||||
}
|
||||
|
||||
var search = nodes.shift();
|
||||
var head = document.head;
|
||||
var found = false;
|
||||
for (var i = 0; i < head.childNodes.length; i++) {
|
||||
if (head.childNodes[i].tagName == search.tagName) {
|
||||
var match = true;
|
||||
for (var attribute in search.attributes) {
|
||||
if (head.childNodes[i].attributes[attribute].value != search.attributes[attribute]) {
|
||||
match = false;
|
||||
}
|
||||
}
|
||||
if (match) {
|
||||
found = true;
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
if (found) {
|
||||
ensureLoaded(nodes, callback);
|
||||
} else {
|
||||
var node = document.createElement(search.tagName);
|
||||
node.onreadystatechange = node.onload = function() {
|
||||
ensureLoaded(nodes, callback);
|
||||
};
|
||||
for (var attribute in search.attributes) {
|
||||
node.setAttribute(attribute, search.attributes[attribute]);
|
||||
}
|
||||
head.insertBefore(node, head.firstChild);
|
||||
}
|
||||
}
|
||||
|
||||
function editing() {
|
||||
return document.getElementById("editPane").style.display != 'none';
|
||||
}
|
||||
|
||||
function edit() {
|
||||
if (editing()) {
|
||||
return;
|
||||
}
|
||||
|
||||
ensureLoaded([
|
||||
{tagName: "script", attributes: {src: "https://cdnjs.cloudflare.com/ajax/libs/codemirror/5.12.0/codemirror.min.js"}},
|
||||
{tagName: "link", attributes: {rel: "stylesheet", href: "https://cdnjs.cloudflare.com/ajax/libs/codemirror/5.12.0/theme/base16-dark.min.css"}},
|
||||
{tagName: "link", attributes: {rel: "stylesheet", href: "https://cdnjs.cloudflare.com/ajax/libs/codemirror/5.12.0/addon/search/matchesonscrollbar.min.css"}},
|
||||
{tagName: "link", attributes: {rel: "stylesheet", href: "https://cdnjs.cloudflare.com/ajax/libs/codemirror/5.12.0/addon/dialog/dialog.min.css"}},
|
||||
{tagName: "link", attributes: {rel: "stylesheet", href: "https://cdnjs.cloudflare.com/ajax/libs/codemirror/5.12.0/codemirror.min.css"}},
|
||||
{tagName: "script", attributes: {src: "https://cdnjs.cloudflare.com/ajax/libs/codemirror/5.12.0/addon/edit/trailingspace.min.js"}},
|
||||
{tagName: "script", attributes: {src: "https://cdnjs.cloudflare.com/ajax/libs/codemirror/5.12.0/addon/dialog/dialog.min.js"}},
|
||||
{tagName: "script", attributes: {src: "https://cdnjs.cloudflare.com/ajax/libs/codemirror/5.12.0/addon/search/search.min.js"}},
|
||||
{tagName: "script", attributes: {src: "https://cdnjs.cloudflare.com/ajax/libs/codemirror/5.12.0/addon/search/searchcursor.min.js"}},
|
||||
{tagName: "script", attributes: {src: "https://cdnjs.cloudflare.com/ajax/libs/codemirror/5.12.0/addon/search/jump-to-line.min.js"}},
|
||||
{tagName: "script", attributes: {src: "https://cdnjs.cloudflare.com/ajax/libs/codemirror/5.12.0/addon/search/matchesonscrollbar.min.js"}},
|
||||
{tagName: "script", attributes: {src: "https://cdnjs.cloudflare.com/ajax/libs/codemirror/5.12.0/addon/scroll/annotatescrollbar.min.js"}},
|
||||
{tagName: "script", attributes: {src: "https://cdnjs.cloudflare.com/ajax/libs/codemirror/5.12.0/mode/javascript/javascript.min.js"}},
|
||||
], function() {
|
||||
load();
|
||||
});
|
||||
|
||||
}
|
||||
|
||||
function load() {
|
||||
var request = new XMLHttpRequest();
|
||||
request.addEventListener("loadend", function() {
|
||||
if (request.status == 200) {
|
||||
document.getElementById("editPane").style.display = 'flex';
|
||||
if (!gEditor) {
|
||||
gEditor = CodeMirror.fromTextArea(document.getElementById("editor"), {
|
||||
'theme': 'base16-dark',
|
||||
'lineNumbers': true,
|
||||
'tabSize': 4,
|
||||
'indentUnit': 4,
|
||||
'indentWithTabs': true,
|
||||
'showTrailingSpace': true,
|
||||
});
|
||||
}
|
||||
gEditor.setValue(request.responseText);
|
||||
gEditor.focus();
|
||||
gBackup = request.responseText;
|
||||
}
|
||||
});
|
||||
request.addEventListener("error", function() {
|
||||
alert("Error loading source.");
|
||||
closeEditor();
|
||||
});
|
||||
request.addEventListener("timeout", function() {
|
||||
alert("Timed out loading source.");
|
||||
closeEditor();
|
||||
});
|
||||
request.addEventListener("abort", function() {
|
||||
alert("Loading source aborted.");
|
||||
closeEditor();
|
||||
});
|
||||
request.open("GET", url() + "/view");
|
||||
request.send();
|
||||
}
|
||||
|
||||
function closeEditor() {
|
||||
document.getElementById("editPane").style.display = 'none';
|
||||
}
|
||||
|
||||
function revert() {
|
||||
gEditor.setValue(gBackup);
|
||||
}
|
||||
|
||||
function explodePath() {
|
||||
return /^\/~([^\/]+)\/([^\/]+)(.*)/.exec(window.location.pathname);
|
||||
}
|
||||
|
||||
function packageOwner() {
|
||||
return explodePath()[1];
|
||||
}
|
||||
|
||||
function packageName() {
|
||||
return explodePath()[2];
|
||||
}
|
||||
|
||||
function save(newName) {
|
||||
document.getElementById("save").disabled = true;
|
||||
document.getElementById("saveAs").disabled = true;
|
||||
|
||||
var contents = gEditor.getValue();
|
||||
var run = document.getElementById("run").checked;
|
||||
|
||||
var request = new XMLHttpRequest();
|
||||
|
||||
var always = function() {
|
||||
document.getElementById("save").disabled = false;
|
||||
document.getElementById("saveAs").disabled = false;
|
||||
};
|
||||
|
||||
request.addEventListener("error", function() {
|
||||
alert("Error saving: " + request.responseText);
|
||||
always();
|
||||
});
|
||||
request.addEventListener("loadend", function() {
|
||||
if (request.status == 200) {
|
||||
gBackup = contents;
|
||||
if (run) {
|
||||
if (newName) {
|
||||
window.location.href = "/~" + packageOwner() + "/" + newName + hash();
|
||||
} else {
|
||||
reconnect();
|
||||
}
|
||||
}
|
||||
} else {
|
||||
alert("Unable to save: " + request.responseText);
|
||||
}
|
||||
always();
|
||||
});
|
||||
request.addEventListener("timeout", function() {
|
||||
alert("Timed out saving: " + request.responseText);
|
||||
always();
|
||||
});
|
||||
request.addEventListener("abort", function() {
|
||||
alert("Save aborted: " + request.responseText);
|
||||
always();
|
||||
});
|
||||
request.open("POST", newName ? newName + "/save" : packageName() + "/save", true);
|
||||
request.setRequestHeader("Content-Type", "text/plain");
|
||||
request.send(contents);
|
||||
}
|
||||
|
||||
function saveAs() {
|
||||
var newName = prompt("Save as:", packageName());
|
||||
if (newName) {
|
||||
save(newName);
|
||||
}
|
||||
}
|
||||
|
||||
@ -553,6 +747,16 @@ function submitButton() {
|
||||
send({event: "submit", value: data});
|
||||
}
|
||||
|
||||
function reconnect() {
|
||||
let oldSocket = gSocket;
|
||||
gSocket = null
|
||||
oldSocket.onclose = function() {}
|
||||
oldSocket.onmessage = function() {}
|
||||
oldSocket.close();
|
||||
split(document.getElementById("terminals"), [{name: "terminal_"}]);
|
||||
connectSocket();
|
||||
}
|
||||
|
||||
function connectSocket() {
|
||||
if (!gSocket || gSocket.readyState == gSocket.CLOSED) {
|
||||
gSocket = new WebSocket(
|
||||
|
Reference in New Issue
Block a user