termwebui

old portfolio website with terminal interface

git clone https://9o.is/git/termwebui.git

index.html

(7939B)


      1 <!DOCTYPE html>
      2 <html lang="en-us">
      3 
      4 <head>
      5 <meta charset="utf-8">
      6 
      7 <script language="JavaScript">
      8 document.oncontextmenu =new Function("return false;")
      9 </script> 
     10 
     11 <style type="text/css">
     12 
     13 html, body, p, em, div, span, label, input, textarea, pre {
     14 	background-color: black;
     15 	color: white;
     16 	font-family: monospace !important;
     17 	font-size: 12px;
     18 	
     19 	border: none !important;
     20 	margin: 0 !important;
     21 	padding: 0 !important;
     22 	
     23 	-webkit-touch-callout: none;
     24     -webkit-user-select: none;
     25     -khtml-user-select: none;
     26     -moz-user-select: none;
     27     -ms-user-select: none;
     28     user-select: none;
     29 }
     30 
     31 html, body, #terminal {
     32 	overflow: hidden;
     33 }
     34 
     35 #terminal {
     36 	width: 600px;
     37 	word-break: break-all;
     38 }
     39 
     40 #scroller {
     41 	position: relative;
     42 	width: 620px;
     43 	overflow-y: scroll;
     44 }
     45 
     46 .green { color: green;}
     47 .blue { color: blue;}
     48 .red { color: red;}
     49 .orange { color: orange;}
     50 .ls-item { margin-right: 15px !important; }
     51 
     52 </style>
     53 </head>
     54 
     55 <body onselectstart="return false">
     56 <div id="terminal">
     57 	<div id="scroller">
     58 		<div id="output"></div>
     59 		<div id="input"></div>
     60 	</div>
     61 </div>
     62 
     63 <script> 
     64 
     65 var Terminal = {
     66 	HOSTNAME: "jcabrra",
     67 	ROOT: "https://jsterm-jcabrra.c9.io",
     68 	PWD: "/",
     69 	PS1: "$ "
     70 };
     71 
     72 Terminal.interface = (function(){
     73 	
     74 	var scroller = document.getElementById("scroller");
     75 	
     76 	var setTitle = function() {
     77 		document.title = "["+Terminal.HOSTNAME+"] Terminal: "+Terminal.PWD;
     78 	};
     79 
     80 	setInterval(function() {
     81 		setTitle();
     82 	}, 100);
     83 	
     84 	return {
     85 		scrollToBottom: function() {
     86 			scroller.scrollTop = scroller.scrollHeight;
     87 		},
     88 		resize: function() {
     89    			scroller.style.height = window.innerHeight + "px";
     90 		}
     91 	}
     92 })();
     93 
     94 Terminal.input = (function(){
     95 	
     96 	var value = "";
     97 	var pointer = 0;
     98 	
     99 	
    100 	var display = (function(){
    101 	
    102 		var display = document.getElementById("input");
    103 		var animation = "<span class='green'>"+String.fromCharCode(9608)+"</span>";
    104 		var cursor = true;
    105 		var cursorText = animation;
    106 
    107 		setInterval(function(){
    108 			display.innerHTML = Terminal.PS1 + (cursor ? cursorText : value);
    109 		}, 50);
    110 		
    111 		setInterval(function(){
    112 			cursor = cursor ? false : true;
    113 		}, 500);
    114 		
    115 		return {
    116 			resetCursor: function() {
    117 				cursor = true;
    118 				cursorText = 
    119 					value.substring(0, pointer) + 
    120 					animation + value.substring(pointer + 1, value.length);
    121 			}	
    122 		}
    123 	})();
    124 	
    125 	var history = (function(){
    126 	
    127 		var history = [""];
    128 		var pointer = 0;
    129 	
    130 		return {
    131 			reset: function(input) {
    132 				history.unshift("");
    133 				pointer = 0;
    134 			},
    135 			up: function() {
    136 				if(pointer < history.length - 1) {
    137 					pointer++;
    138 				}
    139 			},
    140 			down: function() {
    141 				if(pointer > 0) {
    142 					pointer--;
    143 				}
    144 			},
    145 			get: function() {
    146 				return history[pointer];
    147 			},
    148 			set: function(input) {
    149 				history[pointer] = input;
    150 			}
    151 		}
    152 	})();
    153 	
    154 	var getHistory = function() {
    155 		var newValue = history.get();
    156 		value = newValue;
    157 		pointer = newValue.length;
    158 		display.resetCursor();
    159 	};
    160 	
    161 	return {
    162 		set: function(char) {
    163 			value = 
    164 				value.substring(0, pointer) + char + 
    165 				value.substring(pointer, value.length);
    166 			pointer++;
    167 			history.set(value);
    168 			display.resetCursor();
    169 		},
    170 		delete: function() {
    171 			if(pointer > 0) {
    172 				value = 
    173 					value.substring(0, pointer - 1) + 
    174 					value.substring(pointer, value.length);
    175 				pointer--;
    176 				history.set(value);
    177 				display.resetCursor();
    178 			}
    179 		},
    180 		up: function() {
    181 			history.up();
    182 			getHistory();
    183 		},
    184 		down: function() {
    185 			history.down();
    186 			getHistory();
    187 		},
    188 		left: function() {
    189 			if(pointer > 0) {
    190 				pointer--;
    191 				display.resetCursor();
    192 			}
    193 		},
    194 		right: function() {
    195 			if(pointer <= value.length) {
    196 				pointer++;
    197 				display.resetCursor();
    198 			}
    199 		},
    200 		reset: function() {
    201 			value = "";
    202 			pointer = 0;
    203 			display.resetCursor();
    204 			history.reset();
    205 		},
    206 		value: function() {
    207 			return value;
    208 		}
    209 	}
    210 })();
    211 
    212 Terminal.output = (function(){
    213 	
    214 	var display = document.getElementById("output");
    215 	
    216 	return {
    217 		commit: function(text) {
    218 			var out = document.createElement("div");
    219 			out.innerHTML = text;
    220 			display.appendChild(out);
    221 		}
    222 	}
    223 })();
    224 
    225 Terminal.cmd = (function(){
    226 	
    227 	var commands = [];
    228 	
    229 	var valid = function(cmd) {
    230 		var fn = ["name", "exec"];
    231 		
    232 		for(var i=0; i<fn.length;i++) {
    233 			if(!cmd[fn[i]]) {
    234 				return false;
    235 			}
    236 		}
    237 		return true;
    238 	};
    239 	
    240 	var find = function(name) {
    241 		for(var i=0; i<commands.length;i++) {
    242 			if(commands[i].name === name) {
    243 				return commands[i];
    244 			}
    245 		}
    246 	};
    247 	
    248 	return {
    249 		register: function(cmd) {
    250 			if(valid(cmd)) {
    251 				commands.push(cmd);
    252 			}
    253 		},
    254 		execute: function(command) {
    255 			var values = command.split(" ");
    256 			var cmd = find(values[0]);
    257 			if(typeof cmd !== 'undefined') {
    258 				cmd.exec(values);
    259 			}
    260 		}
    261 	}
    262 })();
    263 
    264 (function(){
    265 	var banner = {
    266 		name: 'banner',
    267 		exec: function() {
    268 			var value = "My Banner!\nYeah!"
    269 			Terminal.output.commit(value);
    270 		}
    271 	};
    272 	
    273 	Terminal.cmd.register(banner);
    274 })();
    275 
    276 (function(){
    277 	var date = {
    278 		name: 'date',
    279 		exec: function() {
    280 			var value = new Date().toString()
    281 			Terminal.output.commit(value);
    282 		}
    283 	};
    284 	
    285 	Terminal.cmd.register(date);
    286 })();
    287 
    288 (function(){
    289 	var pwd = {
    290 		name: 'pwd',
    291 		exec: function() {
    292 			Terminal.output.commit(Terminal.PWD);
    293 		}
    294 	};
    295 	
    296 	Terminal.cmd.register(pwd);
    297 })();
    298 
    299 (function(){
    300 	var img = {
    301 		name: 'img',
    302 		exec: function() {
    303 			// TODO: http://thecodeplayer.com/walkthrough/cool-ascii-animation-using-an-image-sprite-canvas-and-javascript
    304 		}
    305 	};
    306 	
    307 	Terminal.cmd.register(img);
    308 })();
    309 
    310 (function(){
    311 	var ls = {
    312 		name: 'ls',
    313 		exec: function() {
    314 			var xhr = new XMLHttpRequest();
    315 			xhr.onreadystatechange = function() {
    316     			if (xhr.readyState === 4 && xhr.status === 200) {
    317     				var obj = null;
    318 					try {
    319 						console.log(xhr.responseText);
    320 						obj = JSON.parse(xhr.responseText);
    321 					} catch(e) {
    322 						console.error('The server returned JSON but contains an error: '+e);
    323 					} finally {
    324 						var value = "";
    325 						
    326 						var dir_len = obj.directories.length;
    327 						for(var i=0; i<dir_len; i++) {
    328 							value += "<span class='ls-item orange'>" + 
    329 								obj.directories[i] + "</span>";
    330 						}
    331 						
    332 						var files_len = obj.files.length;
    333 						for(var i=0; i<files_len; i++) {
    334 							value += "<span class='ls-item'>" + 
    335 								obj.files[i] + "</span>";
    336 						}
    337 						
    338 						Terminal.output.commit(value);
    339 					}
    340     			}
    341 			};
    342 			xhr.setRequestHeader("If-Modified-Since", "Sat, 1 Jan 2005 00:00:00 GMT");
    343 			xhr.open('GET', Terminal.ROOT + Terminal.PWD + ".ls", true);
    344 			xhr.send(null);
    345 		}
    346 	};
    347 	
    348 	Terminal.cmd.register(ls);
    349 })();
    350 
    351 (function(){
    352 	var cat = {
    353 		name: 'cat',
    354 		exec: function(values) {
    355 			var xhr = new XMLHttpRequest();
    356 			xhr.onreadystatechange = function() {
    357     			if (xhr.readyState === 4 && xhr.status === 200) {
    358     				Terminal.output.commit(xhr.responseText);
    359     			}
    360 			}
    361 			xhr.open('GET', Terminal.ROOT + Terminal.PWD + values[1], true);
    362 			xhr.setRequestHeader("Content-Type", "text/plain; charset=UTF-8");
    363 			xhr.send(null);
    364 		}
    365 	};
    366 	
    367 	Terminal.cmd.register(cat);
    368 })();
    369 
    370 // cd (url should reflect pwd)
    371 
    372 Terminal.filesystem = (function(){
    373 	
    374 	
    375 	return {
    376 		
    377 	}
    378 })();
    379 
    380 
    381 window.onkeypress = function(event) {
    382 	event.preventDefault();
    383 	
    384 	switch(event.keyCode) {
    385 		case 13: // [Enter]
    386 			var value = Terminal.input.value();
    387 			Terminal.input.reset();
    388 			Terminal.output.commit(Terminal.PS1 + value);
    389 			Terminal.cmd.execute(value);
    390 			break;
    391 		case 8:  // [backspace]
    392 			Terminal.input.delete();
    393 			break;
    394 		case 37: // [left arrow]
    395 			Terminal.input.left();
    396 			break;
    397 		case 38: // [up arrow]
    398 			Terminal.input.up();
    399 			break;
    400 		case 39: // [right arrow]
    401 			Terminal.input.right();
    402 			break;
    403 		case 40: // [down arrow]
    404 			Terminal.input.down();
    405 			break;
    406 		default:
    407 			var char = event.charCode;
    408 			if(char > 31 && char < 127) {
    409 				char = String.fromCharCode(char);
    410 				Terminal.input.set(char);
    411 			}
    412 			break;
    413 	}
    414 	
    415 	Terminal.interface.scrollToBottom();
    416 }
    417 
    418 window.onload = function() {
    419 	Terminal.interface.resize();
    420 };
    421 
    422 window.onresize = function(event) {
    423     Terminal.interface.resize();
    424 };
    425 
    426 </script>
    427 
    428 </body>
    429 </html>