Skip to content

Commit

Permalink
races autocomplete
Browse files Browse the repository at this point in the history
  • Loading branch information
pyanderson committed Nov 1, 2023
1 parent 787a2ea commit 66389ab
Show file tree
Hide file tree
Showing 9 changed files with 233 additions and 24 deletions.
1 change: 1 addition & 0 deletions chrome/manifest.json
Original file line number Diff line number Diff line change
Expand Up @@ -31,6 +31,7 @@
"features/powers.js",
"features/spells.js",
"features/equipments.js",
"features/races.js",
"features/character-sheet.js",
"features/book.js",
"features/enhancement.js",
Expand Down
1 change: 1 addition & 0 deletions firefox/manifest.json
Original file line number Diff line number Diff line change
Expand Up @@ -31,6 +31,7 @@
"features/powers.js",
"features/spells.js",
"features/equipments.js",
"features/races.js",
"features/character-sheet.js",
"features/book.js",
"features/enhancement.js",
Expand Down
60 changes: 59 additions & 1 deletion src/common/element-factory.js
Original file line number Diff line number Diff line change
Expand Up @@ -2,7 +2,7 @@
/* common/constants vars */
/* global BOOK_BUTTON_ID,BOOK_DIALOG_ID,BOOK_LIST_ID */
/* common/helpers vars */
/* global createElement,slugify,setInputValue,addEventObserver,normalize,clearChildren */
/* global createElement,slugify,setInputValue,addEventObserver,normalize,clearChildren,generateUUID */
/* common/dialog-manager vars */
/* global openDialog */

Expand Down Expand Up @@ -359,3 +359,61 @@ function createBookButton({ cssText, bookItems }) {
};
return button;
}

/**
* Add a repeatable item to the character sheet.
*
* @param {object} props
* @param {HTMLDocument} props.iframe - The character sheet iframe document.
* @param {string} props.groupName - The item group name.
* @param {object[]} props.attributes - The item attributes values.
* @param {object[]} props.attributes[].name - The input name.
* @param {object[]} props.attributes[].value - The input value.
* @returns {HTMLUListElement}
*/
// eslint-disable-next-line no-unused-vars
function addRepItem({ iframe, groupName, attributes }) {
const fieldset = iframe
.querySelector(`div.repcontrol[data-groupname="${groupName}"]`)
.parentNode.querySelector('fieldset');
const itemsContainer = iframe.querySelector(
`div.repcontainer[data-groupname="${groupName}"]`,
);
if (!fieldset) {
console.error(`fieldset for ${groupName} not found`);
return;
}
const repRowId = generateUUID().replace(/_/g, 'Z');
const newItem = createElement('div', {
classes: 'repitem',
append: [
createElement('div', {
classes: 'itemcontrol',
append: [
createElement('button', {
classes: 'btn btn-danger pictos repcontrol_del',
innerHTML: '#',
}),
createElement('a', {
classes: 'btn repcontrol_move',
innerHTML: '≡',
}),
],
}),
...Array.from(fieldset.childNodes).map((child) => child.cloneNode(true)),
],
});
newItem.setAttribute('data-reprowid', repRowId);
for (const attr of attributes) {
const attrInput = newItem.querySelector(
`input[name="${attr.name}"],textarea[name="${attr.name}"]`,
);
if (attrInput) {
attrInput.value = attr.value;
setTimeout(() => {
attrInput.dispatchEvent(new CustomEvent('blur'));
}, 300);
}
}
itemsContainer.append(newItem);
}
26 changes: 26 additions & 0 deletions src/common/helpers.js
Original file line number Diff line number Diff line change
Expand Up @@ -158,3 +158,29 @@ function clearChildren({ el }) {
el.removeChild(el.lastChild);
}
}

/**
* Generate Roll20 UUID.
*
* @returns {string}
*/
// eslint-disable-next-line no-unused-vars
function generateUUID() {
const source =
'-0123456789ABCDEFGHIJKLMNOPQRSTUVWXYZ_abcdefghijklmnopqrstuvwxyz';
const getFirstPart = (part, seed) => {
if (seed === 0) return `-${part}`;
return getFirstPart(
`${source.charAt(seed % 64)}${part}`,
Math.floor(seed / 64),
);
};
const getSecondPart = (part, size) => {
if (part.length === size) return part;
return getSecondPart(
`${part}${source.charAt(Math.floor(64 * Math.random()))}`,
size,
);
};
return `${getFirstPart('', new Date().getTime())}${getSecondPart('', 12)}`;
}
24 changes: 24 additions & 0 deletions src/common/types.js
Original file line number Diff line number Diff line change
Expand Up @@ -39,12 +39,20 @@
* @property {string} description - Eg.: Você se torna treinado em duas perícias a sua escolha...
*/

