diff --git a/public_html/index.html b/public_html/index.html
index 0c9aec9..743795d 100644
--- a/public_html/index.html
+++ b/public_html/index.html
@@ -12,6 +12,7 @@
InstantChat
+
diff --git a/public_html/js/client.js b/public_html/js/client.js
index 5b90372..51b6869 100644
--- a/public_html/js/client.js
+++ b/public_html/js/client.js
@@ -1,7 +1,18 @@
"use strict";
-class Client {
+/**
+ * Client class that implements the InstantChat protocol using WebSockets.
+ *
+ * Dispatches the following events which can be subscribed/unsubscribed using .on() and .off():
+ * - initialized: Connection to server has been established and initialized, ready to send messages.
+ * - disconnected: Connection has been closed.
+ * - connectionError: Some connection error occurred.
+ * - receivedMessage: Chat message has been received. Data: object {from: 'username', text: 'text'}
+ */
+class Client extends EventDispatcher {
constructor(wsUri) {
+ super();
+
this.wsUri = wsUri;
// Create WebSocket and set internal callbacks
@@ -16,17 +27,17 @@ class Client {
// Internal WebSocket event handlers
_onSocketOpen(evt) {
console.log("Connected to " + this.wsUri);
-
- // Send init command containing chat ID and nickname
this.sendInit();
}
_onSocketClose(evt) {
console.log("Connection closed (code " + evt.code + ").");
+ this.dispatch("disconnected");
}
_onSocketError(evt) {
console.error("Connection error: ", evt);
+ this.dispatch("connectionError");
}
_onSocketMessage(evt) {
@@ -76,16 +87,19 @@ class Client {
const msg = JSON.parse(msgString);
switch (msg.type) {
- // Response to "init" command
+ // Response to 'init' command (doesn't have much content, I guess)
case "init":
- // TODO
console.log("Got init response: ", msg);
+ this.dispatch("initialized");
break;
// Incoming chat message
case "message":
- // TODO
- console.log("Got message event: from '" + msg.from + "', text '" + msg.text + "'");
+ console.log("Received chat message from '" + msg.from + "', text '" + msg.text + "'");
+ this.dispatch("receivedMessage", {
+ from: msg.from,
+ text: msg.text,
+ });
break;
// TODO Topic change, user join/leave, error, ...
diff --git a/public_html/js/events.js b/public_html/js/events.js
new file mode 100644
index 0000000..7662ff7
--- /dev/null
+++ b/public_html/js/events.js
@@ -0,0 +1,42 @@
+"use strict";
+
+/**
+ * Base class to implement an event system in any class. Events can be dispatched and
+ * subscribed/unsubscribed. Events can have multiple registered callbacks.
+ */
+class EventDispatcher {
+ constructor() {
+ this._events = {};
+ }
+
+ /**
+ * Dispatch a named event. Calls all callbacks that are subscribed to this event.
+ */
+ dispatch(eventName, data = null) {
+ if (this._events[eventName]) {
+ this._events[eventName].forEach((callback) => {
+ callback(data);
+ });
+ }
+ }
+
+ /**
+ * Subscribe to an event.
+ */
+ on(eventName, callback) {
+ if (!this._events[eventName]) {
+ this._events[eventName] = [];
+ }
+ this._events[eventName].push(callback);
+ }
+
+ /**
+ * Unsubscribe from an event. Not sure how to unsubscribe anonymous functions though.
+ * If callback is not found, nothing happens.
+ */
+ off(eventName, callback) {
+ if (this._events[eventName]) {
+ this._events[eventName] = this._events[eventName].filter(item => item !== callback);
+ }
+ }
+}
diff --git a/public_html/js/ui.js b/public_html/js/ui.js
index 1afd0d0..5411255 100644
--- a/public_html/js/ui.js
+++ b/public_html/js/ui.js
@@ -7,4 +7,21 @@ let client;
(function() {
const wsUri = AppSettings.serverWsUri;
client = new Client(wsUri);
+
+ // Test events
+ client.on("initialized", () => {
+ console.log("UI: Connection initialized!");
+
+ // Send a test message
+ client.sendChatMessage("Meow meow! :3");
+ });
+ client.on("disconnected", () => {
+ console.log("UI: Connection closed!");
+ });
+ client.on("connectionError", () => {
+ console.log("UI: Connection error! :()");
+ });
+ client.on("receivedMessage", (msg) => {
+ console.log("UI: Message from '" + msg.from + "', text: '" + msg.text + "'");
+ });
})();