diff options
-rw-r--r-- | README.md | 3 | ||||
-rw-r--r-- | dist/default.css | 57 | ||||
-rw-r--r-- | dist/index.html | 21 | ||||
-rw-r--r-- | dist/index.js | 85 | ||||
-rw-r--r-- | dist/test/index.html | 3 | ||||
-rw-r--r-- | main.js | 76 | ||||
-rw-r--r-- | package.json | 5 |
7 files changed, 250 insertions, 0 deletions
diff --git a/README.md b/README.md new file mode 100644 index 0000000..d64ce72 --- /dev/null +++ b/README.md @@ -0,0 +1,3 @@ +# Chatroom + +This is an example For creating a simple web socket chatroom server with a webclient diff --git a/dist/default.css b/dist/default.css new file mode 100644 index 0000000..933b93a --- /dev/null +++ b/dist/default.css @@ -0,0 +1,57 @@ +body { + color: white; + background-color: #222; + font-family: Arial, sans-serif; + overflow: hidden; +} + +.header { + height: 10%; +} +.main { + height: 85%; +} + +.footer { + float: bottom; + height:5% +} + +#messages { + height: 100%; + overflow-y: scroll; + overflow-x: auto; + position: relative; + bottom: 0; +} + +#msgbox { + width: 100%; + height: 100%; +} + +input { + border: 1px solid #45d; + background-color: #45b; + color: white; +} +input:focus { + border: 1px solid #000; + +} + +::-webkit-scrollbar { + width: 10px; +} + +::-webkit-scrollbar-track { + background: rgba(0, 0, 0, 0); +} + +::-webkit-scrollbar-thumb { + background: #888; +} + +::-webkit-scrollbar-thumb:hover { + background: #555; +} diff --git a/dist/index.html b/dist/index.html new file mode 100644 index 0000000..c2bcad6 --- /dev/null +++ b/dist/index.html @@ -0,0 +1,21 @@ +<head> + <title>chatroom</title> + <script src="index.js"></script> + <link rel="stylesheet" href="default.css"> + +</head> + +<body> + <div class="header"> + <h1>welcome to discörd</h1> + <label for="nickbox">nickname: </label> + <input id="nickbox" type="text" > + </div> + <div class="main"> + <div id="messages"> + </div> + </div> + <div class="footer"> + <input id="msgbox" type="text"> + </div> +</body> diff --git a/dist/index.js b/dist/index.js new file mode 100644 index 0000000..2ad7b15 --- /dev/null +++ b/dist/index.js @@ -0,0 +1,85 @@ +document.addEventListener("DOMContentLoaded", () => { + + // Read parameters in the url and find a nickname from them + const params = new URLSearchParams(window.location.search); + var nick = params.get("nick"); + // preload the nickname into the nickname input box + if (nick) { + var nickbox = document.getElementById("nickbox"); + nickbox.value = nick; + } + + // initialise the websocket connection + const url = `ws://${window.location.hostname}:8081`; + const connection = new WebSocket(url); + + // define functions listening to the websocket + connection.onopen = () => { + + // estimate how many lines should be requested from the client + var lines = Math.round(window.innerHeight / 12); + // send the initial "join" message from the client, with an initial nickname and how many messages should be preloaded + connection.send(JSON.stringify({ + event: "join", + nickname: nick, + lines: lines + })); + } + + // define a listener for errors, to be printed to the console + connection.onerror = error => { + console.log(`WebSocket error: ${error}`); + } + + // define a listener for messages + connection.onmessage = (ev) => { + // parse the message as a json object + var data = JSON.parse(ev.data); + + // If the message is of type "message", we can add it to the screen + if (data.event == "message"){ + addMessage(data.content, data.nickname); + } + } + + // display messages on the screen for the user + function addMessage(content, sender) { + + // Find the "messages" box in the document + var messagesElement = document.getElementById("messages"); + + // create a new message and add it as a child to the messagesElement + var newMessage = document.createElement("div"); + newMessage.innerText = `${sender}: ${content}`; + messagesElement.appendChild(newMessage); + + // update the scroll, so that the client has the newest message visible + messagesElement.scrollTop = messagesElement.scrollHeight; + } + + // send a message to the webserver + function sendMessage(msg) { + // check the nickname box for a value + nick = document.getElementById("nickbox").value; + + // Send a json object to the websocket + connection.send(JSON.stringify({ + content: msg, + nickname: nick, + event: "message" + })); + } + + var inputBox = document.getElementById("msgbox"); + // prefocus the input box when the page is loaded + inputBox.focus(); + // add event listener for enter key on input box + inputBox.addEventListener("keyup", ev => { + if (event.keyCode == 13) { + event.preventDefault(); + sendMessage(inputBox.value); + inputBox.value = ""; + } + }) +}); + diff --git a/dist/test/index.html b/dist/test/index.html new file mode 100644 index 0000000..8c62610 --- /dev/null +++ b/dist/test/index.html @@ -0,0 +1,3 @@ +<body> + <h1>ctest</h1> +</body> @@ -0,0 +1,76 @@ +const http = require("http"); +const fs = require("fs"); +const path = require("path"); +const url = require("url"); +const websocket = require("ws"); + +const static_content = __dirname + "/dist/"; + +// Create an array to store messages in +var log = [] + +// Initialise a simple http server to serve any static files +http.createServer((req, res) => { + + // normalise path name to stay within a normal directory + var requestUrl = url.parse(req.url); + var fsPath = static_content + path.normalize(requestUrl.pathname); + + // automatically return the index of a directory, if its been selected + if (fs.statSync(fsPath).isDirectory()) + fsPath += fsPath.endsWith("/") ? "index.html" : "/index.html"; + + // read and send the file + fs.readFile(fsPath, (err, data) => { + if (err) { + res.writeHead(404); + res.end(JSON.stringify(err)) + } else { + res.writeHead(200); + res.end(data); + } + }); +}).listen(8080); + +// create websocket: client tracking allows us to get a set of clients so that we can send messages to each client once they appear +const wss = new websocket.Server({port : 8081, clientTracking: true}); + +wss.on("connection", ws => { + // predefine a user nickname + var nick = "anon" + wss.clients.size + + ws.on("message", msg => { + var data = JSON.parse(msg); + + // Ensure that nickname requirements are met before setting client's nick + if (data.nickname && data.nickname.length < 24 && data.nickname.length > 0) nick = data.nickname; + + switch data.event { + case "join": + // send the client the requested number of messages before joining + if (data.lines) log.slice(0-data.lines).forEach(l => ws.send(l)) + break; + case "message": + // ensure that the message length requirements are met correctly + if (data.content.length < 128 && data.content.length > 0) { + + // recreate the message object to be sent + message = JSON.stringify({ + event: "message", + content: data.content, + nickname: nick + }); + + // send the message to the log array first + log.push(message); + + // propogate the message to all connected clients + wss.clients.forEach(c => { + c.send(message); + }) + } + break; + } + + }); +}) diff --git a/package.json b/package.json new file mode 100644 index 0000000..779bfec --- /dev/null +++ b/package.json @@ -0,0 +1,5 @@ +{ + "dependencies": { + "ws": "^7.5.2" + } +} |