mirror of
https://github.com/AndrioCelos/TableturfBattleApp.git
synced 2026-09-12 13:25:25 -05:00
Implement the Show Deck button
This commit is contained in:
@@ -182,6 +182,15 @@
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<div id="showDeckContainer" hidden>
|
||||
<div id="showDeck">
|
||||
<ul id="showDeckList"></ul>
|
||||
<div>
|
||||
<button type="button" id="showDeckCloseButton">Close</button>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<div id="turnNumberContainer" hidden>
|
||||
<p>Turns left</p>
|
||||
<div id="turnNumberLabel">12</div>
|
||||
|
||||
@@ -22,6 +22,11 @@ const resultElement = document.getElementById('result')!;
|
||||
const playerBars = Array.from(document.getElementsByClassName('playerBar'), el => new PlayerBar(el as HTMLDivElement));
|
||||
playerBars.sort((a, b) => a.playerIndex - b.playerIndex);
|
||||
|
||||
const showDeckContainer = document.getElementById('showDeckContainer')!;
|
||||
const showDeckListElement = document.getElementById('showDeckList')!;
|
||||
const showDeckButtons: CardButton[] = [ ];
|
||||
const showDeckCloseButton = document.getElementById('showDeckCloseButton') as HTMLButtonElement;
|
||||
|
||||
const playContainers = Array.from(document.getElementsByClassName('playContainer')) as HTMLDivElement[];
|
||||
playContainers.sort((a, b) => parseInt(a.dataset.index || '0') - parseInt(b.dataset.index || '0'));
|
||||
|
||||
@@ -189,80 +194,106 @@ function showResult() {
|
||||
}
|
||||
}
|
||||
|
||||
function updateHand(cards: any[]) {
|
||||
function clearShowDeck() {
|
||||
showDeckContainer.hidden = true;
|
||||
clearChildren(showDeckListElement);
|
||||
showDeckButtons.splice(0);
|
||||
}
|
||||
|
||||
function updateHand(playerData: PlayerData) {
|
||||
for (const button of handButtons) {
|
||||
handContainer.removeChild(button.element);
|
||||
}
|
||||
handButtons.splice(0);
|
||||
|
||||
if (!currentGame?.me) return;
|
||||
currentGame.me.hand = cards.map(Card.fromJson);
|
||||
if (cards) {
|
||||
for (let i = 0; i < currentGame.me.hand.length; i++) {
|
||||
const card = currentGame.me.hand[i];
|
||||
const button = new CardButton('radio', card);
|
||||
button.inputElement.name = 'handCard';
|
||||
handButtons.push(button);
|
||||
button.inputElement.addEventListener('input', e => {
|
||||
if (button.checked) {
|
||||
for (const button2 of handButtons) {
|
||||
if (button2 != button)
|
||||
button2.element.classList.remove('checked');
|
||||
}
|
||||
if (passButton.checked) {
|
||||
if (canPlay) {
|
||||
canPlay = false;
|
||||
// Send the play to the server.
|
||||
let req = new XMLHttpRequest();
|
||||
req.open('POST', `${config.apiBaseUrl}/games/${currentGame!.id}/play`);
|
||||
req.addEventListener('error', () => communicationError());
|
||||
let data = new URLSearchParams();
|
||||
data.append('clientToken', clientToken);
|
||||
data.append('cardNumber', card.number.toString());
|
||||
data.append('isPass', 'true');
|
||||
req.send(data.toString());
|
||||
if (showDeckButtons.length == 0) {
|
||||
for (const card of playerData.deck!) {
|
||||
const button = new CardButton('checkbox', card);
|
||||
button.inputElement.hidden = true;
|
||||
showDeckButtons.push(button);
|
||||
|
||||
board.autoHighlight = false;
|
||||
}
|
||||
} else {
|
||||
board.cardPlaying = card;
|
||||
if (isNaN(board.highlightX) || isNaN(board.highlightY)) {
|
||||
board.highlightX = board.startSpaces[board.playerIndex!].x - 3;
|
||||
board.highlightY = board.startSpaces[board.playerIndex!].y - 3;
|
||||
}
|
||||
board.cardRotation = 0;
|
||||
board.refreshHighlight();
|
||||
board.table.focus();
|
||||
}
|
||||
}
|
||||
});
|
||||
button.inputElement.addEventListener('keydown', e => {
|
||||
switch (e.key) {
|
||||
case 'ArrowUp':
|
||||
if (i >= 2)
|
||||
handButtons[i - 2].inputElement.focus();
|
||||
e.preventDefault();
|
||||
break;
|
||||
case 'ArrowDown':
|
||||
if (i < 2)
|
||||
handButtons[i + 2].inputElement.focus();
|
||||
e.preventDefault();
|
||||
break;
|
||||
case 'ArrowLeft':
|
||||
if (i % 2 != 0)
|
||||
handButtons[i - 1].inputElement.focus();
|
||||
e.preventDefault();
|
||||
break;
|
||||
case 'ArrowRight':
|
||||
if (i % 2 == 0)
|
||||
handButtons[i + 1].inputElement.focus();
|
||||
e.preventDefault();
|
||||
break;
|
||||
}
|
||||
});
|
||||
handContainer.appendChild(button.element);
|
||||
const li = document.createElement('li');
|
||||
li.appendChild(button.element);
|
||||
showDeckListElement.appendChild(li);
|
||||
}
|
||||
}
|
||||
|
||||
for (const button of showDeckButtons) {
|
||||
const li = button.element.parentElement!;
|
||||
if (playerData.hand!.find(c => c.number == button.card.number))
|
||||
li.className = 'inHand';
|
||||
else if (playerData.cardsUsed.includes(button.card.number))
|
||||
li.className = 'used';
|
||||
else
|
||||
li.className = 'unused';
|
||||
}
|
||||
|
||||
if (!currentGame?.me) return;
|
||||
currentGame.me.hand = playerData.hand!.map(Card.fromJson);
|
||||
for (let i = 0; i < currentGame.me.hand.length; i++) {
|
||||
const card = currentGame.me.hand[i];
|
||||
const button = new CardButton('radio', card);
|
||||
button.inputElement.name = 'handCard';
|
||||
handButtons.push(button);
|
||||
button.inputElement.addEventListener('input', e => {
|
||||
if (button.checked) {
|
||||
for (const button2 of handButtons) {
|
||||
if (button2 != button)
|
||||
button2.element.classList.remove('checked');
|
||||
}
|
||||
if (passButton.checked) {
|
||||
if (canPlay) {
|
||||
canPlay = false;
|
||||
// Send the play to the server.
|
||||
let req = new XMLHttpRequest();
|
||||
req.open('POST', `${config.apiBaseUrl}/games/${currentGame!.id}/play`);
|
||||
req.addEventListener('error', () => communicationError());
|
||||
let data = new URLSearchParams();
|
||||
data.append('clientToken', clientToken);
|
||||
data.append('cardNumber', card.number.toString());
|
||||
data.append('isPass', 'true');
|
||||
req.send(data.toString());
|
||||
|
||||
board.autoHighlight = false;
|
||||
}
|
||||
} else {
|
||||
board.cardPlaying = card;
|
||||
if (isNaN(board.highlightX) || isNaN(board.highlightY)) {
|
||||
board.highlightX = board.startSpaces[board.playerIndex!].x - 3;
|
||||
board.highlightY = board.startSpaces[board.playerIndex!].y - 3;
|
||||
}
|
||||
board.cardRotation = 0;
|
||||
board.refreshHighlight();
|
||||
board.table.focus();
|
||||
}
|
||||
}
|
||||
});
|
||||
button.inputElement.addEventListener('keydown', e => {
|
||||
switch (e.key) {
|
||||
case 'ArrowUp':
|
||||
if (i >= 2)
|
||||
handButtons[i - 2].inputElement.focus();
|
||||
e.preventDefault();
|
||||
break;
|
||||
case 'ArrowDown':
|
||||
if (i < 2)
|
||||
handButtons[i + 2].inputElement.focus();
|
||||
e.preventDefault();
|
||||
break;
|
||||
case 'ArrowLeft':
|
||||
if (i % 2 != 0)
|
||||
handButtons[i - 1].inputElement.focus();
|
||||
e.preventDefault();
|
||||
break;
|
||||
case 'ArrowRight':
|
||||
if (i % 2 == 0)
|
||||
handButtons[i + 1].inputElement.focus();
|
||||
e.preventDefault();
|
||||
break;
|
||||
}
|
||||
});
|
||||
handContainer.appendChild(button.element);
|
||||
}
|
||||
}
|
||||
|
||||
(document.getElementById('redrawNoButton') as HTMLButtonElement).addEventListener('click', redrawButton_click);
|
||||
@@ -385,6 +416,18 @@ function focusFirstEnabledHandCard() {
|
||||
const firstEnabledButton = handButtons.find(b => b.enabled);
|
||||
if (firstEnabledButton)
|
||||
firstEnabledButton.inputElement.focus();
|
||||
else
|
||||
passButton.input.focus();
|
||||
}
|
||||
|
||||
function toggleShowDeck() {
|
||||
if (showDeckContainer.hidden) {
|
||||
showDeckContainer.hidden = false;
|
||||
showDeckCloseButton.focus();
|
||||
} else {
|
||||
showDeckContainer.hidden = true;
|
||||
focusFirstEnabledHandCard();
|
||||
}
|
||||
}
|
||||
|
||||
rotateLeftButton.addEventListener('click', () => {
|
||||
@@ -395,6 +438,8 @@ rotateRightButton.addEventListener('click', () => {
|
||||
board.cardRotation++;
|
||||
board.refreshHighlight();
|
||||
});
|
||||
gameDeckButton.addEventListener('click', toggleShowDeck);
|
||||
showDeckCloseButton.addEventListener('click', () => showDeckContainer.hidden = true);
|
||||
|
||||
document.addEventListener('keydown', e => {
|
||||
if (!pages.get('game')!.hidden) {
|
||||
@@ -415,6 +460,10 @@ document.addEventListener('keydown', e => {
|
||||
}
|
||||
e.preventDefault();
|
||||
break;
|
||||
case 'd':
|
||||
if (!gameButtonsContainer.hidden) toggleShowDeck();
|
||||
e.preventDefault();
|
||||
break;
|
||||
}
|
||||
}
|
||||
});
|
||||
|
||||
@@ -129,6 +129,8 @@ function getGameInfo(gameID: string, myPlayerIndex: number | null) {
|
||||
board.playerIndex = myPlayerIndex;
|
||||
initLobbyPage(window.location.toString());
|
||||
|
||||
showDeckButtons.splice(0);
|
||||
clearShowDeck();
|
||||
myPlayerIndex = setupWebSocket(gameID, myPlayerIndex);
|
||||
}
|
||||
|
||||
|
||||
@@ -104,7 +104,7 @@ function onGameStateChange(game: any, playerData: any) {
|
||||
case GameState.Ongoing:
|
||||
case GameState.Ended:
|
||||
if (playerData)
|
||||
updateHand(playerData.hand);
|
||||
updateHand(playerData);
|
||||
board.autoHighlight = false;
|
||||
redrawModal.hidden = true;
|
||||
showPage('game');
|
||||
@@ -294,11 +294,13 @@ function setupWebSocket(gameID: string, myPlayerIndex: number | null) {
|
||||
|
||||
(async () => {
|
||||
await playInkAnimations(payload.data, anySpecialAttacks);
|
||||
updateHand(payload.playerData.hand);
|
||||
updateHand(payload.playerData);
|
||||
turnNumberLabel.setTurnNumber(payload.data.game.turnNumber);
|
||||
clearPlayContainers();
|
||||
if (payload.event == 'gameEnd') {
|
||||
gameButtonsContainer.hidden = true;
|
||||
passButton.enabled = false;
|
||||
specialButton.enabled = false;
|
||||
gamePage.classList.add('gameEnded');
|
||||
showResult();
|
||||
} else {
|
||||
|
||||
@@ -471,6 +471,56 @@ dialog::backdrop {
|
||||
#playControls > label:is(:active, .checked) { background: var(--special-accent-colour-1); }
|
||||
#playControls > label.disabled { background: grey; }
|
||||
|
||||
#showDeckContainer {
|
||||
grid-column: 1 / span 3;
|
||||
grid-row: 2 / -2;
|
||||
background: black;
|
||||
z-index: 2;
|
||||
}
|
||||
#showDeck {
|
||||
display: flex;
|
||||
flex-flow: column;
|
||||
height: 100%;
|
||||
text-align: center;
|
||||
}
|
||||
#showDeckList {
|
||||
display: grid;
|
||||
grid-template-columns: auto auto auto;
|
||||
list-style-type: none;
|
||||
font-size: smaller;
|
||||
overflow-y: auto;
|
||||
padding: 0;
|
||||
margin: 0;
|
||||
justify-items: center;
|
||||
}
|
||||
#showDeckList > li {
|
||||
margin: 0.25em;
|
||||
border-radius: 0.5em;
|
||||
text-align: center;
|
||||
}
|
||||
#showDeckList > li.inHand {
|
||||
outline: 0.25em solid;
|
||||
}
|
||||
#showDeckList > li.used {
|
||||
opacity: 0.35;
|
||||
}
|
||||
#showDeckCloseButton {
|
||||
border: none;
|
||||
font-family: inherit;
|
||||
color: inherit;
|
||||
width: 40%;
|
||||
grid-row: button-row;
|
||||
margin: 1em;
|
||||
padding: 0 0.5em;
|
||||
text-align: center;
|
||||
background: var(--primary-colour-1);
|
||||
text-shadow: 0 0 4px black;
|
||||
border-radius: 0.5em;
|
||||
}
|
||||
#showDeckCloseButton:hover { background: var(--special-colour-1); }
|
||||
#showDeckCloseButton:focus-within { outline: 2px solid var(--special-accent-colour-2); }
|
||||
#showDeckCloseButton:active { background: var(--special-accent-colour-1); }
|
||||
|
||||
.playContainer { text-align: center; }
|
||||
|
||||
.playContainer[data-index="0"] { grid-column: play-column-1; grid-row: 2 / -1; align-self: end; }
|
||||
@@ -510,9 +560,6 @@ dialog::backdrop {
|
||||
opacity: 1;
|
||||
color: var(--primary-colour-1);
|
||||
}
|
||||
#gameDeckButton {
|
||||
display: none;
|
||||
}
|
||||
|
||||
#boardSection {
|
||||
grid-column: board-column;
|
||||
@@ -1007,6 +1054,14 @@ dialog::backdrop {
|
||||
overflow: scroll visible;
|
||||
}
|
||||
|
||||
#showDeckContainer {
|
||||
grid-column: 1 / -1;
|
||||
grid-row: 2 / -1;
|
||||
}
|
||||
#showDeckList .card {
|
||||
width: 30vw;
|
||||
}
|
||||
|
||||
.playContainer:is([data-index="0"], [data-index="1"], [data-index="2"], [data-index="3"]) {
|
||||
font-size: x-small;
|
||||
grid-column: 1 / -1;
|
||||
|
||||
Reference in New Issue
Block a user