diff options
Diffstat (limited to 'webclient')
| -rw-r--r-- | webclient/client.html | 326 | 
1 files changed, 326 insertions, 0 deletions
| diff --git a/webclient/client.html b/webclient/client.html new file mode 100644 index 0000000..3472cb8 --- /dev/null +++ b/webclient/client.html @@ -0,0 +1,326 @@ +<!doctype html> +<html> +<head> +<meta charset="utf-8"> +<title>tomsg webclient</title> +<script> +var sock=null,username=null; +var roomlist=[":console"]; +var currentroom=":console"; +var roomlogs={":console":[]}; + +(function(){ +	var id=1; +	function uniqid(){ +		return id++; +	} +})(); + +var net_callbacks={}; + +function net_send(msg,cb){ +	var id=uniqid()+""; +	sock.send(id+" "+msg); +	net_callbacks[id]=cb; +} + +function reconnect(){ +	if(sock)sock.close(); + +	net_callbacks={}; + +	var host=location.hostname||"localhost"; +	sock=new WebSocket("ws://"+host+":29546"); +	updateStatus(); +	updateRoomList(); +	sock.addEventListener("message",function(msg){ +		var spl=msg.split(" ",2); +		var id=spl[0],type=spl[1]; +		var rest=msg.slice(id.length+type.length+2); +		if(id=="_push"){ +			if(type=="message"){ +				spl=rest.split(" ",2); +				var r=spl[0],u=spl[1]; +				addRoomEntry(r,"message",[u,rest.slice(r.length+u.length+2)]); +			} else { +				alert("Unknown push message type '"+type+"'!"); +			} +		} else if(net_callbacks[id]){ +			var fn=net_callbacks[id]; +			var obj; +			if(type=="ok")fn(true); +			else if(type=="error")fn(null,rest); +			else if(type=="name")fn(rest); +			else if(type=="list")fn(rest.split(" ").slice(1)); +			else alert("Unknown server response message type '"+type+"'!"); +		} else { +			alert("No callback for server message id '"+id+"'!"); +		} +	}); +	sock.addEventListener("open",function(){ +		updateStatus(); +	}); +	sock.addEventListener("close",function(ev){ +		updateStatus(); +		if(ev.code!=1000){ +			setTimeout(function(){ +				reconnect(); +			},1000+Math.random()*1000); +		} +	}); +} + +function updateStatus(){ +	var str=null; +	if(!sock||sock.readyState>=2){ +		str="not connected"; +	} else if(sock.readyState==0){ +		str="connecting..."; +	} else if(username){ +		str="u: "+username; +	} else { +		str="connected"; +	} +	var div=document.getElementById("status"); +	if(!div.firstChild)div.appendChild(document.createTextNode("")); +	div.firstChild.nodeValue=str; +} + +function updateRoomList(){ +	var rldiv=document.getElementById("roomlist"); +	var ch=rldiv.children,len=ch.length; +	var i; +	for(i=len-1;i>=0;i--)rldiv.removeChild(ch[i]); + +	var div; +	for(i=0;i<roomlist.length;i++){ +		div=document.createElement("div"); +		div.classList.add("roomlistitem"); +		if(roomlist[i]==currentroom)div.classList.add("selected"); +		div.addEventListener("click",function(roomid){ +			currentroom=roomid; +			drawRoom(currentroom); +		}.bind(this,roomlist[i])); +		div.appendChild(document.createTextNode(roomlist[i])); +		rldiv.appendChild(div); +	} +} + +function drawRoom(roomid){ +	var tbody=document.getElementById("roomlog"); +	var ch=tbody.children,len=ch.length; +	var i; +	for(i=len-1;i>=0;i--)tbody.removeChild(ch[i]); + +	var roomtitle=document.getElementById("roomtitle"); +	if(!roomtitle.firstChild)roomtitle.appendChild(document.createTextNode(roomid)); +	else roomtitle.firstChild.nodeValue=roomid; + +	var tr,td; +	var items=roomlogs[roomid]; +	if(!items){ +		alert("drawRoom on nonexistent roomid '"+roomid+"'!"); +		return; +	} +	for(i=Math.max(0,items.length-20);i<items.length;i++){ +		drawRoomEntry(items[i][0],items[i][1]); +	} +} + +function drawRoomEntry(type,args){ +	var tbody=document.getElementById("roomlog"); +	var tr=document.createElement("tr"); +	var td; +	switch(type){ +		case "message": +			td=document.createElement("td"); +			td.appendChild(document.createTextNode(args[0])); +			tr.appendChild(td); +			td=document.createElement("td"); +			td.classList.add("message"); +			td.appendChild(document.createTextNode(args[1])); +			tr.appendChild(td); +			tbody.appendChild(tr); +			break; + +		default: +			alert("drawRoomEntry on unknown type '"+type+"'!"); +			break; +	} +} + +function addRoomEntry(roomid,type,args){ +	if(!roomlogs[roomid]){ +		alert("addRoomEntry on nonexistent roomid '"+roomid+"'!"); +		return; +	} +	roomlogs[roomid].push([type,args]); +	if(roomid==currentroom){ +		drawRoomEntry(type,args); +	} +} + +function doSend(){ +	var inputelem=document.getElementById("roominput"); +	var text=inputelem.value; +	inputelem.value=""; +	addRoomEntry(currentroom,"message",["-",text]); +} + +function doKeypress(ev){ +	if(ev.keyCode==10||ev.keyCode==13)doSend(); +} + +window.addEventListener("load",function(){ +	reconnect(); +	drawRoom(currentroom); +}); +</script> +<style> +html, body{ +	margin:0; +	width:100%; +	height:100%; +} +body{ +	background-color:#04040c; +	color:#eee; +	font-family:mononoki,meslo,monaco,monospace; +	font-size:11pt; +} +table{ +	border-collapse:collapse; +} +#window{ +	width:100%; +	height:100%; +} + +/* SIDEBAR */ +#sidebar{ +	width:150px; +	border-right:1px #668 solid; +	vertical-align:top; +} + +#branding{ +	background-color:#223; +	padding:4px; +	height:22px; +	text-align:center; +	font-size:13pt; +} +#status{ +	padding:2px; +	margin:8px 0px 10px 0px; +} +.roomlistitem{ +	margin:1px 0px; +	padding:3px 2px; +	background-color:#223; +	cursor:pointer; +} +.roomlistitem:hover{ +	background-color:#282833; +} +.roomlistitem.selected{ +	background-color:#335; +	font-weight:bold; +} +.roomlistitem:hover{ +	background-color:#445; +} + +/* ROOM VIEW */ +#room{ +	width:100%; +	height:100%; +} +#room_td{ +	padding:0; +} +#roomtitle{ +	height:22px; +	padding:4px; +	background-color:#335; +	font-weight:bold; +} + +#roomlog_td{ +	vertical-align:top; +} +#roomlog_table{ +	width:100%; +	/*height:100%;*/ +} +#roomlog > tr > td:first-child{ +	width:150px; +} + +#roombar_tr{ +	height:30px; +	border-top:1px #668 solid; +} +#roominput_td{ +	position:relative; +	vertical-align:top; +	padding:0px 1px 0px 10px; +} +#roominput{ +	position:absolute; +	background-color:rgba(0,0,0,0); +	padding:0; +	border-width:0; +	width:calc(100% - 11px); +	height:100%; +	color:white; +	font-family:inherit; +	font-size:inherit; +} +#roomsend_td{ +	position:relative; +	width:40px; +	vertical-align:top; +	padding:0; +} +#roomsend{ +	position:absolute; +	width:100%; +	height:100%; +	background-color:#335; +	border-width:0px; +	color:#ccc; +	font-family:inherit; +	font-size:inherit; +	cursor:pointer; +} +#roomsend:hover{ +	background-color:#445; +} +</style> +<script src="https://use.fontawesome.com/ccf28a5626.js"></script> +</head> +<body> +<table id="window"><tbody><tr> +	<td id="sidebar"> +		<div id="branding">TOMSG</div> +		<div id="status"> </div> +		<div id="roomlist"></div> +	</td> +	<td id="room_td"> +		<table id="room"><tbody> +			<tr id="roomtitle_tr"><td id="roomtitle" colspan="2"></td></tr> +			<tr id="roomlog_tr"><td id="roomlog_td" colspan="2"> +				<table id="roomlog_table"><tbody id="roomlog"></tbody></table> +			</td></tr> +			<tr id="roombar_tr"> +				<td id="roominput_td"><input type="text" id="roominput" onkeypress="doKeypress(event)"></td> +				<td id="roomsend_td"> +					<button id="roomsend" onclick="doSend()"><i class="fa fa-send"></i></button> +				</td> +			</tr> +		</tbody></table> +	</td> +</tr></tbody></table> +</body> +</html> | 
