summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--README.md3
-rw-r--r--dist/default.css57
-rw-r--r--dist/index.html21
-rw-r--r--dist/index.js85
-rw-r--r--dist/test/index.html3
-rw-r--r--main.js76
-rw-r--r--package.json5
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&ouml;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>
diff --git a/main.js b/main.js
new file mode 100644
index 0000000..a849dd4
--- /dev/null
+++ b/main.js
@@ -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"
+ }
+}