devel_wizard-2.x-dev/components/organization/spell-definition-list/spell-definition-list.js
components/organization/spell-definition-list/spell-definition-list.js
/**
* @typedef {Object} DevelWizardSpeed
* @property {string} unit
* @property {number} amount
*/
(function (document, Drupal, drupalSettings) {
// @todo Better API, because currently only one instance is supported.
Drupal.behaviors.develWizardSpellDefinitionList = {
attach: function (context, settings) {
const listElement = context.querySelector('.devel-wizard-spell-definition-list:not(.dw-sdl-processed)');
if (!listElement) {
return;
}
listElement.classList.add('dw-sdl-processed');
const controlsElement = listElement.querySelector(':scope > .controls');
Drupal.develWizardSpellDefinitionList.initState();
Drupal.develWizardSpellDefinitionList.initControls(controlsElement);
Drupal.develWizardSpellDefinitionList.updateState(listElement);
Drupal.develWizardSpellDefinitionList.updateView(listElement);
}
};
Drupal.develWizardSpellDefinitionList = Drupal.develWizardSpellDefinitionList ?? {};
Drupal.develWizardSpellDefinitionList.state = null;
Drupal.develWizardSpellDefinitionList.initState = function () {
if (Drupal.develWizardSpellDefinitionList.state !== null) {
return;
}
// @todo Populate the filters from URL queryString.
Drupal.develWizardSpellDefinitionList.state = {
selectedTags: [],
additionalTags: [],
selectedSpells: [],
};
};
/**
* @param {Element} listElement
*/
Drupal.develWizardSpellDefinitionList.initControls = function (listElement) {
const tagsWrapper = listElement.querySelector(':scope > .tags');
const tags = drupalSettings.develWizard.spellDefinitionList.tags;
let tagButton;
tagButton = Drupal.develWizardSpellDefinitionList.createTagButton('_all', Drupal.t('- All -'));
tagsWrapper.prepend(tagButton);
for (const [tagKey, tagLabel] of Object.entries(tags)) {
tagButton = Drupal.develWizardSpellDefinitionList.createTagButton(tagKey, tagLabel);
tagsWrapper.append(tagButton);
}
}
/**
* @param {string} tagKey
* @param {string} tagLabel
*
* @return {Element}
*/
Drupal.develWizardSpellDefinitionList.createTagButton = function (tagKey, tagLabel) {
const tagButton = document.createElement('button');
tagButton.setAttribute('data-tag', tagKey);
tagButton.classList.add('button', 'button--small');
tagButton.addEventListener('click', Drupal.develWizardSpellDefinitionList.onTagChange);
tagButton.textContent = tagLabel;
return tagButton
};
/**
* @param {Event} event
*/
Drupal.develWizardSpellDefinitionList.onTagChange = function (event) {
const state = Drupal.develWizardSpellDefinitionList.state;
const tag = event.target.getAttribute('data-tag');
if (tag === '_all') {
Drupal.develWizardSpellDefinitionList.state.selectedTags = [];
}
else {
const tagIndex = state.selectedTags.indexOf(tag);
if (tagIndex === -1) {
state.selectedTags.push(tag);
}
else {
state.selectedTags.splice(tagIndex, 1);
}
}
const listElement = event.target.closest('.devel-wizard-spell-definition-list');
Drupal.develWizardSpellDefinitionList.updateState();
Drupal.develWizardSpellDefinitionList.updateView(listElement);
};
Drupal.develWizardSpellDefinitionList.updateState = function () {
const state = Drupal.develWizardSpellDefinitionList.state;
// The "selectedTags" is the base point, rests are calculated.
state.additionalTags = [];
state.selectedSpells = [];
if (state.selectedTags.length !== 0) {
for (const [spellId, spell] of Object.entries(drupalSettings.develWizard.spellDefinitionList.spells)) {
if (!state.selectedTags.every(tag => spell.tags.hasOwnProperty(tag))) {
continue;
}
state.selectedSpells.push(spellId);
Object.keys(spell.tags).forEach(function (tag) {
if (!state.selectedTags.includes(tag) && !state.additionalTags.includes(tag)) {
state.additionalTags.push(tag);
}
});
}
}
};
Drupal.develWizardSpellDefinitionList.updateView = function (listElement) {
Drupal.develWizardSpellDefinitionList.updateViewControls(listElement);
Drupal.develWizardSpellDefinitionList.updateViewItems(listElement);
};
Drupal.develWizardSpellDefinitionList.updateViewControls = function (listElement) {
const state = Drupal.develWizardSpellDefinitionList.state;
const buttonElements = listElement.querySelectorAll(':scope > .controls > .tags > button:not([data-tag="_all"])');
const isAnyTagSelected = state.selectedTags.length > 0;
buttonElements.forEach(function (buttonElement) {
const tag = buttonElement.getAttribute('data-tag');
const isTagSelected = state.selectedTags.includes(tag);
buttonElement.classList.toggle('selected', isTagSelected);
if (isAnyTagSelected && !isTagSelected && !state.additionalTags.includes(tag)) {
buttonElement.setAttribute('disabled', 'disabled');
}
else {
buttonElement.removeAttribute('disabled');
}
});
}
Drupal.develWizardSpellDefinitionList.updateViewItems = function (listElement) {
const state = Drupal.develWizardSpellDefinitionList.state;
const isAnyTagSelected = state.selectedTags.length > 0;
listElement.querySelectorAll(':scope > .items > *[data-spell-id]').forEach(function (spellElement) {
const spellId = spellElement.getAttribute('data-spell-id');
const isSpellSelected = !isAnyTagSelected || state.selectedSpells.includes(spellId);
if (isSpellSelected) {
spellElement.classList.remove('hidden', 'not-selected');
return;
}
const transitionSpeed = getComputedStyle(spellElement).getPropertyValue('--speed-transition');
const delay = Drupal.develWizardSpellDefinitionList.parseSpeed(transitionSpeed)
Drupal.develWizardSpellDefinitionList.convertSpeedTo(delay, 'ms');
spellElement.classList.add('not-selected');
setTimeout(
function () {
spellElement.classList.add('hidden');
},
delay.amount,
);
});
};
/**
* @param {string} value
*
* @return {DevelWizardSpeed}
*/
Drupal.develWizardSpellDefinitionList.parseSpeed = function (value) {
return {
unit: value.replaceAll(/[\d.]/g, ''),
amount: parseFloat(value),
};
};
/**
* @param {DevelWizardSpeed} speed
* @param {string} unit
* New unit.
*
* @return void
*/
Drupal.develWizardSpellDefinitionList.convertSpeedTo = function (speed, unit) {
switch (speed.unit + ':' + unit) {
case 's:ms':
speed.amount = speed.amount * 1000;
break;
case 'ms:s':
speed.amount = speed.amount / 1000;
break;
}
speed.unit = unit;
};
})(document, Drupal, drupalSettings);
