artisan-1.x-dev/ui/theme-form.js

ui/theme-form.js
(function (Drupal, once, window) {

  Drupal.artisan_theme_form = {};

  Drupal.behaviors.artisan_theme_form = {
    attach(context) {
      // Color & palette.
      once('artisan-theme-form-color-field', '.artisan-theme-form-group input[type="color"]', context).forEach(colorField);
      once('artisan-theme-form-color-palette', '.artisan-theme-form-group.artisan-theme-form-group--palette input[type="color"]', context).forEach(paletteColorsDef);
      once('artisan-theme-form-color-palette', '.artisan-theme-form-group:not(.artisan-theme-form-group--palette) input[type="color"]', context).forEach(paletteColorsSet);

      // Extra widgets.
      once('artisan-theme-form-extra-widget', '.artisan-theme-form-group input.artisan-theme-extra-widget-numeric-input', context).forEach(numericInput);
      once('artisan-theme-form-extra-widget', '.artisan-theme-form-group input.artisan-theme-extra-widget-numeric-unit', context).forEach(numericUnit);
      once('artisan-theme-form-extra-widget', '.artisan-theme-form-group input.artisan-theme-extra-widget-font-weight', context).forEach(fontWeight);
      once('artisan-theme-form-extra-widget', '.artisan-theme-form-group input.artisan-theme-extra-widget-decoration', context).forEach(decoration);

      // Presets.
      once('artisan-theme-presets', '.artisan-theme-form-presets', context).forEach(initPresets);
    }
  };

  function decoration(element) {
    const deCoptions = new Map();
    deCoptions.set('_empty', Drupal.t('- Decoration select / Clear -'));
    deCoptions.set('underline', Drupal.t('Underline'));
    deCoptions.set('line-through', Drupal.t('Line-through'));
    deCoptions.set('overline', Drupal.t('Overline'));
    deCoptions.set('_other', Drupal.t('- Other -'));

    let deCwrapper = document.createElement('div');
    deCwrapper.classList.add('artisan-theme-form__widget-extra-wrapper');

    let deCselect = document.createElement('select');
    deCselect.classList.add('form-element', 'form-element--type-select');
    for (let [currentValue, currentLabel] of deCoptions) {
      let optionElement = document.createElement('option');
      optionElement.value = currentValue;
      optionElement.textContent = currentLabel;
      deCselect.appendChild(optionElement);
    };

    element.parentNode.classList.add('artisan-theme-form__autofocus');
    element.classList.add('artisan-theme-form__influenced');
    element.readOnly = true;

    deCselect.addEventListener("change", (event) => {
      if (event.target.value === '_other') {
        element.readOnly = false;
        element.focus();
      }
      else if (event.target.value === '_empty') {
        element.readOnly = true;
        element.value = '';
      }
      else {
        element.value = event.target.value;
        element.readOnly = true;
      }
    });

    element.addEventListener("focus", (event) => {
      if (event.target.readOnly) {
        deCselect.focus();
      }
    });

    deCwrapper.appendChild(deCselect);
    element.parentNode.appendChild(deCwrapper);

    if (element.value !== '') {
      deCselect.value = element.value;
      if (deCselect.value === '') {
        deCselect.value = '_other';
        element.readOnly = false;
      }
    }
  }

  function fontWeight(element) {
    const fWoptions = new Map();
    fWoptions.set('_empty', Drupal.t('- Weight select / Clear -'));
    fWoptions.set('lighter', Drupal.t('Lighter'));
    fWoptions.set('normal', Drupal.t('Normal'));
    fWoptions.set('bold', Drupal.t('Bold'));
    fWoptions.set('bolder', Drupal.t('Bolder'));
    fWoptions.set('100', Drupal.t('100 - Thin'));
    fWoptions.set('200', Drupal.t('200 - Extra Light'));
    fWoptions.set('300', Drupal.t('300 - Light'));
    fWoptions.set('400', Drupal.t('400 - Normal'));
    fWoptions.set('500', Drupal.t('500 - Medium'));
    fWoptions.set('600', Drupal.t('600 - Semi Bold'));
    fWoptions.set('700', Drupal.t('700 - Bold'));
    fWoptions.set('800', Drupal.t('800 - Extra Bold'));
    fWoptions.set('800', Drupal.t('900 - Black'));
    fWoptions.set('_other', Drupal.t('- Other -'));

    let fWwrapper = document.createElement('div');
    fWwrapper.classList.add('artisan-theme-form__widget-extra-wrapper');

    let fWselect = document.createElement('select');
    fWselect.classList.add('form-element', 'form-element--type-select');
    for (let [currentValue, currentLabel] of fWoptions) {
      let optionElement = document.createElement('option');
      optionElement.value = currentValue;
      optionElement.textContent = currentLabel;
      fWselect.appendChild(optionElement);
    };

    element.parentNode.classList.add('artisan-theme-form__autofocus');
    element.classList.add('artisan-theme-form__influenced');
    element.readOnly = true;

    fWselect.addEventListener("change", (event) => {
      if (event.target.value === '_other') {
        element.readOnly = false;
        element.focus();
      }
      else if (event.target.value === '_empty') {
        element.readOnly = true;
        element.value = '';
      }
      else {
        element.value = event.target.value;
        element.readOnly = true;
      }
    });

    element.addEventListener("focus", (event) => {
      if (event.target.readOnly) {
        fWselect.focus();
      }
    });

    fWwrapper.appendChild(fWselect);
    element.parentNode.appendChild(fWwrapper);

    if (element.value !== '') {
      fWselect.value = element.value;
      if (fWselect.value === '') {
        fWselect.value = '_other';
        element.readOnly = false;
      }
    }
  }

  function numericInput(element) {
    element.type = "number";
    element.min = "0";
    element.step = "0.1";
  }

  function numericUnit(element) {
    const unitOptions = {
      '_empty': Drupal.t('- Unit select / Clear -'),
      'px': Drupal.t('px - pixels'),
      'em': Drupal.t('em - relative to parent element'),
      'rem': Drupal.t('rem - relative to root/browser element'),
      'vw': Drupal.t('vw - relative to window width'),
      'vh': Drupal.t('vh - relative to window heigth'),
      '%': Drupal.t('% - percentage relative to parent element'),
      '_other': Drupal.t('- Other -')
    };
    let numericUnitWrapper = document.createElement('div');
    numericUnitWrapper.classList.add('artisan-theme-form__widget-extra-wrapper');
    let unitSelect = document.createElement('select');
    unitSelect.classList.add('form-element', 'form-element--type-select');
    Object.keys(unitOptions).forEach((currentValue) => {
      let optionElement = document.createElement('option');
      optionElement.value = currentValue;
      optionElement.textContent = unitOptions[currentValue];
      unitSelect.appendChild(optionElement);
    });

    let numericInput = document.createElement('input');
    numericInput.classList.add('form-element');
    numericInput.type = 'number';
    numericInput.min = '0';
    numericInput.step = '0.1';

    numericInput.addEventListener("change", (event) => {
      element.value = event.target.value + (unitSelect.value !== '_empty' && unitSelect.value !== '_other' ? unitSelect.value : '');
    });

    element.classList.add('artisan-theme-form__influenced');
    element.parentNode.classList.add('artisan-theme-form__autofocus');

    unitSelect.addEventListener("change", (event) => {
      if (event.target.value === '_other') {
        element.readOnly = false;
        element.focus();
        numericInput.classList.add('visually-hidden');
      }
      else if (event.target.value === '_empty') {
        element.readOnly = true;
        numericInput.value = '';
        numericInput.dispatchEvent(new Event('change'));
        numericInput.classList.remove('visually-hidden');
      }
      else {
        element.value = numericInput.value + event.target.value;
        element.readOnly = true;
        numericInput.classList.remove('visually-hidden');
      }
    });

    element.readOnly = true;
    numericUnitWrapper.appendChild(numericInput);
    numericUnitWrapper.appendChild(unitSelect);
    element.parentNode.appendChild(numericUnitWrapper);

    element.addEventListener("focus", (event) => {
      if (event.target.readOnly) {
        numericInput.focus();
      }
    });
    if (element.value !== '') {
      numericInput.value = element.value.replace(/[a-zA-Z]/g, '');
      unitSelect.value = element.value.replace(/[0-9\.,]/g, '');
      if (unitSelect.value === '') {
        numericInput.classList.add('visually-hidden');
        unitSelect.value = '_other';
      }
    }
  }

  function paletteColorsDef(paletteElement) {
    Drupal.artisan_theme_form[paletteElement.name] = {
      'label': paletteElement.parentNode.querySelector('label').textContent,
      'value': paletteElement.value.toUpperCase()
    };
    paletteElement.addEventListener("change", (event) => {
      Drupal.artisan_theme_form[paletteElement.name].value = event.target.value.toUpperCase();
      paletteElement.closest('form').querySelectorAll('.artisan-theme-form-group:not(.artisan-theme-form-group--palette) select').forEach((element) => {
        if (element.querySelector('option[value="'+ event.target.name +'"]')) {
          element.querySelector('option[value="'+ event.target.name +'"]').disabled = paletteElement.dataset.empty === event.target.value;
        }
        if (element.value === event.target.name) {
          element.parentNode.parentNode.querySelector('input[type="color"]').value = event.target.value;
          element.dispatchEvent(new Event('change'));
        }
      });
    });
  }

  function paletteColorsSet(element) {

    let paletteWrapper = document.createElement('div');
    paletteWrapper.classList.add('artisan-theme-form__widget-extra-wrapper');
    let paletteSelect = document.createElement('select');
    paletteSelect.classList.add('form-element', 'form-element--type-select');
    let paletteSelectOptionEmpty = document.createElement('option');
    paletteSelectOptionEmpty.value = '_empty';
    paletteSelectOptionEmpty.textContent = Drupal.t('- Palette select -');
    paletteSelect.appendChild(paletteSelectOptionEmpty);
    Object.keys(Drupal.artisan_theme_form).forEach((currentValue) => {
      let paletteSelectOption = document.createElement('option');
      if (Drupal.artisan_theme_form[currentValue].value === element.dataset.empty) {
        paletteSelectOption.disabled = true;
      }
      paletteSelectOption.value = currentValue;
      paletteSelectOption.textContent = Drupal.artisan_theme_form[currentValue].label;
      paletteSelect.appendChild(paletteSelectOption);
    });
    let paletteSelectOptionOther = document.createElement('option');
    paletteSelectOptionOther.value = '_other';
    paletteSelectOptionOther.textContent = Drupal.t('- Other -');
    paletteSelect.appendChild(paletteSelectOptionOther);
    paletteSelect.addEventListener("change", (event) => {
      if (event.target.value !== '_other' && event.target.value !== '_empty') {
        event.target.parentNode.parentNode.querySelector('input[type="color"]').value = Drupal.artisan_theme_form[event.target.value].value;
        event.target.parentNode.parentNode.querySelector('input[type="color"]').dispatchEvent(new Event('change'));
      }
      else if (event.target.value === '_other') {
        event.target.parentNode.parentNode.querySelector('input[type="color"]').click();
      }
      else if (event.target.value === '_empty') {
        event.target.parentNode.parentNode.querySelector('a.artisan-theme-form-color-clear').click();
      }
    });

    paletteWrapper.appendChild(paletteSelect);
    element.parentNode.appendChild(paletteWrapper);

//      element.parentNode.appendChild(paletteSelect);

    element.addEventListener("change", (event) => {
      let paletteActive = false;
      event.target.parentNode.querySelector('select').value = '_other';
      Object.keys(Drupal.artisan_theme_form).forEach((currentValue) => {
        if (!paletteActive && event.target.value !== event.target.dataset.empty && Drupal.artisan_theme_form[currentValue].value === event.target.value.toUpperCase()) {
          event.target.parentNode.querySelector('select').value = currentValue;
          paletteActive = true;
        }
      });
      if (!paletteActive && event.target.value === event.target.dataset.empty) {
        event.target.parentNode.querySelector('select').value = '_empty';
      }
      else if (!paletteActive) {
        event.target.parentNode.querySelector('select').value = '_other';
      }
    });
    element.dispatchEvent(new Event('change'));
  }

  /**
   * Color field.
   */
  function colorField(element) {
    let clearLink = document.createElement('a');
    clearLink.href = '#';
    clearLink.addEventListener('click', function (e) {
      e.preventDefault();
      e.stopPropagation();
      element.value = element.dataset.empty;
      element.dispatchEvent(new Event('change'));
    });
    clearLink.classList.add('artisan-theme-form-color-clear');
    clearLink.appendChild(document.createTextNode(Drupal.t('Clear')));
    element.parentNode.insertBefore(clearLink, element.nextSibling);

    if (element.value === element.dataset.empty) {
      clearLink.classList.add('artisan-theme-form-color-clear--cleared');
    }
    element.addEventListener('change', function (e) {
      if (e.target.value === e.target.dataset.empty) {
        clearLink.classList.add('artisan-theme-form-color-clear--cleared');
      }
      else {
        clearLink.classList.remove('artisan-theme-form-color-clear--cleared');
      }
    });
  }

  function initPresets(element) {
    function snake_case_string(str) {
      return str && str.match(
        /[A-Z]{2,}(?=[A-Z][a-z]+[0-9]*|\b)|[A-Z]?[a-z]+[0-9]*|[A-Z]|[0-9]+/g)
        .map(s => s.toLowerCase())
        .join('_');
    }
    let presets = {};
    if (element.value) {
      try {
        presets = JSON.parse(element.value);
      }
      catch (error) {
        const messages = new Drupal.Message();
        messages.clear();
        messages.add(Drupal.t('No valid presets stored, it will be reset on save (any new preset will be preserved). Invalid JSON format:<pre>:json</pre>', {':json': element.value}), {type: 'warning'});
        presets = {};
        element.value = '';
        // element.classList.remove('visually-hidden');
      }
    }

    presets['clear'] = {
      'label': Drupal.t('- Clear everything, use wisely! -'),
      'keys': {}
    };

    element.closest('.artisan-theme-form-presets-wrapper').querySelector('div[class*="description"] a').addEventListener('click', (event) => {
      event.preventDefault();
      event.stopPropagation();
      element.classList.toggle('visually-hidden');
    });

    let presetWrapper = document.querySelector('.artisan-theme-form-presets-wrapper');
    let presetInnerWrapper = document.createElement('div');
    presetInnerWrapper.classList.add('artisan-theme-form-presets-inner-wrapper');
    let presetsSelect = document.createElement('select');

    let presetsAddButton = document.createElement('button');
    let presetsApplyButton = document.createElement('button');
    let presetsRemoveButton = document.createElement('button');
    let addPresetText = document.createTextNode(Drupal.t('Create preset (current snap)'));
    let applyPresetText = document.createTextNode(Drupal.t('Apply / preview selected preset'));
    let removePresetText = document.createTextNode("Remove selected preset");
    let inputPresetName = document.createElement('input');
    inputPresetName.type = 'text';
    inputPresetName.classList.add('form-element');
    inputPresetName.placeholder = 'New preset name';
    presetsApplyButton.appendChild(applyPresetText);
    presetsApplyButton.classList.add('button');
    presetsRemoveButton.appendChild(removePresetText);
    presetsRemoveButton.classList.add('button', 'button--danger');
    presetsAddButton.appendChild(addPresetText);
    presetsAddButton.classList.add('button');
    refreshSelectOptions();
    presetsSelect.classList.add('form-element', 'form-element--type-select');
    presetWrapper.appendChild(presetInnerWrapper);
    presetInnerWrapper.appendChild(presetsSelect);
    presetInnerWrapper.appendChild(presetsApplyButton);
    presetInnerWrapper.appendChild(presetsRemoveButton);
    presetInnerWrapper.appendChild(inputPresetName);
    presetInnerWrapper.appendChild(presetsAddButton);

    presetsApplyButton.addEventListener("click", (event) => {
      event.preventDefault();
      event.stopPropagation();
      const messages = new Drupal.Message();
      messages.clear();
      if (presets[presetsSelect.value] === undefined) {
        messages.add(Drupal.t('Please select a preset to apply it'), {type: 'error'});
        return;
      }

      event.target.closest('form').querySelectorAll('.artisan-theme-form-group input[data-drupal-selector][name], .artisan-theme-form-group select[data-drupal-selector][name], .artisan-theme-form-group textarea[data-drupal-selector][name]').forEach((element) => {
        if (presets[presetsSelect.value] && presets[presetsSelect.value].keys && presets[presetsSelect.value].keys[element.name] !== undefined) {
          if (element.type === 'checkbox') {
            element.checked = presets[presetsSelect.value].keys[element.name];
          }
          else {
            element.value = presets[presetsSelect.value].keys[element.name];
          }
        }
        else {
          if (element.type === 'checkbox') {
            element.checked = false;
          }
          else {
            element.value = element.dataset.empty || '';
          }
        }
        element.dispatchEvent(new Event('change'));
      });


      messages.add(Drupal.t('Preset applied, please check preset modifications before consolidation by saving.'), {type: 'warning'});
    });

    presetsRemoveButton.addEventListener("click", (event) => {
      event.preventDefault();
      event.stopPropagation();
      const messages = new Drupal.Message();
      messages.clear();
      if (!presetsSelect.value || presetsSelect.value === 'clear' || presets[presetsSelect.value] === undefined) {
        messages.add(Drupal.t('Please select a preset to remove it'), {type: 'error'});
      }
      else {
        messages.add(Drupal.t('Preset :label removed', {':label': presets[presetsSelect.value].label}), {type: 'warning'});
        delete presets[presetsSelect.value];
        if (presets['clear']) {
          delete presets['clear'];
        }
        element.value = JSON.stringify(presets);
        presets['clear'] = {
          'label': Drupal.t('- Clear everything, use wisely! -'),
          'keys': {}
        };
        refreshSelectOptions();
      }
    });

    presetsAddButton.addEventListener("click", (event) => {
      event.preventDefault();
      event.stopPropagation();
      const messages = new Drupal.Message();
      messages.clear();

      if (Object.keys(presets).length > 10) {
        messages.add(Drupal.t('Maximum preset reached (10), please remove one to add a new one'), {type: 'error'});
        inputPresetName.value = '';
        return;
      }
      let presetKey = snake_case_string(inputPresetName.value) ||  'preset_' + (Object.keys(presets).length + 1);
      let presetLabel = inputPresetName.value || 'Preset ' + (Object.keys(presets).length + 1);
      presets[presetKey] = {
        'label': presetLabel,
        'keys': {}
      };
      event.target.closest('form').querySelectorAll('.artisan-theme-form-group input[data-drupal-selector][name], .artisan-theme-form-group select[data-drupal-selector][name], .artisan-theme-form-group textarea[data-drupal-selector][name]').forEach((element) => {
        if (element.type === 'checkbox') {
          if (element.checked) {
            presets[presetKey]['keys'][element.name] = element.checked;
          }
        }
        else if (element.value !== '' && element.value !== element.dataset.empty) {
          presets[presetKey]['keys'][element.name] = element.value;
        }
      });
      inputPresetName.value = '';
      messages.add(Drupal.t('New preset :label created, consolidate by saving', {':label': presetLabel}), {type: 'warning'});
      if (presets['clear']) {
        delete presets['clear'];
      }
      element.value = JSON.stringify(presets);
      presets['clear'] = {
        'label': Drupal.t('- Clear everything, use wisely! -'),
        'keys': {}
      };
      refreshSelectOptions();
    });

    function refreshSelectOptions() {
      presetsSelect.innerHTML = '';
      let defaultOption = document.createElement('option');
      defaultOption.value = '_empty';
      defaultOption.textContent = Drupal.t('- Preset select -');
      presetsSelect.appendChild(defaultOption);

      Object.keys(presets).forEach((currentValue) => {
        let optionElement = document.createElement('option');
        optionElement.value = currentValue;
        optionElement.textContent = presets[currentValue].label;
        presetsSelect.appendChild(optionElement);
      });
    }
  }
}(Drupal, once, window));

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

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