diff options
author | tomsmeding <tom.smeding@gmail.com> | 2017-03-25 23:02:21 +0100 |
---|---|---|
committer | tomsmeding <tom.smeding@gmail.com> | 2017-03-25 23:02:21 +0100 |
commit | 11f606c269e3b7cca1848bc227e8e38321fb6e3e (patch) | |
tree | c1dded2e8a1f244f8b9a17b0aa7778b2e0afe353 | |
parent | 7157893eb0d7cce75a423b42e183ef88bc2130eb (diff) |
Start work on web client
-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> |