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);

Главная | Обратная связь

drupal hosting | друпал хостинг | it patrol .inc