summaryrefslogtreecommitdiff
path: root/webcards/scripts
diff options
context:
space:
mode:
Diffstat (limited to 'webcards/scripts')
-rw-r--r--webcards/scripts/cards/card.js123
-rw-r--r--webcards/scripts/cards/deck.js180
-rw-r--r--webcards/scripts/cards/drag.js111
-rw-r--r--webcards/scripts/client.js146
-rw-r--r--webcards/scripts/cookie.js27
-rw-r--r--webcards/scripts/gui/chat.js149
-rw-r--r--webcards/scripts/gui/input.js182
-rw-r--r--webcards/scripts/gui/lobby.js212
-rw-r--r--webcards/scripts/gui/table.js75
-rw-r--r--webcards/scripts/socket/message.js18
-rw-r--r--webcards/scripts/socket/sock.js48
-rw-r--r--webcards/scripts/theme.js32
12 files changed, 808 insertions, 495 deletions
diff --git a/webcards/scripts/cards/card.js b/webcards/scripts/cards/card.js
index 932a22c..750d124 100644
--- a/webcards/scripts/cards/card.js
+++ b/webcards/scripts/cards/card.js
@@ -1,103 +1,110 @@
+'use strict';
+
+// Possible positions of content in a card
const CardPos = ["top", "topl", "topr", "mid", "midt", "midb", "bot", "botl", "botr", "all"];
// Card class represents one card.
// Every card should have a deck.
// Use deck.appendCard or deck.prependCard to make a card visible
-function Card (data) {
- this.e = document.createElement("card");
- this.generateElements(data);
- this.e.style.left = "0px";
- this.e.style.top = "0px";
-}
-
-// Internal
-Card.prototype = {
- // Main generation func, only for use in contructor
- generateElements: function (data) {
- while(this.e.firstElementChild != null)
- this.e.firstElementChild.remove();
-
- switch (typeof data) {
- case "object":
- this.generateObjectCard(data, this.e);
- break;
- case "string":
- this.generateBasicCard(data, this.e);
- break;
- default:
- this.generateErrorCard(this.e);
- }
- },
+class Card {
+ constructor (data)
+ {
+ this.e = document.createElement("card");
+ this.generateElements(data);
+ this.e.style.left = "0px";
+ this.e.style.top = "0px";
+ }
// Generate a card with basic text only
- generateBasicCard: function (data, el) {
+ static generateBasicCard (data, el)
+ {
let t = document.createElement("carea");
t.className = "mid";
t.innerText = data;
el.appendChild(t);
- },
-
- // Generate a card with rich visuals
- generateObjectCard: function (data, el) {
-
- // Check for an asset URL
- if (typeof data.assetURL != "string") {
- data.assetURL = "";
- }
-
- // Set card styles
- for (let i in data.style) {
- el.style[i] = data.style[i];
- }
+ }
- // Generate card areas.
- for (let i in CardPos) {
- if (typeof data[CardPos[i]] == "object")
- el.appendChild(this.generateCArea(data[CardPos[i]], CardPos[i], data.assetURL));
- }
- },
+ // Generate a card with a simple error message.
+ static generateErrorCard (el)
+ {
+ Card.generateBasicCard("Card Error: data", el);
+ }
- generateCArea: function (data, carea, assetURL) {
+ // Generate an area of a card
+ static generateCArea (data, carea, assetURL)
+ {
// Create and set area
let area = document.createElement("carea");
area.className = carea;
// Create inner area text and images
- for (let i in data) {
+ for (let i in data)
+ {
if (i == "style")
+ {
for (j in data.style)
area.style[j] = data.style[j];
+ }
- if (data[i].type == "text") {
+ if (data[i].type == "text")
+ {
let e = document.createElement("ctext");
e.innerText = data[i].text;
- for (let j in data[i].style) {
+ for (let j in data[i].style)
e.style[j] = data[i].style[j];
- }
area.appendChild(e);
- } else if (data[i].type == "image") {
+ }
+ else if (data[i].type == "image")
+ {
let e = document.createElement("cimage");
e.style.backgroundImage = "url(\"" + assetURL + data[i].image + "\")";
+ for (let j in data[i].style)
+ e.style[j] = data[i].style[j];
+
area.appendChild(e);
}
}
return area;
- },
+ }
+
+ // Generate a card with rich visuals
+ static generateObjectCard (data, el)
+ {
+ // Generate card areas.
+ for (let i in CardPos)
+ {
+ if (typeof data[CardPos[i]] == "object")
+ el.appendChild(this.generateCArea(data[CardPos[i]], CardPos[i], data.assetURL));
+ }
+ }
- generateErrorCard: function(el)
+ generateElements (data)
{
- this.generateBasicCard("Card Error: data", el);
- },
+ while(this.e.firstElementChild != null)
+ this.e.firstElementChild.remove();
- setPos: function(p)
+ switch (typeof data)
+ {
+ case "object":
+ Card.generateObjectCard(data, this.e);
+ break;
+ case "string":
+ Card.generateBasicCard(data, this.e);
+ break;
+ default:
+ Card.generateErrorCard(this.e);
+ }
+ }
+
+ setPos (p)
{
this.e.style.setProperty("--cpos", p);
}
-}; \ No newline at end of file
+}
diff --git a/webcards/scripts/cards/deck.js b/webcards/scripts/cards/deck.js
index a02142d..6da24b0 100644
--- a/webcards/scripts/cards/deck.js
+++ b/webcards/scripts/cards/deck.js
@@ -1,67 +1,87 @@
+'use strict';
+
// Deck class represents multiple cards.
// Can be arranged in multiple ways.
-function Deck (options = {mode: "stack", smode: "one", sct: 0, pos: [0, 0]}){
- this.cards = [];
-
- // View mode
- // infdraw - infinite draw. always appears as if there are multiple cards
- // stack - stack mode
- // strip
- // horizontal
- // left (strip-hl)
- // right (strip-hr)
- // vertical
- // up (strip-vu)
- // down (strip-vd)
- this.inf = options.mode == "infdraw";
-
- // Select mode - controls what other cards are selected when one card is selected
- // above - selectes cards above the selected one
- // below - selects cards below the selected one
- // around - selects cards above and below
- // one - selects only card chosen
- // all - selects all cards when card selected
- this.smode = options.smode;
-
- // Select count (negative defaults to 0)
- // above - controls number of cards above clicked are selected
- // below - controls number of cards below clicked are selected
- // around
- // number - number above and below selected
- // array - [first number: number above selected] [second number: number below selected]
- // one - no effect
- // all - no effect
- this.sct = options.sct > 0 ? options.sct : 0;
+// Decks work as FIFO
+class Deck {
- // Position
- // array of where the deck is centered
- this.x = options.pos[0];
- this.y = options.pos[1];
-
- this.e = document.createElement("deck");
- this.e.style.left = this.x + "px";
- this.e.style.top = this.y + "px";
- this.e.setAttribute("mode", options.mode);
-}
+ cards = [];
+ inf = false;
+ smode = "";
+ sct = 0;
+ x = 0;
+ y = 0;
+ e = null;
+
+ constructor(options = {mode: "stack", smode: "one", sct: 0, pos: [0, 0]})
+ {
+ // View mode
+ // infdraw - infinite draw. always appears as if there are multiple cards
+ // stack - stack mode
+ // strip
+ // horizontal
+ // left (strip-hl)
+ // right (strip-hr)
+ // vertical
+ // up (strip-vu)
+ // down (strip-vd)
+ this.inf = options.mode == "infdraw";
+
+ // Select mode - controls what other cards are selected when one card is selected
+ // above - selectes cards above the selected one
+ // below - selects cards below the selected one
+ // around - selects cards above and below
+ // one - selects only card chosen
+ // all - selects all cards when card selected
+ this.smode = options.smode;
+
+ // Select count (negative defaults to 0)
+ // above - controls number of cards above clicked are selected
+ // below - controls number of cards below clicked are selected
+ // around
+ // number - number above and below selected
+ // array - [first number: number above selected] [second number: number below selected]
+ // one - no effect
+ // all - no effect
+ this.sct = options.sct > 0 ? options.sct : 0;
+
+ // Position
+ // array of where the deck is centered
+ this.x = options.pos[0];
+ this.y = options.pos[1];
+
+ this.e = document.createElement("deck");
+ this.e.style.left = this.x + "px";
+ this.e.style.top = this.y + "px";
+ this.e.setAttribute("mode", options.mode);
+ }
-//Decks work as FIFO
-Deck.prototype = {
- // Add a card to the front of the deck
- appendCard: function(card) {
+ updatePos()
+ {
+ let len = this.cards.length - 1;
+ for(let i in this.cards)
+ this.cards[i].setPos(len-i);
+ this.updateCount();
+ }
+
+ appendCard(card)
+ {
this.cards.push(card);
this.e.appendChild(card.e);
this.updatePos();
- },
+
+ }
- // Add a card to the back of the deck
- prependCard: function(card) {
+ prependCard(card)
+ {
this.cards.unshift(card);
this.e.prepend(card.e);
card.setPos(this.cards.length - 1);
- },
+ this.updateCount();
+ }
- // Add a card at the index specified
- addCardAt: function(card, index) {
+ addCardAt(card, index)
+ {
if(index < 0 || index > this.cards.length)
return
@@ -74,11 +94,12 @@ Deck.prototype = {
temp[temp.length - 1].e.after(card.e);
temp.push(card);
this.cards.unshift(...temp);
+ this.updatePos();
}
- },
+ }
- // Swap the cards at the specified indexes
- swapCard: function(index1, index2) {
+ swapCards(index1, index2)
+ {
if(index1 < 0 || index1 >= this.cards.length || index2 < 0 || index2 >= this.cards.length)
return
@@ -88,31 +109,38 @@ Deck.prototype = {
this.cards[index1 - 1].e.after(this.cards[index1]);
this.cards[index2 - 1].e.after(this.cards[index2]);
- },
-
- // Remove the card at the front of the deck (index length - 1), returns the card removed (if any)
- removeFront: function() {
- return this.removeCard(this.cards.length - 1);
- },
-
- // Remove the card at the back of the deck (index 0), returns the card removed (if any)
- removeBack: function() {
- return this.removeCard(0);
- },
-
- // Remove a card from the deck, returning the card element
- removeCard: function(index) {
+ }
+ removeCard(index)
+ {
if(index < 0 || index >= this.cards.length)
return
this.e.removeChild(this.cards[index].e);
- return this.cards.splice(index, 1)[0];
- },
+ let c = this.cards.splice(index, 1)[0];
- updatePos: function() {
- let len = this.cards.length - 1;
- for(let i in this.cards)
- this.cards[i].setPos(len-i);
+ this.updatePos();
+ return c;
+ }
+
+ removeFront()
+ {
+ return this.removeCard(this.cards.length - 1);
+ }
+
+ removeBack()
+ {
+ return this.removeCard(0);
}
-}; \ No newline at end of file
+
+ updateCount ()
+ {
+ this.e.style.setProperty("--ccount", this.cards.length - 1);
+ }
+
+ isInside(x, y)
+ {
+ var rect = this.e.getBoundingClientRect();
+ return (x > rect.left && x < rect.right && y > rect.top && y < rect.bottom)
+ }
+}
diff --git a/webcards/scripts/cards/drag.js b/webcards/scripts/cards/drag.js
index 54fb797..3b02eff 100644
--- a/webcards/scripts/cards/drag.js
+++ b/webcards/scripts/cards/drag.js
@@ -1,17 +1,23 @@
-function MultiDrag() {
- this.del = false;
- this.drag = [];
- window.addEventListener("mousemove", this.update.bind(this));
- document.body.addEventListener("mouseleave", this.stopDraggingAll.bind(this));
-}
+'use strict';
-MultiDrag.prototype = {
- addDragEl: function(el, ox, oy, px, py, pt) {
+class MultiDrag extends EventTarget {
+ del = false;
+ drag = [];
+ cbs = [];
+
+ constructor() {
+ super();
+
+ window.addEventListener("mousemove", this.update.bind(this));
+ document.body.addEventListener("mouseleave", this.stopDraggingAll.bind(this));
+ }
+
+ addDragEl(el, ox, oy, px, py, pt) {
if(this.del)
return;
-
+
el.style.transitionDuration = "0.04s";
-
+
this.drag.push({
e: el,
osx: ox,
@@ -20,76 +26,103 @@ MultiDrag.prototype = {
pry: py,
ptd: pt
});
-
+
return this.drag.length - 1;
- },
+ }
- dragging: function(e) {
+ dragging(e) {
for(let i in this.drag) {
if(this.drag[i].e == e)
return true;
}
return false;
- },
+ }
- startDragging: function(e) {
+ startDragging(e) {
if(this.del)
return;
-
+
console.log(e);
-
+
if(e.button != 0)
return;
-
- let pos
- if(e.target.parentElement != null)
- pos = e.target.parentElement.getBoundingClientRect();
- else
- pos = e.target.getBoundingClientRect();
+
+ this.dispatchEvent(new Event("dragstart", {target: e.target}));
return this.addDragEl(
e.target,
- e.pageX,
- e.pageY,
+ e.pageX - parseInt(e.target.style.left),
+ e.pageY - parseInt(e.target.style.top),
e.target.style.left,
e.target.style.top,
e.target.style.transitionDuration
);
- },
-
- stopDragging: function(i) {
+ }
+
+ stopDragging(i) {
+ if(this.del)
+ return;
+
this.del = true;
-
+
if (i < 0 || i >= this.drag.length)
return;
+ var cap = {target: null, x: 0, y: 0};
+
this.drag[i].e.style.transitionDuration = this.drag[i].ptd;
+
+ cap.x = parseInt(this.drag[i].e.style.left);
this.drag[i].e.style.left = this.drag[i].prx;
+
+ cap.y = parseInt(this.drag[i].e.style.top);
this.drag[i].e.style.top = this.drag[i].pry;
+
+ cap.target = this.drag.splice(i, 1).e;
+
+ this.del = false;
- this.drag.splice(i, 1);
+ this.dispatchEvent(new Event("dragstop", cap));
+ }
- this.del = false;
- },
+ stopDraggingEl(el) {
+ for(let d of this.drag) {
+ if(d.e === el)
+ this.stopDragging(this.drag.indexOf(d));
+ }
+ }
- stopDraggingAll: function() {
+ stopDraggingAll() {
+ if(this.del)
+ return;
+
this.del = true;
-
+
while (this.drag.length > 0) {
this.drag[0].e.style.transitionDuration = this.drag[0].ptd;
this.drag[0].e.style.left = this.drag[0].prx;
this.drag[0].e.style.top = this.drag[0].pry;
-
+
this.drag.shift();
}
-
+
this.del = false;
- },
- update: function(e) {
+ this.dispatchEvent(new Event("dragstopall"));
+ }
+
+ update(e) {
for (let i = 0; i < this.drag.length && !this.del; i++) {
this.drag[i].e.style.left = e.pageX - this.drag[i].osx + "px";
this.drag[i].e.style.top = e.pageY - this.drag[i].osy + "px";
}
}
-}; \ No newline at end of file
+
+ addTarget(e) {
+ e.addEventListener("mousedown", this.startDragging.bind(this));
+ e.addEventListener("mouseup", this.stopDraggingEl.apply(this, [e]))
+ }
+
+ removeTarget (e) {
+ }
+} \ No newline at end of file
diff --git a/webcards/scripts/client.js b/webcards/scripts/client.js
index 0bf2e75..acb3d90 100644
--- a/webcards/scripts/client.js
+++ b/webcards/scripts/client.js
@@ -1,110 +1,128 @@
+const VERSION = "1.0.0";
+
// Client acts as the message hub for the whole game.
// WebSocket messages come into Client and Client redirects them to the lobby or table based on the state of the game.
// Client also performs the handshake for first starting the connection and messages everyone if the connection errors or closes.
-function Client(serveraddr, game) {
- this.state = "handshake";
-
- this.soc = new SockWorker(serveraddr, "1", this.cb.bind(this));
+class Client{
- this.lob = new Lobby(document.getElementsByClassName("lobby")[0], this.soc);
- this.tab = new Table(document.getElementsByClassName("table")[0], this.soc);
+ constructor (serveraddr, game)
+ {
+ this.socket = new SockWorker(serveraddr, VERSION);
+ this.socket.addEventListener("error", this.socketError.bind(this));
+ this.socket.addEventListener("closed", this.socketClose.bind(this));
+ this.socket.addEventListener("handshake", this.handshake.bind(this));
+ this.socket.addEventListener("menu", this.menu.bind(this));
+ this.socket.addEventListener("game", this.game.bind(this));
- this.game = game;
-}
+ this.lobby = new Lobby(document.getElementsByClassName("lobby")[0], this.socket);
+
+ this.drag = new MultiDrag();
+
+ this.table = new Table(document.getElementsByClassName("table")[0], this.drag, this.socket);
+
+ this.chat = new Chat(document.getElementsByClassName("chat")[0], this.socket);
+ this.chat.addChannel("global");
+ this.chat.switchChannel("global");
+
+ this.game = game;
+ }
-Client.prototype = {
// Initialize the connection
- init: function() {
- this.soc.init();
- },
-
- // Entry point for a message from the server.
- // If it's a close message, we close the game if it is open and change the lobby to reflect the error/close.
- cb: function(m) {
- console.log(m);
-
- if(m.type == "error" || m.type == "closed") {
- var t = m.type;
- t = t[0].toUpperCase() + t.slice(1)
- this.lob.setState(t, "closed", this.soc.server);
- this.tab.handleClose();
- return;
- }
+ init ()
+ {
+ this.socket.init();
+ }
- switch(this.state) {
- case "handshake":
- this.lob.setState("Connected", "ok", this.soc.server);
- this.handshake(m);
- break;
- case "lobby":
- this.lobby(m);
- break;
- case "game":
- break;
- }
- },
+ // Callbacks for if the socket fails or closes
+
+ socketError() {
+ this.lobby.setState("Error", "closed", this.socket.server);
+ this.table.handleClose();
+ }
- // Called when negotiating with the server for the first time and we are determining versions
- handshake: function(m) {
+ socketClose() {
+ this.lobby.setState("Closed", "closed", this.socket.server);
+ this.table.handleClose();
+ }
+
+ // Callback when negotiating with the server for the first time and we are determining versions
+ handshake (m)
+ {
switch (m.type) {
case "verr":
- this.soc.close();
+ this.socket.close();
alert(`Error connecting to server: version of client (${this.version}) not accepted.`);
console.error(`Error connecting to server: version of client (${this.version}) not accepted.`);
console.error(m.data);
return;
- case "lobby":
- this.state = "lobby";
- this.soc.send("ready", "");
+ case "ready":
+ this.socket.send("ready", "");
return;
}
- },
+ }
- // Lobby switch, called when in the lobby and a message arrives from the server
- lobby: function (m) {
+ // Menu switch, called when in the lobby and a message arrives from the server
+ menu (m)
+ {
switch (m.type) {
case "plist":
- this.lob.packList(m.data);
+ this.lobby.packList(m.data);
break;
case "glist":
- this.lob.gameList(m.data, this.game);
+ this.lobby.gameList(m.data, this.game);
this.game = null;
break;
case "players":
- this.lob.players(m.data);
+ this.lobby.players(m.data);
break;
case "gdel":
- this.lob.removeGame(m.data);
+ this.lobby.removeGame(m.data);
break;
case "gadd":
- this.lob.addGame(m.data);
+ this.lobby.addGame(m.data);
break;
case "pdel":
- this.lob.removePlayer(m.data);
+ this.lobby.removePlayer(m.data);
break;
case "padd":
- this.lob.addPlayer(m.data);
+ this.lobby.addPlayer(m.data);
break;
case "pmove":
- this.lob.movePlayer(m.data);
+ this.lobby.movePlayer(m.data);
break;
}
- },
+ }
// Game switch, called when in game and a message arrives from the server
- game: function (m) {
+ game (m)
+ {
switch (m.type) {
}
- },
+ }
- // Reset the lobby and table, then attempt to reopen the connection to the server.
- reset: function() {
- this.state = "handshake";
+ // Callback when a chat event is recieved from the server
+ chat (m)
+ {
+ switch (m.type) {
+ case "delchan":
+ this.chat.deleteChannel(m.data);
+ break;
+ case "newchan":
+ this.chat.addChannel(m.data);
+ break;
+
+ case "message":
+ this.chat.recieveMessage(m.data.type, m.data.data);
+ }
+ }
- this.lob.reset();
- this.tab.reset();
+ // Reset the lobby and table, then attempt to reopen the connection to the server.
+ reset ()
+ {
+ this.lobby.reset();
+ this.table.reset();
- this.soc.init();
+ this.socket.init();
}
-};
+}
diff --git a/webcards/scripts/cookie.js b/webcards/scripts/cookie.js
index 2eb5977..d614af7 100644
--- a/webcards/scripts/cookie.js
+++ b/webcards/scripts/cookie.js
@@ -1,8 +1,7 @@
-function CookieManager() {
-}
+'use strict';
-CookieManager.prototype = {
- getCookie: function(name){
+class Cookies {
+ static getCookie(name){
let cookies = document.cookie.split(";");
for(let i in cookies) {
let cname = cookies[i].trim().split("=")[0];
@@ -11,9 +10,9 @@ CookieManager.prototype = {
}
}
return "";
- },
+ }
- setCookie: function(name, value, data={}) {
+ static setCookie(name, value, data = {}) {
let extra = "";
for(let key in data)
@@ -22,18 +21,16 @@ CookieManager.prototype = {
}
document.cookie = name + "=" + value + extra;
- },
+ }
- setYearCookie: function(name, value) {
+ static setYearCookie(name, value) {
var date = new Date(Date.now());
date.setFullYear(date.getFullYear() + 1);
- this.setCookie(name, value, {expires: date.toUTCString()});
- },
+ Cookies.setCookie(name, value, {expires: date.toUTCString()});
+ }
- removeCookie: function(name) {
+ static removeCookie(name) {
var date = new Date(0);
- this.setCookie(name, "", {expires: date.toUTCString()});
+ Cookies.setCookie(name, "", {expires: date.toUTCString()});
}
-};
-
-var Cookies = new CookieManager(); \ No newline at end of file
+}
diff --git a/webcards/scripts/gui/chat.js b/webcards/scripts/gui/chat.js
new file mode 100644
index 0000000..68b8f5d
--- /dev/null
+++ b/webcards/scripts/gui/chat.js
@@ -0,0 +1,149 @@
+'use strict';
+
+class Chat {
+ constructor(e)
+ {
+ this.chats = [];
+ this.root = e;
+ e.getElementsByClassName("toggle-chat")[0].onclick = this.toggle.bind(this);
+ }
+
+ getChannel (name)
+ {
+ for(let i in this.chats)
+ {
+ if (this.chats[i].name == name)
+ {
+ return this.chats[i];
+ }
+ }
+
+ return null;
+ }
+
+ isActive (name)
+ {
+ for(let i in this.chats)
+ {
+ if (this.chats[i].name == name)
+ {
+ if(this.chats[i].btn.getAttribute("active") == "true")
+ return true;
+ return false;
+ }
+ }
+
+ return false;
+ }
+
+ addChannel (name, follow = true)
+ {
+ if(this.getChannel(name) != null)
+ return;
+
+ let d = document.createElement("div");
+ let b = document.createElement("button");
+
+ this.root.getElementsByClassName("chat-select")[0].appendChild(b);
+
+ b.setAttribute("active", false);
+
+ b.onclick = this.switchChannel.bind(this, name);
+
+ b.innerText = name[0].toUpperCase() + name.slice(1).toLowerCase();
+
+ d.className = "chat-text";
+
+ this.chats.push({name: name, e: d, btn: b});
+
+ if(follow)
+ this.switchChannel(name)
+ }
+
+ getActiveChannel ()
+ {
+ for(let i in this.chats)
+ {
+ if (this.chats[i].btn.getAttribute("active") == "true")
+ {
+ return this.chats[i];
+ }
+ }
+
+ return null;
+ }
+
+ switchChannel (name)
+ {
+ let c = this.getChannel(name);
+
+ if(c == null)
+ return;
+
+ if(this.getActiveChannel() != null)
+ this.getActiveChannel().btn.setAttribute("active", false);
+
+ c.btn.setAttribute("active", true);
+ var ct = this.root.getElementsByClassName("chat-text")[0];
+ ct.replaceWith(c.e);
+
+ c.e.scroll({
+ top: c.e.scrollTopMax
+ });
+ }
+
+ recieveMessage (channel, msg)
+ {
+ let c = this.getChannel(channel);
+
+ if(c == null)
+ return;
+
+ let autoscroll = c.e.scrollTop == c.e.scrollTopMax;
+
+ let csp = document.createElement("span");
+ csp.style.color = msg.color;
+ csp.innerText = msg.user + ": ";
+ let tsp = document.createElement("span");
+ tsp.innerText = msg.text;
+ let d = document.createElement("div");
+ d.appendChild(csp);
+ d.appendChild(tsp);
+
+ c.e.appendChild(d);
+
+ if(autoscroll)
+ c.e.scroll({top: c.e.scrollTopMax});
+ }
+
+ clearChannel (name)
+ {
+ let c = this.getChannel(name);
+ if(c == null)
+ return;
+
+ while(c.e.firstElementChild != null)
+ c.e.firstElementChild.remove();
+ }
+
+ deleteChannel (name)
+ {
+ let c = this.getChannel(name);
+ if(c == null)
+ return;
+
+ while(c.e.firstElementChild != null)
+ c.e.firstElementChild.remove();
+
+ c.btn.remove();
+
+ this.chats.splice(this.chats.indexOf(c), 1);
+ }
+
+ toggle () {
+ if(this.root.getAttribute("show") != "true")
+ this.root.setAttribute("show", "true");
+ else
+ this.root.setAttribute("show", "false");
+ }
+}
diff --git a/webcards/scripts/gui/input.js b/webcards/scripts/gui/input.js
index b0bbec0..6ed3d39 100644
--- a/webcards/scripts/gui/input.js
+++ b/webcards/scripts/gui/input.js
@@ -1,29 +1,9 @@
-function customSelectValue (el) {
- var sel = el.getAttribute("selected");
-
- if(typeof sel != "undefined") {
- return el.children[parseInt(sel)].getAttribute("value");
- }
-
- return "";
-}
-
-function customSelectOption (el) {
- var sn = Array.prototype.indexOf.call(el.parentElement.children, el);
- var psn = el.parentElement.getAttribute("selected");
-
- if(typeof psn == "string")
- el.parentElement.children[parseInt(psn)].setAttribute("selected", false);
+'use strict';
- if(typeof sn == "string")
- el.parentElement.setAttribute("selected", parseInt(sn));
-
- el.setAttribute("selected", true);
- el.parentElement.setAttribute("selected", parseInt(sn));
-}
-
-var InputFuncs = {
- createInput: function(type = "text", id) {
+//This whole clusterfuq of functions needs fixing.
+class MakeInput {
+ static createInput(type = "text", id)
+ {
var el = document.createElement("input");
el.setAttribute("type", type);
@@ -35,38 +15,41 @@ var InputFuncs = {
}
return el;
- },
+ }
- inputLabel(text, id) {
+ static inputLabel(text, id)
+ {
var el = document.createElement("label");
el.innerText = text;
if(typeof id == "string")
el.setAttribute("for", id);
return el;
- },
+ }
- colorInput: function(value, id) {
- var el = this.createInput("color", id);
+ static colorInput (value, id) {
+ var el = MakeInput.createInput("color", id);
el.value = value;
return el;
- },
+ }
- textInput: function(value, placeholder, id) {
- var el = this.createInput("text", id);
+ static textInput (value, placeholder, id)
+ {
+ var el = MakeInput.createInput("text", id);
el.setAttribute("placeholder", placeholder);
el.value = value;
return el;
- },
+ }
- numberInput: function(value, id) {
- var el = this.createInput("number", id);
+ static numberInput (value, id)
+ {
+ var el = MakeInput.createInput("number", id);
el.value = value;
return el;
- },
+ }
//To fix
- fileInput: function(value, id) {
- var el = this.createInput("file", id);
+ static fileInput (value, id) {
+ var el = MakeInput.createInput("file", id);
el.value = value;
@@ -89,38 +72,38 @@ var InputFuncs = {
}
return el;
- },
+ }
- checkboxInput: function(checked = false, id) {
- var el = this.createInput("checkbox", false, id);
+ static checkboxInput (checked = false, id) {
+ var el = MakeInput.createInput("checkbox", false, id);
if(checked)
el.setAttribute("checked");
return el;
- },
+ }
- radioInput: function(group, value, checked = false, id) {
- var el = this.createInput("radio", false, id);
+ static radioInput (group, value, checked = false, id) {
+ var el = MakeInput.createInput("radio", false, id);
el.setAttribute("name", group);
el.setAttribute("value", value);
if(checked)
el.checked = true;
return el;
- },
+ }
- radioInputs: function(group, names, values, checked = 0, id) {
+ static radioInputs (group, names, values, checked = 0, id) {
let toWrap = [];
for(let i = 0; i < values.length; i++) {
- toWrap.push(this.inputLabel(names[i], group+"-"+i));
+ toWrap.push(MakeInput.inputLabel(names[i], group+"-"+i));
if(i == checked)
- toWrap.push(this.radioInput(group, values[i], true, group+"-"+i));
+ toWrap.push(MakeInput.radioInput(group, values[i], true, group+"-"+i));
else
- toWrap.push(this.radioInput(group, values[i], false, group+"-"+i));
+ toWrap.push(MakeInput.radioInput(group, values[i], false, group+"-"+i));
toWrap.push(document.createElement("br"));
}
- var wrapper = this.wrapInputs("radio", ...toWrap);
+ var wrapper = MakeInput.wrapInputs("radio", ...toWrap);
wrapper.getValue = function() {
for(let i = 0; i < this.children.length; i++){
@@ -133,9 +116,9 @@ var InputFuncs = {
wrapper.setAttribute("id", id);
return wrapper;
- },
+ }
- selectOption: function(text, value, selected) {
+ static selectOption (text, value, selected) {
var so = document.createElement("div");
so.innerText = text;
so.setAttribute("value", value);
@@ -145,9 +128,9 @@ var InputFuncs = {
so.setAttribute("selected", true);
return so
- },
+ }
- selectInput: function(names, values, id, select = 0) {
+ static selectInput (names, values, id, select = 0) {
var se = document.createElement("div");
se.className = "input-select";
se.setAttribute("tabindex", 0);
@@ -155,20 +138,20 @@ var InputFuncs = {
for(let i in names)
{
- se.appendChild(this.selectOption(names[i], values[i], i == select));
+ se.appendChild(MakeInput.selectOption(names[i], values[i], i == select));
}
if(typeof id == "string")
se.setAttribute("id", id);
- var wrapper = this.wrapInputs("select", se);
- wrapper.getValue = customSelectValue.bind(null, se);
+ var wrapper = MakeInput.wrapInputs("select", se);
+ wrapper.getValue = MakeInput.selValue.bind(null, se);
wrapper.setAttribute("tabindex", 0);
return wrapper;
- },
+ }
- wrapInputs: function(type, ...el) {
+ static wrapInputs (type, ...el) {
var wrapper = document.createElement("div");
wrapper.className = "input-container";
@@ -181,37 +164,68 @@ var InputFuncs = {
return wrapper;
}
-};
-function Settings (settings = {}) {
- this.settings = settings;
-
- this.genSettings();
+ static selValue (el) {
+ let sel = parseInt(el.getAttribute("selected"));
+
+ if(typeof sel != "undefined") {
+ return el.children[sel].getAttribute("value");
+ }
+
+ return "";
+ }
+
+ static selOption (el) {
+ let sn = Array.prototype.indexOf.call(el.parentElement.children, el);
+ let psn = parseInt(el.parentElement.getAttribute("selected"));
+
+ if(Number.isInteger(psn))
+ el.parentElement.children[psn].setAttribute("selected", false);
+
+ el.parentElement.setAttribute("selected", sn);
+ el.setAttribute("selected", true);
+ }
}
-Settings.prototype = {
- getSettings: function() {
- var out = {};
- for(let key in this.settings) {
-
- }
- },
+class Settings {
+ constructor (template = {})
+ {
+ this.settings = Settings.genSettings(template);
+ }
- putSettings: function (el) {
- for(let key in this.settings) {
- el.appendChild(this.settings[key]);
- }
- },
+ static genSettings (template)
+ {
+ var out = {};
- genSettings: function() {
- for(let key in this.settings) {
- switch(this.settings[key].type) {
+ for(let key in template)
+ {
+ switch(template[key].type)
+ {
case "radio":
- this.settings[key] = inputFuncs.radioInputs(...this.settings[key].args);
+ out[key] = MakeInput.radioInputs(...template[key].args);
+ break;
default:
- if(typeof inputFuncs[this.settings[key].type+"Input"] != null)
- this.settings[key] = inputFuncs[this.settings[key].type+"Input"](...this.settings[key].args);
+ if(typeof MakeInput[template[key].type+"Input"] != null)
+ out[key] = MakeInput[template[key].type+"Input"](...template[key].args);
}
}
+
+ return out;
+ }
+
+ getSettings ()
+ {
+ var out = {};
+
+ for(let key in this.settings)
+ out[key] = this.settings[key].getValue();
+
+ return out;
}
-}; \ No newline at end of file
+
+ putSettings (el)
+ {
+ for(let key in this.settings)
+ el.appendChild(this.settings[key]);
+ }
+}
diff --git a/webcards/scripts/gui/lobby.js b/webcards/scripts/gui/lobby.js
index 07f8223..7d2b6cd 100644
--- a/webcards/scripts/gui/lobby.js
+++ b/webcards/scripts/gui/lobby.js
@@ -1,39 +1,93 @@
-// Lobby manages the players and games provided by the server and allows users to join or create their own games.
-function Lobby(el){
- this.root = el;
-
- this.e = {
- status: el.getElementsByClassName("status")[0],
- addr: el.getElementsByClassName("addr")[0],
- games: el.getElementsByClassName("games")[0],
- settings: el.getElementsByClassName("settings")[0],
-
- stats: {
- game: document.getElementById("game"),
- packs: document.getElementById("packs"),
- online: document.getElementById("online"),
- ingame: document.getElementById("ingame"),
- pubgame: document.getElementById("pubgame")
- }
- };
-
- this.top = new TopBar(document.getElementsByClassName("topbar")[0]);
-
- this.init = false;
- this.online = [];
- this.games = [];
- this.packs = [];
- this.players = [];
+// ###############
+// # TopBar Code #
+// ###############
+
+// TopBar represents the bar at the top of the screen when client is in the lobby.
+
+class TopBar{
+ constructor (el)
+ {
+ this.root = el;
+
+ this.newGame = el.getElementsByClassName("new-game")[0];
+ this.mobileSettings = el.getElementsByClassName("mobile-settings")[0];
+ this.status = el.getElementsByClassName("status")[0];
+ }
+
+ // Set color of status bar
+ setStatus (s) {
+ this.status.setAttribute("s", s);
+ }
+
+ // Toggle showing the new game screen
+ toggleNewGame () {
+ if (this.newGame.style.display !== "none")
+ this.newGame.style.display = "none";
+ else
+ this.newGame.style.display = "block";
+ }
+
+ // Toggle showing the mobile settings
+ toggleMobileSettings () {
+ if (this.mobileSettings.style.display !== "none")
+ this.mobileSettings.style.display = "none";
+ else
+ this.mobileSettings.style.display = "block";
+ }
}
-Lobby.prototype = {
+// #############
+// # Game code #
+// #############
+
+// Game represents a single game in the lobby view. It has methods for setting up the elements and such.
+class Game{
+ constructor (name, packs, maxp, id)
+ {
+ }
+}
+
+// ##############
+// # Lobby Code #
+// ##############
+
+// Lobby manages the players and games provided by the server and allows users to join or create their own games.
+class Lobby {
+ constructor (el)
+ {
+ this.root = el;
+
+ this.e = {
+ status: el.getElementsByClassName("status")[0],
+ addr: el.getElementsByClassName("addr")[0],
+ games: el.getElementsByClassName("games")[0],
+ settings: el.getElementsByClassName("settings")[0],
+
+ stats: {
+ game: document.getElementById("game"),
+ packs: document.getElementById("packs"),
+ online: document.getElementById("online"),
+ ingame: document.getElementById("ingame"),
+ pubgame: document.getElementById("pubgame")
+ }
+ };
+
+ this.top = new TopBar(document.getElementsByClassName("topbar")[0]);
+
+ this.init = false;
+ this.online = [];
+ this.games = [];
+ this.packs = [];
+ this.players = [];
+ }
+
// Set initial pack list
// {data array} array of strings representing pack names
- packList: function(data) {
+ packList (data) {
this.packs = data;
this.top.setPacks(this.packs)
this.e.stats.packs.innerText = this.packs.length();
- },
+ }
// Set initial game list.
// { data object } object containing {games} and {name}
@@ -43,20 +97,20 @@ Lobby.prototype = {
// { data.games[n].packs } list of the pack names used by this game
// { data.games[n].id } room identifier (uuid)
// { data.games[n].max } max players in room
- gameList: function(data) {
+ gameList (data) {
while (this.e.games.firstChild != null) {
this.e.games.remove(this.elements.games.firstChild)
}
for (let i in data.games) {
- let gel = new GameEl(i.name, i.packs, i.id);
+ let gel = new Game(i.name, i.packs, i.id);
this.games.push(gel);
this.e.games.appendChild(gel.getElement());
}
this.e.stats.game.innerText = data.name;
this.e.stats.pubgame.innerText = this.games.length();
- },
+ }
// Set the initial player list.
// { data array } represents a list of player objects from the server
@@ -64,26 +118,26 @@ Lobby.prototype = {
// { data[n].game string } id of the game room (empty if not in game).
// { data[n].color string } css color chosen by player.
// { data[n].uuid string } uuid of the player
- players: function(data) {
+ players (data) {
this.e.stats.online.innerText = this.players.length();
this.init = true;
- },
+ }
// Called when a new public game is created on the server
// { data object } the game object
// { data.name } room name
// { data.packs } list of the pack names used by this game
// { data.id } room identifier (uuid)
- addGame: function(data) {
+ addGame (data) {
- },
+ }
// Called when a new public game is removed on the server
// { data string } the uuid of the game to delete
- removeGame: function(data) {
+ removeGame (data) {
- },
+ }
// Called when a new player enters the lobby.
// { data object } an object representing the player
@@ -91,56 +145,60 @@ Lobby.prototype = {
// { data.game string } id of the game room (empty if not in game).
// { data.color string } css color chosen by player.
// { data.uuid string } uuid of the player
- addPlayer: function(data) {
+ addPlayer (data) {
- },
+ }
// Called when a player modifies their settings in the lobby.
// { data object } new player settings
// { data.name string } non null if the player has changed their name
// { data.color string } non null if the player has changed their color
// { data.uuid string } uuid of player changing their settings
- modPlayer: function(data) {
+ modPlayer (data) {
- },
+ }
// Called when a player moves between the lobby and a game, or between two games
// { data object } new location
// { data.player } uuid of player changing location
// { data.loc } uuid of room player is moving to (empty if moving to lobby)
- movePlayer: function(data) {
+ movePlayer (data) {
- },
+ }
// Called when a player exits the game (from lobby or game)
- // {data string } uuid of player
- removePlayer: function(data) {
+ // { data string } uuid of player
+ removePlayer (data) {
- },
+ }
// Called when the client wants to toggle the new game screen
- newGame: function() {
+ newGame () {
//if(this.init) return;
this.top.toggleNewGame();
- },
+ }
// Called when the client wants to toggle the mobile settings screen
- mobileSettings: function() {
+ mobileSettings () {
//if(this.init) return;
this.top.toggleMobileSettings();
- },
+ }
// Called when the WebSocket state has changed.
- setState: function(text, s, server) {
+ setState (text, s, server) {
this.e.status.setAttribute("s", s);
if(this.e.status.innerText != "Error" || ( this.e.status.innerText == "Error" && text != "Closed"))
this.e.status.innerText = text;
this.e.addr.innerText = server;
this.top.setStatus(s);
- },
+ }
+
+ getState () {
+ return this.e.status.innerText.toLowerCase();
+ }
// Called when we are resetting the game.
- reset: function() {
+ reset () {
while (this.e.games.firstElementChild != null) {
this.e.games.removeChild(this.e.games.firstElementChild)
}
@@ -148,50 +206,4 @@ Lobby.prototype = {
this.setState("Connecting", "loading", this.e.addr.innerText);
this.init = false;
}
-};
-
-// ###############
-// # TopBar Code #
-// ###############
-
-// TopBar represents the bar at the top of the screen when client is in the lobby.
-
-function TopBar(el) {
- this.root = el;
-
- this.newGame = el.getElementsByClassName("new-game")[0];
- this.mobileSettings = el.getElementsByClassName("mobile-settings")[0];
- this.status = el.getElementsByClassName("status")[0];
}
-
-TopBar.prototype = {
- // Set color of status bar
- setStatus: function(s) {
- this.status.setAttribute("s", s);
- },
-
- // Toggle showing the new game screen
- toggleNewGame: function() {
- if (this.newGame.style.display !== "none")
- this.newGame.style.display = "none";
- else
- this.newGame.style.display = "block";
- },
-
- // Toggle showing the mobile settings
- toggleMobileSettings: function() {
- if (this.mobileSettings.style.display !== "none")
- this.mobileSettings.style.display = "none";
- else
- this.mobileSettings.style.display = "block";
- }
-};
-
-// #############
-// # Game code #
-// #############
-
-// GameEl represents a single game in the lobby view. It has methods for setting up the elements and such.
-function GameEl(name, packs, maxp, id) {
-
-} \ No newline at end of file
diff --git a/webcards/scripts/gui/table.js b/webcards/scripts/gui/table.js
index 2776f80..c4878a0 100644
--- a/webcards/scripts/gui/table.js
+++ b/webcards/scripts/gui/table.js
@@ -1,32 +1,79 @@
// Table represents and manages the actual game. It accepts inputs from the server and tries to query the server when the player makes a move.
-function Table(el, soc) {
- this.root = el;
- this.soc = soc;
-}
+class Table{
+ constructor(e, drag, socket) {
+ this.root = e;
+ this.drag = drag;
+
+ this.root.addEventListener("mouseup", drag.stopDraggingAll.bind(drag));
+
+ //drag.addEventListener("dragstop", );
+
+ this.socket = socket;
+
+ this.decks = [];
+ }
-Table.prototype = {
-
- openTable: function(){
+ openTable ()
+ {
let state = this.root.getAttribute("state")
if((state == "close" || state == "closed") && state != "") {
this.root.setAttribute("state", "closed");
setTimeout(this.root.setAttribute.bind(this.root), 50, "state", "open");
}
- },
+ }
- closeTable: function(){
+ closeTable ()
+ {
let state = this.root.getAttribute("state")
if(state != "close" && state != "closed") {
this.root.setAttribute("state", "");
setTimeout(this.root.setAttribute.bind(this.root), 50, "state", "close");
}
- },
+ }
- handleClose: function() {
+ handleClose ()
+ {
this.reset();
- },
+ }
+
+ reset ()
+ {
+ while(this.root.firstElementChild != null)
+ this.root.firstElementChild.remove();
+
+ this.decks = [];
- reset: function() {
this.closeTable();
+ this.drag.stopDraggingAll();
}
-} \ No newline at end of file
+
+ /* Deck and card functions */
+ newDeck(options)
+ {
+ var d = new Deck(options);
+ this.decks.push(d);
+ this.root.appendChild(d.e);
+ }
+
+ newCard(data, deck = 0)
+ {
+ var c = new Card(data);
+ this.decks[deck].appendCard(c);
+ this.drag.addTarget(c.e);
+ }
+
+ checkDeck(x, y)
+ {
+ for(let d of this.decks)
+ {
+ if(d.isInside(x, y))
+ return true;
+ }
+ return false;
+ }
+
+ dragCheck(cap)
+ {
+ console.log(cap);
+ }
+}
diff --git a/webcards/scripts/socket/message.js b/webcards/scripts/socket/message.js
index 5e821c4..044027d 100644
--- a/webcards/scripts/socket/message.js
+++ b/webcards/scripts/socket/message.js
@@ -1,14 +1,18 @@
-function Message(type, data){
- this.t = type;
- this.d = data;
-}
+'use strict';
+
+class Message{
+ constructor (type, data)
+ {
+ this.t = type;
+ this.d = data;
+ }
-Message.prototype = {
- stringify: function(){
+ stringify ()
+ {
var dat = this.d
if(typeof dat !== "string"){
dat = JSON.stringify(dat);
}
return JSON.stringify({type: this.t, data: dat});
}
-};
+}
diff --git a/webcards/scripts/socket/sock.js b/webcards/scripts/socket/sock.js
index cf06a5e..4eacc18 100644
--- a/webcards/scripts/socket/sock.js
+++ b/webcards/scripts/socket/sock.js
@@ -1,13 +1,15 @@
// A wrapper around the wrapper
-function SockWorker(serveraddr, version, callback) {
- this.server = serveraddr;
- this.version = version;
- this.cb = callback;
-}
+class SockWorker extends EventTarget{
+ constructor (serveraddr, version)
+ {
+ super();
+
+ this.server = serveraddr;
+ this.version = version;
+ }
-SockWorker.prototype = {
// Initialize the connection.
- init: function() {
+ init () {
if(this.server == "" || this.server == null) {
return;
}
@@ -22,42 +24,42 @@ SockWorker.prototype = {
} catch (e) {
this.err();
}
- },
+ }
// Called when the connection connects to the server
- o: function() {
+ o () {
this.send("version", this.version);
- },
+ }
// Called when the connection gets a message from the server
// Attempts to turn the message into a usable object and pass it to the callback
- msg: function(e) {
+ msg (e) {
if(typeof e.data == "string") {
var dat = JSON.parse(e.data)
- this.cb(dat);
+ this.dispatchEvent(new Event(dat.type, dat.data));
}
- },
+ }
// Called when the connection closes.
// Passes a close object to the callback.
- c: function() {
- this.cb({type: "close", data: ""});
- },
+ c () {
+ this.dispatchEvent(new Event("closed"));
+ }
// Called when the connection encounters an error.
// Passes an error to the callback
- err: function() {
- this.cb({type: "error", data: ""});
- },
+ err () {
+ this.dispatchEvent(new Event("error"));
+ }
// Call to close the connection to the server
- close: function() {
+ close () {
this.socket.close();
- },
+ }
// Send a message to the server
- send: function(type, data) {
+ send (type, data) {
var m = new Message(type, data);
this.socket.send(m.stringify())
}
-}; \ No newline at end of file
+}
diff --git a/webcards/scripts/theme.js b/webcards/scripts/theme.js
index 8e69377..e93f5b5 100644
--- a/webcards/scripts/theme.js
+++ b/webcards/scripts/theme.js
@@ -1,24 +1,26 @@
-function Theme(){
- this.t = document.getElementById("theme");
-}
+'use strict';
+
+class Theme{
+ static theme = document.getElementById("theme");
-Theme.prototype = {
- init: function() {
+ static init()
+ {
if(Cookies.getCookie("theme") == ""){
Cookies.setYearCookie("theme", "styles/themes/colors-base.css");
}
- },
+ }
- restore: function() {
- this.init();
- this.t.setAttribute("href", Cookies.getCookie("theme") + "?v=" + Date.now());
- },
+ static restore()
+ {
+ Theme.init();
+ Theme.theme.setAttribute("href", Cookies.getCookie("theme") + "?v=" + Date.now());
+ }
- set: function(sheet) {
+ static set(sheet)
+ {
Cookies.setYearCookie("theme", sheet);
- this.restore();
+ Theme.restore();
}
-};
+}
-var GlobalTheme = new Theme();
-GlobalTheme.restore();
+Theme.restore(); \ No newline at end of file