/**
* @typedef Ability
* @type {object}
* @property {string} name - Eg.: Conhecimento das Rochas
* @property {string} description - Eg.: Você recebe visão no escuro e +2 em testes de Percepção e Sobrevivência realizados no subterrâneo.
*/

/**
* @typedef T20Data
* @type {object}
* @property {SpellData} spells
* @property {PowerData} abilitiesAndPowers
* @property {EquipmentData[]} equipments
* @property {Race[]} races
*/

/**
Expand Down Expand Up @@ -103,3 +111,19 @@
* @property {string} name - Eg.: Armas
* @property {Weapon[]|Armor[]|Item[]} items
*/

/**
* @typedef Attribute
* @type {object}
* @property {string} attr - Eg.: con
* @property {number} mod - Eg.: 2
*/

/**
* @typedef Race
* @type {object}
* @property {string} name - Eg.: Anão
* @property {number} displacement - Eg.: 6
* @property {Attribute[]} attributes
* @property {Ability[]} abilities
*/
33 changes: 21 additions & 12 deletions src/features/character-sheet.js
Original file line number Diff line number Diff line change
Expand Up @@ -11,6 +11,8 @@
/* global calcCD,loadSpellsEnhancement */
/* features/equipments vars */
/* global loadEquipmentEnhancement */
/* features/races vars */
/* global loadRacesEnhancement */

