diff options
author | Kevin Chabowski <kevin@kch42.de> | 2014-03-27 12:28:05 +0100 |
---|---|---|
committer | Kevin Chabowski <kevin@kch42.de> | 2014-03-27 23:51:07 +0100 |
commit | dfd11c94c1ad5261caa43128a39fcce550edf61d (patch) | |
tree | b80458e610077b17da9815d14f71f590d4de56af | |
parent | c35e43e9cf0f915236016a3f73a6ee6bc9962e0b (diff) | |
download | simplechat-dfd11c94c1ad5261caa43128a39fcce550edf61d.tar.gz simplechat-dfd11c94c1ad5261caa43128a39fcce550edf61d.tar.bz2 simplechat-dfd11c94c1ad5261caa43128a39fcce550edf61d.zip |
Chat now works on the client side
-rw-r--r-- | chat/messages.go | 2 | ||||
-rw-r--r-- | pages.go | 6 | ||||
-rw-r--r-- | static/chat.js | 100 | ||||
-rw-r--r-- | static/style.css | 26 | ||||
-rw-r--r-- | tpls/chat.html | 16 | ||||
-rw-r--r-- | websock.go | 15 |
6 files changed, 156 insertions, 9 deletions
diff --git a/chat/messages.go b/chat/messages.go index dbcd150..eed62fa 100644 --- a/chat/messages.go +++ b/chat/messages.go @@ -26,7 +26,7 @@ func (mt MsgType) String() string { return "???" } -func (mt *MsgType) MarshalJSON() ([]byte, error) { +func (mt MsgType) MarshalJSON() ([]byte, error) { return json.Marshal(mt.String()) } @@ -1,6 +1,7 @@ package main import ( + "github.com/gorilla/mux" "html/template" "net/http" "path" @@ -11,7 +12,7 @@ var ( ) type ChatpageData struct { - Websock string + Websock, Roomname string } func PrepTemplates() { @@ -24,5 +25,6 @@ func Home(rw http.ResponseWriter, req *http.Request) { } func Chatpage(rw http.ResponseWriter, req *http.Request) { - TplChat.Execute(rw, ChatpageData{"ws://" + req.Host + req.URL.Path + "socket"}) + vars := mux.Vars(req) + TplChat.Execute(rw, ChatpageData{"ws://" + req.Host + req.URL.Path + "socket", vars["chatroom"]}) } diff --git a/static/chat.js b/static/chat.js new file mode 100644 index 0000000..d9c89fe --- /dev/null +++ b/static/chat.js @@ -0,0 +1,100 @@ +function askTryAgain(reason, ws_url) { + if(confirm("Could not join chat (Reason: "+ reason +"). Try again?")) { + window.setTimeout(RunChat, 1, ws_url); // We use a timeout, so we don't accidentally fill up the call stack. + } +} + +function addBuddy(nick) { + var found = false; + $("#buddies li").each(function(index) { + if($(this).text() == nick) { + found = true; + } + }); + if(!found) { + $("#buddies").append($("<li/>").text(nick)); + } +} + +function removeBuddy(nick) { + $("#buddies li").each(function(index) { + var self = $(this); + if(self.text() == nick) { + self.remove(); + } + }); +} + +function chatlogWriter(event) { + var data = JSON.parse(event.data); + var msgtext = ""; + switch(data.type) { + case "chat": + msgtext = data.text; + break; + case "join": + msgtext = "joined the room"; + addBuddy(data.user); + break; + case "leave": + msgtext = "left the room"; + removeBuddy(data.user); + break; + } + + var elemNick = $("<span/>").addClass("nick").text(data.user); + var elemText = $("<span/>").addClass("msg").text(msgtext); + var logentry = $("<li/>").addClass(data.type).append(elemNick).append(elemText); + $("#chatlog").append(logentry); + window.scrollTo(0, logentry.offset().top); +} + +function initChatSender(ws) { + var send = function() { + var ct = $("#chattext") + ws.send(ct.prop("value")); + ct.prop("value",""); + ct.focus(); + }; + + $("#sendbtn").click(send); + $("#chattext").keyup(function(event) { + if(event.keyCode==13) { + send(); + } + }); +} + +function Join(ws_url, nick) { + var ws = new WebSocket(ws_url, "chat"); + ws.onopen = function(_) { + ws.send(nick); + ws.onmessage = function(event) { + var data = JSON.parse(event.data); + if(data.ok) { + ws.onmessage = chatlogWriter; + for(i in data.buddies) { + addBuddy(data.buddies[i]); + } + initChatSender(ws); + ws.onclose = function(_) { + alert("Connection lost. Try refreshing the page."); + }; + } else { + ws.close(); + askTryAgain(data.error, ws_url); + } + }; + }; +} + +function RunChat(ws_url) { + var nick = ""; + while(nick == "") { + nick = prompt("Choose a nickname"); + if(nick === null) { + return; + } + } + Join(ws_url, nick); +} diff --git a/static/style.css b/static/style.css new file mode 100644 index 0000000..00fe4a4 --- /dev/null +++ b/static/style.css @@ -0,0 +1,26 @@ +* { + font-family: sans-serif; +} + +#chatlog { + display: table; + list-style: none; + margin: 0; + padding: 0 +} + +#chatlog li { + display: table-row; + margin: 0; + padding: 0; +} + +#chatlog li .nick { + display: table-cell; + padding-right: 1ex; + font-weight: bold; +} + +#chatlog li .msg { + display: table-cell; +}
\ No newline at end of file diff --git a/tpls/chat.html b/tpls/chat.html index c107b49..27ad69f 100644 --- a/tpls/chat.html +++ b/tpls/chat.html @@ -1,9 +1,19 @@ <!DOCTYPE html> <html> <head> - <title></title> + <title>{{.Roomname}}</title> + <script type="text/javascript" src="/static/jquery.min.js"></script> + <script type="text/javascript" src="/static/chat.js"></script> + <script type="text/javascript">$("document").ready(function(){RunChat("{{.Websock}}");});</script> + <link rel="stylesheet" type="text/css" href="/static/style.css" /> </head> <body> -{{ .Websock }} + <h1>{{.Roomname}}</h1> + <ul id="buddies"></ul> + <ul id="chatlog"></ul> + <div id="chatinput"> + <input type="text" name="chattext" id="chattext"/> + <button id="sendbtn">Chat</button> + </div> </body> -</html>
\ No newline at end of file +</html> @@ -43,11 +43,13 @@ func AcceptWebSock(rw http.ResponseWriter, req *http.Request) { return } + exit := make(chan struct{}) + go func() { var s string for { if websocket.Message.Receive(ws, &s) != nil { - return + break } if s == "" { @@ -56,11 +58,18 @@ func AcceptWebSock(rw http.ResponseWriter, req *http.Request) { buddy.Say(s) } + + exit <- struct{}{} }() - for m := range buddy.Receive { - if send(m) != nil { + for { + select { + case <-exit: return + case m := <-buddy.Receive: + if send(m) != nil { + return + } } } }).ServeHTTP(rw, req) |