From 2ce432034eb35f763182de03fb7b42d2a07afc4b Mon Sep 17 00:00:00 2001 From: Kyle Gunger Date: Tue, 15 Sep 2020 20:03:52 -0400 Subject: Webcards update from local git server --- webcards/scripts/gui/chat.js | 149 +++++++++++++++++++++++++++++ webcards/scripts/gui/input.js | 182 +++++++++++++++++++----------------- webcards/scripts/gui/lobby.js | 212 ++++++++++++++++++++++-------------------- webcards/scripts/gui/table.js | 75 ++++++++++++--- 4 files changed, 420 insertions(+), 198 deletions(-) create mode 100644 webcards/scripts/gui/chat.js (limited to 'webcards/scripts/gui') 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); + } +} -- cgit v1.2.3