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:
		
										
											Binary file not shown.
										
									
								
							| Before Width: | Height: | Size: 1.8 KiB | 
							
								
								
									
										210
									
								
								core/client.js
									
									
									
									
									
								
							
							
						
						
									
										210
									
								
								core/client.js
									
									
									
									
									
								
							| @@ -8,8 +8,30 @@ var gSendKeyEvents = false; | |||||||
| var gSendDeviceOrientationEvents = false; | var gSendDeviceOrientationEvents = false; | ||||||
| var gGeolocatorWatch; | var gGeolocatorWatch; | ||||||
|  |  | ||||||
|  | var gEditor; | ||||||
|  | var gBackup; | ||||||
|  |  | ||||||
| var kMaxCommandHistory = 16; | 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) { | function keydown(event) { | ||||||
| 	if (event.keyCode == 13) { | 	if (event.keyCode == 13) { | ||||||
| 		gCommandHistory.push(document.getElementById("input").value); | 		gCommandHistory.push(document.getElementById("input").value); | ||||||
| @@ -32,9 +54,181 @@ function keydown(event) { | |||||||
| 			input.value = gCommandHistory.shift(); | 			input.value = gCommandHistory.shift(); | ||||||
| 			event.preventDefault(); | 			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}); | 	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() { | function connectSocket() { | ||||||
| 	if (!gSocket || gSocket.readyState == gSocket.CLOSED) { | 	if (!gSocket || gSocket.readyState == gSocket.CLOSED) { | ||||||
| 		gSocket = new WebSocket( | 		gSocket = new WebSocket( | ||||||
|   | |||||||
| @@ -1,34 +0,0 @@ | |||||||
| <!DOCTYPE html> |  | ||||||
| <html> |  | ||||||
| 	<head> |  | ||||||
| 		<title>Web Terminal</title> |  | ||||||
| 		<script src="https://cdnjs.cloudflare.com/ajax/libs/codemirror/5.12.0/codemirror.min.js"></script> |  | ||||||
| 		<script src="https://cdnjs.cloudflare.com/ajax/libs/codemirror/5.12.0/addon/edit/trailingspace.min.js"></script> |  | ||||||
| 		<script src="https://cdnjs.cloudflare.com/ajax/libs/codemirror/5.12.0/addon/dialog/dialog.min.js"></script> |  | ||||||
| 		<script src="https://cdnjs.cloudflare.com/ajax/libs/codemirror/5.12.0/addon/search/search.min.js"></script> |  | ||||||
| 		<script src="https://cdnjs.cloudflare.com/ajax/libs/codemirror/5.12.0/addon/search/searchcursor.min.js"></script> |  | ||||||
| 		<script src="https://cdnjs.cloudflare.com/ajax/libs/codemirror/5.12.0/addon/search/jump-to-line.min.js"></script> |  | ||||||
| 		<script src="https://cdnjs.cloudflare.com/ajax/libs/codemirror/5.12.0/addon/search/matchesonscrollbar.min.js"></script> |  | ||||||
| 		<script src="https://cdnjs.cloudflare.com/ajax/libs/codemirror/5.12.0/addon/scroll/annotatescrollbar.min.js"></script> |  | ||||||
| 		<link rel="stylesheet" href="https://cdnjs.cloudflare.com/ajax/libs/codemirror/5.12.0/codemirror.min.css"> |  | ||||||
| 		<link rel="stylesheet" href="https://cdnjs.cloudflare.com/ajax/libs/codemirror/5.12.0/addon/dialog/dialog.min.css"> |  | ||||||
| 		<link rel="stylesheet" href="https://cdnjs.cloudflare.com/ajax/libs/codemirror/5.12.0/addon/search/matchesonscrollbar.min.css"> |  | ||||||
| 		<link rel="stylesheet" href="https://cdnjs.cloudflare.com/ajax/libs/codemirror/5.12.0/theme/base16-dark.min.css"> |  | ||||||
| 		<script src="https://cdnjs.cloudflare.com/ajax/libs/codemirror/5.12.0/mode/javascript/javascript.min.js"></script> |  | ||||||
| 		<link type ="text/css" rel="stylesheet" href="/terminal/style.css"> |  | ||||||
| 		<meta name="viewport" content="width=device-width, initial-scale=1"> |  | ||||||
| 		<link type="image/png" rel="shortcut icon" href="/terminal/favicon.png"> |  | ||||||
| 	</head> |  | ||||||
| 	<body style="display: flex; flex-flow: column"> |  | ||||||
| 		<div class="navigation"> |  | ||||||
| 			<input type="button" id="back" name="back" value="Back" onclick="back()"> |  | ||||||
| 			<input type="button" id="save" name="save" value="Save" onclick="save()"> |  | ||||||
| 			<input type="button" id="saveAs" name="saveAs" value="Save As" onclick="saveAs()"> |  | ||||||
| 			<input type="checkbox" id="run" name="run" checked><label for="run">Run after Saving</label> |  | ||||||
| 			<input type="button" id="revert" name="revert" value="Revert to Saved" onclick="revert()"> |  | ||||||
| 			<button onclick="addLicense()"><img src="/terminal/agplv3-88x31.png" width="34" height="12" alt="AGPLv3"> Add License Header</button> |  | ||||||
| 		</div> |  | ||||||
| 		<textarea id="editor" class="main">$(SOURCE)</textarea> |  | ||||||
| 		<script src="/terminal/editor.js"></script> |  | ||||||
| 	</body> |  | ||||||
| </html> |  | ||||||
							
								
								
									
										118
									
								
								core/editor.js
									
									
									
									
									
								
							
							
						
						
									
										118
									
								
								core/editor.js
									
									
									
									
									
								
							| @@ -1,118 +0,0 @@ | |||||||
| var gBackup; |  | ||||||
| var gEditor; |  | ||||||
|  |  | ||||||
| window.addEventListener("load", function() { |  | ||||||
| 	gEditor = CodeMirror.fromTextArea(document.getElementById("editor"), { |  | ||||||
| 		'theme': 'base16-dark', |  | ||||||
| 		'lineNumbers': true, |  | ||||||
| 		'tabSize': 4, |  | ||||||
| 		'indentUnit': 4, |  | ||||||
| 		'indentWithTabs': true, |  | ||||||
| 		'showTrailingSpace': true, |  | ||||||
| 	}); |  | ||||||
| 	gBackup = gEditor.getValue(); |  | ||||||
| 	gEditor.focus(); |  | ||||||
| }); |  | ||||||
|  |  | ||||||
| window.addEventListener("keydown", function(event) { |  | ||||||
| 	if (event.keyCode == 83 && event.altKey) { |  | ||||||
| 		save(); |  | ||||||
| 	} else if (event.keyCode == 66 && event.altKey) { |  | ||||||
| 		back(); |  | ||||||
| 	} |  | ||||||
| }); |  | ||||||
|  |  | ||||||
| function explodePath() { |  | ||||||
| 	return /^\/~([^\/]+)\/([^\/]+)(.*)/.exec(window.location.pathname); |  | ||||||
| } |  | ||||||
|  |  | ||||||
| function packageOwner() { |  | ||||||
| 	return explodePath()[1]; |  | ||||||
| } |  | ||||||
|  |  | ||||||
| function packageName() { |  | ||||||
| 	return explodePath()[2]; |  | ||||||
| } |  | ||||||
|  |  | ||||||
| function back(uri) { |  | ||||||
| 	if (uri) { |  | ||||||
| 		window.location.pathname = uri; |  | ||||||
| 	} else { |  | ||||||
| 		window.location.pathname = "/~" + packageOwner() + "/" + packageName(); |  | ||||||
| 	} |  | ||||||
| } |  | ||||||
|  |  | ||||||
| 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) { |  | ||||||
| 				back(request.responseText); |  | ||||||
| 			} |  | ||||||
| 		} 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" : "save", true); |  | ||||||
| 	request.setRequestHeader("Content-Type", "text/plain"); |  | ||||||
| 	request.send(contents); |  | ||||||
| } |  | ||||||
|  |  | ||||||
| function saveAs() { |  | ||||||
| 	var newName = prompt("Save as:", packageName()); |  | ||||||
| 	if (newName) { |  | ||||||
| 		save(newName); |  | ||||||
| 	} |  | ||||||
| } |  | ||||||
|  |  | ||||||
| function revert() { |  | ||||||
| 	gEditor.setValue(gBackup); |  | ||||||
| } |  | ||||||
|  |  | ||||||
| function addLicense() { |  | ||||||
| 	var contents = "/*\n" + |  | ||||||
| 		"<one line to give the program's name and a brief idea of what it does.>\n" + |  | ||||||
| 		"Copyright (C) <year>  <name of author>\n".replace("<year>", new Date().getFullYear()) + |  | ||||||
| 		"\n" + |  | ||||||
| 		"This program is free software: you can redistribute it and/or modify\n" + |  | ||||||
| 		"it under the terms of the GNU Affero General Public License as published by\n" + |  | ||||||
| 		"the Free Software Foundation, either version 3 of the License, or\n" + |  | ||||||
| 		"(at your option) any later version.\n" + |  | ||||||
| 		"\n" + |  | ||||||
| 		"This program is distributed in the hope that it will be useful,\n" + |  | ||||||
| 		"but WITHOUT ANY WARRANTY; without even the implied warranty of\n" + |  | ||||||
| 		"MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the\n" + |  | ||||||
| 		"GNU Affero General Public License for more details.\n" + |  | ||||||
| 		"\n" + |  | ||||||
| 		"You should have received a copy of the GNU Affero General Public License\n" + |  | ||||||
| 		"along with this program.  If not, see <http://www.gnu.org/licenses/>.\n" + |  | ||||||
| 		"*/\n\n" + |  | ||||||
| 		gEditor.getValue(); |  | ||||||
| 	gEditor.setValue(contents); |  | ||||||
| } |  | ||||||
| @@ -12,18 +12,32 @@ | |||||||
| 			<span>😎</span> | 			<span>😎</span> | ||||||
| 			<span id="title">Tilde Friends</span> | 			<span id="title">Tilde Friends</span> | ||||||
| 			<a href="/">home</a> | 			<a href="/">home</a> | ||||||
| 			<a href="$(EDIT_SOURCE)">edit</a> | 			<a href="#" onclick="event.preventDefault(); edit()">edit</a> | ||||||
| 			<a href="$(VIEW_SOURCE)">view source</a> | 			<a href="$(VIEW_SOURCE)">view source</a> | ||||||
| 			<a href="/~cory/about">about</a> | 			<a href="/~cory/about">about</a> | ||||||
| 			<span id="status"></span> | 			<span id="status"></span> | ||||||
| 			<span id="update">update available! <a href="">refresh</a> to update</span> | 			<span id="update">update available! <a href="">refresh</a> to update</span> | ||||||
| 			<span id="login"></span> | 			<span id="login"></span> | ||||||
| 		</div> | 		</div> | ||||||
|  | 		<div id="content" class="hbox" style="flex: 1 1; width: 100%"> | ||||||
|  | 			<div id="editPane" style="flex: 0 0 50%; display: none; flex-flow: column; overflow: auto"> | ||||||
|  | 				<div class="navigation"> | ||||||
|  | 					<input type="button" id="closeEditor" name="closeEditor" value="Close" onclick="closeEditor()"> | ||||||
|  | 					<input type="button" id="save" name="save" value="Save" onclick="save()"> | ||||||
|  | 					<input type="button" id="saveAs" name="saveAs" value="Save As" onclick="saveAs()"> | ||||||
|  | 					<input type="checkbox" id="run" name="run" checked><label for="run">Restart after save</label> | ||||||
|  | 					<input type="button" id="revert" name="revert" value="Revert to Saved" onclick="revert()"> | ||||||
|  | 				</div> | ||||||
|  | 				<textarea id="editor" class="main"></textarea> | ||||||
|  | 			</div> | ||||||
|  | 			<div class="vbox" style="flex: 1 0 50%; overflow: auto"> | ||||||
| 				<div id="terminals" class="vbox"><div id="terminal_" class="terminal" style="flex: 1 1"></div></div> | 				<div id="terminals" class="vbox"><div id="terminal_" class="terminal" style="flex: 1 1"></div></div> | ||||||
| 				<div class="input"> | 				<div class="input"> | ||||||
| 					<span id="prompt">></span> | 					<span id="prompt">></span> | ||||||
| 					<input type='text' id='input'> | 					<input type='text' id='input'> | ||||||
| 				</div> | 				</div> | ||||||
|  | 			</div> | ||||||
|  | 		</div> | ||||||
| 		<script src="/terminal/client.js"></script> | 		<script src="/terminal/client.js"></script> | ||||||
| 	</body> | 	</body> | ||||||
| </html> | </html> | ||||||
|   | |||||||
| @@ -102,11 +102,6 @@ a:active, .command:active { | |||||||
| 	padding: 0; | 	padding: 0; | ||||||
| } | } | ||||||
|  |  | ||||||
| .CodeMirror-scroll { |  | ||||||
| 	height: 100%; |  | ||||||
| 	padding: 0; |  | ||||||
| } |  | ||||||
|  |  | ||||||
| .cm-tab { | .cm-tab { | ||||||
| 	background: url(data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAADAAAAAMCAYAAAAkuj5RAAAAAXNSR0IArs4c6QAAAGFJREFUSMft1LsRQFAQheHPowAKoACx3IgEKtaEHujDjORSgWTH/ZOdnZOcM/sgk/kFFWY0qV8foQwS4MKBCS3qR6ixBJvElOobYAtivseIE120FaowJPN75GMu8j/LfMwNjh4HUpwg4LUAAAAASUVORK5CYII=); | 	background: url(data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAADAAAAAMCAYAAAAkuj5RAAAAAXNSR0IArs4c6QAAAGFJREFUSMft1LsRQFAQheHPowAKoACx3IgEKtaEHujDjORSgWTH/ZOdnZOcM/sgk/kFFWY0qV8foQwS4MKBCS3qR6ixBJvElOobYAtivseIE120FaowJPN75GMu8j/LfMwNjh4HUpwg4LUAAAAASUVORK5CYII=); | ||||||
| 	background-position: right; | 	background-position: right; | ||||||
|   | |||||||
| @@ -7,7 +7,6 @@ var kStaticFiles = [ | |||||||
| 	{uri: '/favicon.png', path: 'favicon.png', type: 'image/png'}, | 	{uri: '/favicon.png', path: 'favicon.png', type: 'image/png'}, | ||||||
| 	{uri: '/client.js', path: 'client.js', type: 'text/javascript; charset=UTF-8'}, | 	{uri: '/client.js', path: 'client.js', type: 'text/javascript; charset=UTF-8'}, | ||||||
| 	{uri: '/editor.js', path: 'editor.js', type: 'text/javascript; charset=UTF-8'}, | 	{uri: '/editor.js', path: 'editor.js', type: 'text/javascript; charset=UTF-8'}, | ||||||
| 	{uri: '/agplv3-88x31.png', path: 'agplv3-88x31.png', type: 'image/png'}, |  | ||||||
| 	{uri: '/robots.txt', path: 'robots.txt', type: 'text/plain; charset=UTF-8'}, | 	{uri: '/robots.txt', path: 'robots.txt', type: 'text/plain; charset=UTF-8'}, | ||||||
| ]; | ]; | ||||||
|  |  | ||||||
|   | |||||||
		Reference in New Issue
	
	Block a user