" +
+ "
';
@@ -447,22 +470,33 @@ function constructCompactDeckBuilderElement (card, deckManager) {
cardContainer.classList.add('selected-card');
}
- cardContainer.querySelector('.compact-card-right').addEventListener('click', () => {
- deckManager.addCopyOfCard(card.role);
- updateDeckStatus(deckManager);
- cardContainer.querySelector('.card-quantity').innerText = deckManager.getCard(card.role).quantity;
- if (deckManager.getCard(card.role).quantity > 0) {
- document.getElementById('card-' + card.role.replaceAll(' ', '-')).classList.add('selected-card');
+ const addHandler = (e) => {
+ if (e.type === 'click' || e.code === 'Enter') {
+ deckManager.addCopyOfCard(card.role);
+ updateDeckStatus(deckManager);
+ cardContainer.querySelector('.card-quantity').innerText = deckManager.getCard(card.role).quantity;
+ if (deckManager.getCard(card.role).quantity > 0) {
+ document.getElementById('card-' + card.role.replaceAll(' ', '-')).classList.add('selected-card');
+ }
}
- });
- cardContainer.querySelector('.compact-card-left').addEventListener('click', () => {
- deckManager.removeCopyOfCard(card.role);
- updateDeckStatus(deckManager);
- cardContainer.querySelector('.card-quantity').innerText = deckManager.getCard(card.role).quantity;
- if (deckManager.getCard(card.role).quantity === 0) {
- document.getElementById('card-' + card.role.replaceAll(' ', '-')).classList.remove('selected-card');
+ };
+
+ const removeHandler = (e) => {
+ if (e.type === 'click' || e.code === 'Enter') {
+ deckManager.removeCopyOfCard(card.role);
+ updateDeckStatus(deckManager);
+ cardContainer.querySelector('.card-quantity').innerText = deckManager.getCard(card.role).quantity;
+ if (deckManager.getCard(card.role).quantity === 0) {
+ document.getElementById('card-' + card.role.replaceAll(' ', '-')).classList.remove('selected-card');
+ }
}
- });
+ };
+
+ cardContainer.querySelector('.compact-card-right').addEventListener('click', addHandler);
+ cardContainer.querySelector('.compact-card-right').addEventListener('keyup', addHandler);
+ cardContainer.querySelector('.compact-card-left').addEventListener('click', removeHandler);
+ cardContainer.querySelector('.compact-card-left').addEventListener('keyup', removeHandler);
+
return cardContainer;
}
@@ -560,56 +594,72 @@ function addOptionsToList (deckManager, selectEl) {
function addCustomRoleEventListeners (deckManager, select) {
document.querySelectorAll('.deck-select-role').forEach((role) => {
const name = role.querySelector('.deck-select-role-name').innerText;
- role.querySelector('.deck-select-include').addEventListener('click', (e) => {
- e.preventDefault();
- if (!deckManager.getCard(name)) {
- deckManager.addToDeck(name);
- const cardEl = constructCompactDeckBuilderElement(deckManager.getCard(name), deckManager);
- toast('"' + name + '" made available below.', 'success', true, true, 4);
- if (deckManager.getCard(name).team === globals.ALIGNMENT.GOOD) {
- document.getElementById('deck-good').appendChild(cardEl);
- } else {
- document.getElementById('deck-evil').appendChild(cardEl);
- }
- updateCustomRoleOptionsList(deckManager, select);
- } else {
- toast('"' + select.value + '" already included.', 'error', true, true, 3);
- }
- });
-
- role.querySelector('.deck-select-remove').addEventListener('click', (e) => {
- if (confirm("Delete the role '" + name + "'?")) {
+ const includeHandler = (e) => {
+ if (e.type === 'click' || e.code === 'Enter') {
e.preventDefault();
- deckManager.removeFromCustomRoleOptions(name);
- updateCustomRoleOptionsList(deckManager, select);
+ if (!deckManager.getCard(name)) {
+ deckManager.addToDeck(name);
+ const cardEl = constructCompactDeckBuilderElement(deckManager.getCard(name), deckManager);
+ toast('"' + name + '" made available below.', 'success', true, true, 4);
+ if (deckManager.getCard(name).team === globals.ALIGNMENT.GOOD) {
+ document.getElementById('deck-good').appendChild(cardEl);
+ } else {
+ document.getElementById('deck-evil').appendChild(cardEl);
+ }
+ updateCustomRoleOptionsList(deckManager, select);
+ } else {
+ toast('"' + select.value + '" already included.', 'error', true, true, 3);
+ }
}
- });
+ };
+ role.querySelector('.deck-select-include').addEventListener('click', includeHandler);
+ role.querySelector('.deck-select-include').addEventListener('keyup', includeHandler);
- role.querySelector('.deck-select-info').addEventListener('click', (e) => {
- const alignmentEl = document.getElementById('custom-role-info-modal-alignment');
- alignmentEl.classList.remove(globals.ALIGNMENT.GOOD);
- alignmentEl.classList.remove(globals.ALIGNMENT.EVIL);
- e.preventDefault();
- const option = deckManager.getCustomRoleOption(name);
- document.getElementById('custom-role-info-modal-name').innerText = name;
- alignmentEl.classList.add(option.team);
- document.getElementById('custom-role-info-modal-description').innerText = option.description;
- alignmentEl.innerText = option.team;
- ModalManager.displayModal('custom-role-info-modal', 'modal-background', 'close-custom-role-info-modal-button');
- });
+ const removeHandler = (e) => {
+ if (e.type === 'click' || e.code === 'Enter') {
+ if (confirm("Delete the role '" + name + "'?")) {
+ e.preventDefault();
+ deckManager.removeFromCustomRoleOptions(name);
+ updateCustomRoleOptionsList(deckManager, select);
+ }
+ }
+ };
+ role.querySelector('.deck-select-remove').addEventListener('click', removeHandler);
+ role.querySelector('.deck-select-remove').addEventListener('keyup', removeHandler);
- role.querySelector('.deck-select-edit').addEventListener('click', (e) => {
- e.preventDefault();
- const option = deckManager.getCustomRoleOption(name);
- document.getElementById('role-name').value = option.role;
- document.getElementById('role-alignment').value = option.team;
- document.getElementById('role-description').value = option.description;
- deckManager.createMode = false;
- deckManager.currentlyEditingRoleName = option.role;
- const createBtn = document.getElementById('create-role-button');
- createBtn.setAttribute('value', 'Update');
- ModalManager.displayModal('role-modal', 'modal-background', 'close-modal-button');
- });
+ const infoHandler = (e) => {
+ if (e.type === 'click' || e.code === 'Enter') {
+ const alignmentEl = document.getElementById('custom-role-info-modal-alignment');
+ alignmentEl.classList.remove(globals.ALIGNMENT.GOOD);
+ alignmentEl.classList.remove(globals.ALIGNMENT.EVIL);
+ e.preventDefault();
+ const option = deckManager.getCustomRoleOption(name);
+ document.getElementById('custom-role-info-modal-name').innerText = name;
+ alignmentEl.classList.add(option.team);
+ document.getElementById('custom-role-info-modal-description').innerText = option.description;
+ alignmentEl.innerText = option.team;
+ ModalManager.displayModal('custom-role-info-modal', 'modal-background', 'close-custom-role-info-modal-button');
+ }
+ };
+ role.querySelector('.deck-select-info').addEventListener('click', infoHandler);
+ role.querySelector('.deck-select-info').addEventListener('keyup', infoHandler);
+
+ const editHandler = (e) => {
+ if (e.type === 'click' || e.code === 'Enter') {
+ e.preventDefault();
+ const option = deckManager.getCustomRoleOption(name);
+ document.getElementById('role-name').value = option.role;
+ document.getElementById('role-alignment').value = option.team;
+ document.getElementById('role-description').value = option.description;
+ deckManager.createMode = false;
+ deckManager.currentlyEditingRoleName = option.role;
+ const createBtn = document.getElementById('create-role-button');
+ createBtn.setAttribute('value', 'Update');
+ ModalManager.displayModal('role-modal', 'modal-background', 'close-modal-button');
+ }
+ };
+ role.querySelector('.deck-select-edit').addEventListener('click', editHandler);
+ role.querySelector('.deck-select-edit').addEventListener('keyup', editHandler);
});
}
diff --git a/client/src/modules/GameStateRenderer.js b/client/src/modules/GameStateRenderer.js
index 29ac700..188741a 100644
--- a/client/src/modules/GameStateRenderer.js
+++ b/client/src/modules/GameStateRenderer.js
@@ -46,11 +46,15 @@ export class GameStateRenderer {
const linkDiv = document.createElement('div');
linkDiv.innerText = window.location;
gameLinkContainer.prepend(linkDiv);
- gameLinkContainer.addEventListener('click', () => {
- navigator.clipboard.writeText(gameLinkContainer.innerText).then(() => {
- toast('Link copied!', 'success', true);
- });
- });
+ const linkCopyHandler = (e) => {
+ if (e.type === 'click' || e.code === 'Enter') {
+ navigator.clipboard.writeText(gameLinkContainer.innerText).then(() => {
+ toast('Link copied!', 'success', true);
+ });
+ }
+ };
+ gameLinkContainer.addEventListener('click', linkCopyHandler);
+ gameLinkContainer.addEventListener('keyup', linkCopyHandler);
const copyImg = document.createElement('img');
copyImg.setAttribute('src', '../images/copy.svg');
gameLinkContainer.appendChild(copyImg);
@@ -250,15 +254,19 @@ function renderPotentialMods (gameState, group, transferModHandlers, socket) {
if ((member.out || member.userType === globals.USER_TYPES.SPECTATOR) && !(member.id === gameState.client.id)) {
const container = document.createElement('div');
container.classList.add('potential-moderator');
+ container.setAttribute("tabindex", "0");
container.dataset.pointer = member.id;
container.innerText = member.name;
- transferModHandlers[member.id] = () => {
- if (confirm('Transfer moderator powers to ' + member.name + '?')) {
- socket.emit(globals.COMMANDS.TRANSFER_MODERATOR, gameState.accessCode, member.id);
+ transferModHandlers[member.id] = (e) => {
+ if (e.type === 'click' || e.code === 'Enter') {
+ if (confirm('Transfer moderator powers to ' + member.name + '?')) {
+ socket.emit(globals.COMMANDS.TRANSFER_MODERATOR, gameState.accessCode, member.id);
+ }
}
};
container.addEventListener('click', transferModHandlers[member.id]);
+ container.addEventListener('keyup', transferModHandlers[member.id]);
modalContent.appendChild(container);
}
}
diff --git a/client/src/modules/ModalManager.js b/client/src/modules/ModalManager.js
index 75a4457..fadfbd8 100644
--- a/client/src/modules/ModalManager.js
+++ b/client/src/modules/ModalManager.js
@@ -21,6 +21,7 @@ function displayModal (modalId, backgroundId, closeButtonId) {
} else {
throw new Error('One or more of the ids supplied to ModalManager.displayModal is invalid.');
}
+ modal.focus();
}
function dispelModal (modalId, backgroundId) {
diff --git a/client/src/modules/Templates.js b/client/src/modules/Templates.js
index e25289f..5c40a42 100644
--- a/client/src/modules/Templates.js
+++ b/client/src/modules/Templates.js
@@ -3,7 +3,7 @@ export const templates = {
"