summaryrefslogtreecommitdiff
path: root/scripts
diff options
context:
space:
mode:
authorKyle Gunger <kgunger12@gmail.com>2021-10-15 21:01:22 -0400
committerKyle Gunger <kgunger12@gmail.com>2021-10-15 21:01:22 -0400
commit6c4896d3aa9d618f024b54c8d51f25ca3f625744 (patch)
treea70ceb0b6d477141e7791b21cb6eaa79316529df /scripts
parentfcf01353f94b11b8ca6db8ead14d2ec89a0275f4 (diff)
[Themes] Theme selection and small fixes
Diffstat (limited to 'scripts')
-rw-r--r--scripts/client.js9
-rw-r--r--scripts/cookie.js6
-rw-r--r--scripts/gui/chat.js25
-rw-r--r--scripts/gui/input.js37
-rw-r--r--scripts/gui/lobby.js391
-rw-r--r--scripts/gui/table.js18
-rw-r--r--scripts/theme.js43
7 files changed, 303 insertions, 226 deletions
diff --git a/scripts/client.js b/scripts/client.js
index 7f98c7b..07e2fce 100644
--- a/scripts/client.js
+++ b/scripts/client.js
@@ -55,6 +55,7 @@ class Client{
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.socket.addEventListener("chat", this.chat.bind(this));
this.lobby = new Lobby(document.getElementsByClassName("lobby")[0], this.socket);
@@ -63,8 +64,8 @@ class Client{
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.chat.addChannel("Global");
+ this.chat.switchChannel("Global");
this.settings = new Settings(DefaultUserOps);
this.settings.putSettings(this.lobby.e.settings);
@@ -164,7 +165,9 @@ class Client{
game (m)
{
switch (m.type) {
-
+ case "move":
+ this.table.moveByID(m.data.card, m.data.deck, m.data.pos);
+ break;
}
}
diff --git a/scripts/cookie.js b/scripts/cookie.js
index d614af7..44a0be9 100644
--- a/scripts/cookie.js
+++ b/scripts/cookie.js
@@ -12,7 +12,7 @@ class Cookies {
return "";
}
- static setCookie(name, value, data = {}) {
+ static setCookie(name, value, data = {SameSite: "Strict"}) {
let extra = "";
for(let key in data)
@@ -26,11 +26,11 @@ class Cookies {
static setYearCookie(name, value) {
var date = new Date(Date.now());
date.setFullYear(date.getFullYear() + 1);
- Cookies.setCookie(name, value, {expires: date.toUTCString()});
+ Cookies.setCookie(name, value, {SameSite: "Strict", expires: date.toUTCString()});
}
static removeCookie(name) {
var date = new Date(0);
- Cookies.setCookie(name, "", {expires: date.toUTCString()});
+ Cookies.setCookie(name, "", {SameSite: "Strict", expires: date.toUTCString()});
}
}
diff --git a/scripts/gui/chat.js b/scripts/gui/chat.js
index fa4b88d..8a5db9f 100644
--- a/scripts/gui/chat.js
+++ b/scripts/gui/chat.js
@@ -1,11 +1,17 @@
'use strict';
class Chat {
- constructor(e)
+ constructor(e, soc)
{
this.chats = [];
this.root = e;
+ this.socket = soc;
e.getElementsByClassName("toggle-chat")[0].onclick = this.toggle.bind(this);
+ let cin = e.getElementsByClassName("chat-input")[0];
+ this.chatInput = cin.children[0];
+
+ cin.children[0].addEventListener("keydown", this.checkEnter.bind(this));
+ cin.children[0].addEventListener("click", this.sendMessage.bind(this));
}
getChannel (name)
@@ -50,7 +56,7 @@ class Chat {
b.onclick = this.switchChannel.bind(this, name);
- b.innerText = name[0].toUpperCase() + name.slice(1).toLowerCase();
+ b.innerText = name;
d.className = "chat-text";
@@ -92,6 +98,21 @@ class Chat {
});
}
+ checkEnter(e)
+ {
+ if(e.key === "Enter") {
+ this.sendMessage();
+ }
+ }
+
+ sendMessage ()
+ {
+ var str = this.chatInput.value;
+ this.chatInput.value = "";
+ this.socket.send("chat", str);
+
+ }
+
recieveMessage (channel, msg)
{
let c = this.getChannel(channel);
diff --git a/scripts/gui/input.js b/scripts/gui/input.js
index f72dd91..a44784b 100644
--- a/scripts/gui/input.js
+++ b/scripts/gui/input.js
@@ -199,6 +199,10 @@ class MakeInput {
var wrapper = MakeInput.wrapInputs("select", se);
wrapper.getValue = MakeInput.selValue.bind(null, se);
+ wrapper.getIndex = MakeInput.selIndex.bind(null, se);
+ wrapper.addOption = MakeInput.selAdd.bind(se);
+ wrapper.removeOption = MakeInput.selRem.bind(se);
+ wrapper.setIndex = MakeInput.selSet.bind(se);
wrapper.setAttribute("tabindex", 0);
return wrapper;
@@ -213,18 +217,47 @@ class MakeInput {
return "";
}
+
+ static selIndex (el) {
+ return parseInt(el.getAttribute("selected"));
+ }
- static selOption (el) {
+ static selOption (el, dispatch = true) {
let sn = el.selectIndex;
let psn = parseInt(el.parentElement.getAttribute("selected"));
- if(Number.isInteger(psn))
+ if(Number.isInteger(psn) && psn < el.parentElement.childElementCount)
el.parentElement.children[psn].setAttribute("selected", false);
el.parentElement.setAttribute("selected", sn);
el.setAttribute("selected", true);
+
+ if(dispatch)
+ el.parentElement.parentElement.dispatchEvent(new InputEvent("change"));
}
+ static selSet (index) {
+ MakeInput.selOption(this.children[index], false);
+ }
+
+ static selAdd (name, value) {
+ this.appendChild(MakeInput.selectOption(value, name, this.childElementCount, false));
+ return this.childElementCount - 1;
+ }
+
+ static selRem (index) {
+ if(index >= this.childElementCount)
+ return false;
+
+ this.children[index].remove();
+
+ for(let i = index; i < this.childElementCount; i++) {
+ this.children[index].selectIndex = "" + i;
+ }
+
+ return true;
+ }
+
static titleWrap(el, title) {
var wrapper = document.createElement("div");
wrapper.className = "input-title-wrapper";
diff --git a/scripts/gui/lobby.js b/scripts/gui/lobby.js
index 13f3eab..8242843 100644
--- a/scripts/gui/lobby.js
+++ b/scripts/gui/lobby.js
@@ -6,43 +6,43 @@
// TopBar represents the bar at the top of the screen when client is in the lobby.
class TopBar{
- constructor (el, desktopSettings)
- {
- this.root = el;
- this.desktopSettings = desktopSettings;
-
- 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 (settings) {
- if (this.mobileSettings.style.display !== "none"){
- this.mobileSettings.style.display = "none";
- settings.putSettings(this.desktopSettings);
- } else {
- this.mobileSettings.style.display = "block";
- settings.putSettings(this.mobileSettings);
- }
- }
-
- mobileSettingsOpen() {
- return this.mobileSettings.style.display !== "none"
- }
+ constructor (el, desktopSettings)
+ {
+ this.root = el;
+ this.desktopSettings = desktopSettings;
+
+ 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 (settings) {
+ if (this.mobileSettings.style.display !== "none"){
+ this.mobileSettings.style.display = "none";
+ settings.putSettings(this.desktopSettings);
+ } else {
+ this.mobileSettings.style.display = "block";
+ settings.putSettings(this.mobileSettings);
+ }
+ }
+
+ mobileSettingsOpen() {
+ return this.mobileSettings.style.display !== "none"
+ }
}
// #############
@@ -50,22 +50,32 @@ class TopBar{
// #############
// Game represents a single game in the lobby view. It has methods for setting up the elements and such.
-function createGameEl (options = {id: 0, name: ""}, el)
-{
- let e = document.createElement("div");
- e.className = "game";
-
- let title = document.createElement("h2");
- title.textContent = options.name;
- e.appendChild(title);
-
- let join = document.createElement("button");
- join.className = "join";
- join.textContent = "Join";
- join.addEventListener("click", game.joinGame.bind(game, options.id));
- e.appendChild(join);
-
- el.appendChild(e);
+class Game {
+ constructor(options = {id: 0, name: ""}, el)
+ {
+ this.getID = function () {
+ return options.id;
+ }
+
+ this.getName = function () {
+ return options.name;
+ }
+
+ let e = document.createElement("div");
+ e.className = "game";
+
+ let title = document.createElement("h2");
+ title.textContent = options.name;
+ e.appendChild(title);
+
+ let join = document.createElement("button");
+ join.className = "join";
+ join.textContent = "Join";
+ join.addEventListener("click", game.joinGame.bind(game, options.id));
+ e.appendChild(join);
+
+ el.appendChild(e);
+ }
}
// ##############
@@ -74,160 +84,123 @@ function createGameEl (options = {id: 0, name: ""}, el)
// 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.e.settings
- );
-
- this.init = false;
- this.online = [];
- this.games = [];
- this.packs = [];
- this.players = [];
- }
-
- // Set initial pack list
- // {data array} array of strings representing pack names
- 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}
- // { data.name string } name of the game the server runs
- // { data.games array } array of public games the server is running
- // { data.games[n].name } room name
- // { 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 (data) {
- while (this.e.games.firstChild != null) {
- this.e.games.remove(this.elements.games.firstChild)
- }
-
- for (let i in data.games) {
- 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
- // { data[n].name string } name of the player
- // { 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 (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 (data) {
- createGameEl(data, this.e.games);
- }
-
- // Called when a new public game is removed on the server
- // { data string } the uuid of the game to delete
- removeGame (data) {
-
- }
-
- // Called when a new player enters the lobby.
- // { data object } an object representing the player
- // { data.name string } name of the player
- // { 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 (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 (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 (data) {
-
- }
-
- // Called when a player exits the game (from lobby or game)
- // { data string } uuid of player
- removePlayer (data) {
-
- }
-
- // Called when the client wants to toggle the new game screen
- newGame () {
- //if(this.init) return;
- this.top.toggleNewGame();
- }
-
- // Called when the client wants to toggle the mobile settings screen
- mobileSettings (settings) {
- //if(this.init) return;
- this.top.toggleMobileSettings(settings);
- }
-
- // Called when the WebSocket state has changed.
- 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 () {
- while (this.e.games.firstElementChild != null) {
- this.e.games.removeChild(this.e.games.firstElementChild)
- }
-
- this.setState("Connecting", "loading", this.e.addr.innerText);
- this.init = false;
- }
+ 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.e.settings
+ );
+
+ this.init = false;
+ this.online = [];
+ this.games = [];
+ this.packs = [];
+ }
+
+ // Set initial pack list
+ // {data array} array of strings representing pack names
+ 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}
+ // { data.name string } name of the game the server runs
+ // { data.games array } array of public games the server is running
+ // { data.games[n].name } room name
+ // { 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 (data) {
+ while (this.e.games.firstChild != null) {
+ this.e.games.remove(this.elements.games.firstChild)
+ }
+
+ for (let i of data.games) {
+ let g = new Game(i, this.e.games);
+ this.games.push(g);
+ }
+
+ this.e.stats.game.innerText = data.name;
+ this.e.stats.pubgame.innerText = this.games.length();
+ }
+
+ // Set the initial player list.
+ // { data object } player statistics from the server
+ // { data.online number } players on server
+ // { data.ingame number } players on server and in game
+ players (data) {
+ this.e.stats.online.innerText = data.online;
+ this.e.stats.ingame.innerText = data.ingame;
+ }
+
+ // 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 (data) {
+ let g = new Game(data, this.e.games);
+ this.games.push(g);
+ }
+
+ // Called when a new public game is removed on the server
+ // { data string } the uuid of the game to delete
+ removeGame (data) {
+
+ }
+
+ // Called when the client wants to toggle the new game screen
+ newGame () {
+ //if(this.init) return;
+ this.top.toggleNewGame();
+ }
+
+ // Called when the client wants to toggle the mobile settings screen
+ mobileSettings (settings) {
+ //if(this.init) return;
+ this.top.toggleMobileSettings(settings);
+ }
+
+ // Called when the WebSocket state has changed.
+ 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 () {
+ while (this.e.games.firstElementChild != null) {
+ this.e.games.removeChild(this.e.games.firstElementChild)
+ }
+
+ this.setState("Connecting", "loading", this.e.addr.innerText);
+ this.init = false;
+ }
}
diff --git a/scripts/gui/table.js b/scripts/gui/table.js
index 0d21262..9aac2ae 100644
--- a/scripts/gui/table.js
+++ b/scripts/gui/table.js
@@ -83,7 +83,7 @@ class Table{
return null;
}
- moveCard(card, newDeck)
+ moveCard(card, newDeck, index = -1)
{
for(let d of this.decks)
{
@@ -91,10 +91,14 @@ class Table{
break;
}
card.resetPos();
- newDeck.appendCard(card);
+
+ if(index < 0)
+ newDeck.appendCard(card);
+ else
+ newDeck.addCardAt(card, index);
}
- moveByID(cardID, deckID)
+ moveByID(cardID, deckID, index = -1)
{
let card, deck;
for(let d of this.decks)
@@ -107,12 +111,12 @@ class Table{
deck = d;
}
- this.moveCard(card, deck);
+ this.moveCard(card, deck, index);
}
- checkMove(cardID, deckID)
+ checkMove(cardID, deckID, index = -1)
{
- this.socket.send("game", {});
+ this.socket.send("game", {type: "move", card: cardID, deck: deckID, pos: index});
}
dragCheck(cap)
@@ -131,7 +135,7 @@ class Table{
if(c !== null)
{
if(d !== null)
- this.moveCard(c, d);
+ this.checkMove(c.getID(), d.getID());
else
c.resetPos();
}
diff --git a/scripts/theme.js b/scripts/theme.js
index 627b833..b9dcb37 100644
--- a/scripts/theme.js
+++ b/scripts/theme.js
@@ -1,10 +1,28 @@
'use strict';
+const BASE_THEMES = [[
+ "styles/themes/colors-base.css",
+ "styles/themes/colors-dark.css"
+],
+[
+ "Light",
+ "Dark"
+]];
+
class Theme{
static theme = document.getElementById("theme");
+ static UserThemes = [[],[]];
static init()
{
+ let uth = Cookies.getCookie("userThemes").split(',');
+
+ for (let i = 1; i < uth.length; i += 2)
+ {
+ this.UserThemes[0].push(uth[i - 1]);
+ this.UserThemes[1].push(uth[i]);
+ }
+
if(Cookies.getCookie("theme") == ""){
Cookies.setYearCookie("theme", "styles/themes/colors-base.css");
}
@@ -21,6 +39,31 @@ class Theme{
Cookies.setYearCookie("theme", sheet);
Theme.theme.setAttribute("href", sheet + "?v=" + Date.now());
}
+
+ static setUserThemes() {
+ let out = "";
+ for (let i = 0; i < this.UserThemes[0].length; i++)
+ {
+ if(i !== 0)
+ out = out + ",";
+
+ out = out + this.UserThemes[0][i] + "," + this.UserThemes[1][i];
+ }
+
+ Cookies.setYearCookie("userThemes", out);
+ }
+
+ static removeUserTheme (index) {
+ this.UserThemes[0].splice(index, 1);
+ this.UserThemes[1].splice(index, 1);
+ this.setUserThemes();
+ }
+
+ static addUserTheme (name, value) {
+ this.UserThemes[0].push(name);
+ this.UserThemes[1].push(value);
+ this.setUserThemes();
+ }
}
Theme.restore(); \ No newline at end of file