/**
* Returns the data configuration of the character saved in the local storage.
Expand Down Expand Up @@ -128,20 +130,13 @@ function loadSheetExtraCSS({ iframe }) {
* Load the sheet improvements.
*
* @param {object} props
* @param {SpellData} props.spells - The spells data.
* @param {PowerData} props.powers - The powers data.
* @param {EquipmentData} props.equipments - The equipments data.
* @param {T20Data} props.db - The Tormenta20 data.
* @param {string} props.characterId - The character ID in the Roll20 game.
*/
// eslint-disable-next-line no-unused-vars
function loadSheetEnhancement({
spells,
abilitiesAndPowers,
equipments,
characterId,
}) {
function loadSheetEnhancement({ db: data, characterId }) {
// Tormenta20 data
const data = { spells, abilitiesAndPowers, equipments };
// const data = { spells, abilitiesAndPowers, equipments, races };
// Load the functionalities
const iframe = document.querySelector(`iframe[name="iframe_${characterId}"]`);
if (!iframe) {
Expand All @@ -165,14 +160,28 @@ function loadSheetEnhancement({
});
const equipmentsContainer = pathQuerySelector({
root: iframe.contentDocument,
path: ['div.sheet-right-container', 'div.sheet-equipment-container'],
path: [
'div.sheet-right-container',
'div.sheet-equipment-container',
'div[data-groupname="repeating_equipment"]',
],
});
if (spellsContainer && powersContainer && equipmentsContainer) {
const headerContainer = pathQuerySelector({
root: iframe.contentDocument,
path: ['div.sheet-left-container', 'div.sheet-header-info'],
});
if (
spellsContainer &&
powersContainer &&
equipmentsContainer &&
headerContainer
) {
init({ iframe: iframe.contentDocument, characterId });
calcCD({ iframe: iframe.contentDocument });
loadSpellsEnhancement({ iframe: iframe.contentDocument, data });
loadPowersEnhancement({ iframe: iframe.contentDocument, data });
loadEquipmentEnhancement({ iframe: iframe.contentDocument, data });
loadRacesEnhancement({ iframe: iframe.contentDocument, data });
// Observers
const spellsObserver = new MutationObserver(() => {
loadSpellsEnhancement({ iframe: iframe.contentDocument, data });
Expand Down
10 changes: 5 additions & 5 deletions src/features/equipments.js
Original file line number Diff line number Diff line change
Expand Up @@ -11,20 +11,20 @@
* @param {Equipment[]} props.equipments - All available equipments.
*/
function loadEquipmentAutoComplete({ equipmentsContainer, equipments }) {
if (!equipmentsContainer.querySelector('#list-equipment')) {
if (!equipmentsContainer.querySelector('#equipment-list')) {
equipmentsContainer.append(
createElement('datalist', {
id: 'list-equipment',
id: 'equipment-list',
append: equipments.map((equipment) =>
createElement('option', { value: equipment.name }),
),
}),
);
}
for (const input of equipmentsContainer.querySelectorAll(
'input[name="attr_equipname"]:not([list="list-equipment"])',
'input[name="attr_equipname"]:not([list="equipment-list"])',
)) {
input.setAttribute('list', 'list-equipment');
input.setAttribute('list', 'equipment-list');
input.autocomplete = 'off';
const updateSpacesValue = () => {
const equipment = equipments.find(
Expand Down Expand Up @@ -55,7 +55,7 @@ function loadEquipmentAutoComplete({ equipmentsContainer, equipments }) {
}

/**
* Add the equipment autocomplete.
* Load the equipment related enhancements.
*
* @param {object} props
* @param {HTMLDocument} props.iframe - The character sheet iframe document.
Expand Down
95 changes: 95 additions & 0 deletions src/features/races.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,95 @@
'use strict';

/* common/helpers vars */
/* global pathQuerySelector,createElement */

/**
* Add the race autocomplete.
*
* @param {object} props
* @param {HTMLDocument} props.iframe - The character sheet iframe document.
* @param {Race[]} props.races - All available races.
*/
function loadRaceAutoComplete({ iframe, races }) {
const headerContainer = pathQuerySelector({
root: iframe,
path: ['div.sheet-left-container', 'div.sheet-header-info'],
});
// const abilitiesAndPowersContainer = pathQuerySelector({
// root: iframe,
// path: ['div.sheet-left-container', 'div.sheet-powers-and-abilities'],
// });
if (!headerContainer.querySelector('#race-list')) {
headerContainer.append(
createElement('datalist', {
id: 'race-list',
append: races.map((race) =>
createElement('option', { value: race.name }),
),
}),
);
}
const input = headerContainer.querySelector('input[name="attr_trace"]');
input.setAttribute('list', 'race-list');
input.autocomplete = 'off';

// const updateAbilities = () => {
// const race = races.find((race) => race.name === input.value);
// if (race) {
// const toRemove = races
// .filter((r) => r.name !== race.name)
// .map((r) => r.abilities)
// .reduce(
// (acc, abilities) => [...acc, ...abilities.map((a) => a.name)],
// [],
// );
// const allAbilitiesInputs = abilitiesAndPowersContainer.querySelectorAll(
// 'input[name="attr_nameability"],input[name="attr_namepower"]',
// );
// const currentAbilities = Array.from(allAbilitiesInputs).map(
// (abilityInput) => abilityInput.value.trim(),
// );
// // add the race abilities
// for (const ability of race.abilities) {
// if (!currentAbilities.includes(ability.name)) {
// addRepItem({
// iframe,
// groupName: 'repeating_abilities',
// attributes: [
// { name: 'attr_nameability', value: ability.name },
// { name: 'attr_abilitydescription', value: ability.description },
// ],
// });
// }
// }
// // remove the other races abilities
// for (const abilityInput of allAbilitiesInputs) {
// if (toRemove.includes(abilityInput.value.trim())) {
// console.log(`remove ${abilityInput.value}`);
// }
// }
// }
// };
// addEventObserver({
// el: input,
// eventName: 'input',
// eventHandler: updateAbilities,
// });
// addEventObserver({
// el: input,
// eventName: 'change',
// eventHandler: updateAbilities,
// });
}

/**
* Load the race related enhancements.
*
* @param {object} props
* @param {HTMLDocument} props.iframe - The character sheet iframe document.
* @param {T20Data} props.data - The Tormenta20 data.
*/
// eslint-disable-next-line no-unused-vars
function loadRacesEnhancement({ iframe, data }) {
loadRaceAutoComplete({ iframe, races: data.races });
}
7 changes: 1 addition & 6 deletions src/index.js
Original file line number Diff line number Diff line change
Expand Up @@ -19,12 +19,7 @@ $(document).ready(() => {
const data = e.originalEvent.data;
// only add the sheet improvements when a character sheet is opened
if (data.type === 'loaded')
loadSheetEnhancement({
spells: db.spells,
abilitiesAndPowers: db.abilities_and_powers,
equipments: db.equipments,
characterId: data.characterId,
});
loadSheetEnhancement({ db, characterId: data.characterId });
});
});
});

0 comments on commit 66389ab

Please sign in to comment.