Subversion Repositories eFlore/Applications.cel

Rev

Rev 3897 | Blame | Compare with Previous | Last modification | View Log | RSS feed

import {findFieldset} from './utils.js';

// Variable permettant un seul affichage du titre
// de la prévisualisation pour les nouveaux champs
let firstClick = true;

/************************************************
 *  Fonction d'affichage des champs classiques  *
 ************************************************/

// Prévisualisation
export const displayClassicFields = () => {
  // Affichage du titre du widget
  renderFields($('#titre'), $('.widget-renderer h1'));
  // Affichage de la description
  renderFields($('#description'), $('.preview-description'));
  // Affichage referentiel
  $('#label-taxon span').text(` (${$('#referentiel').val()})`);
  $('#referentiel').change(function () {
    $('#label-taxon span').text(` (${$(this).val()})`);
  });

  // Affichage du logo s'il existe déjà
  if (0 !== $('#logo').val().length || $('#logo')[0].defaultValue) {
    $('#preview-logo').append(
      `<img src="${$('#group-settings-form .logo img').prop('src')}" width="75%">`
    );
  }
  // Affichage du logo chargé
  $('#logo.input-file').change(function(event) {
    // Si le 'change' n'était pas une suppression
    if ($.isEmptyObject(event.target.files[0])) {
      $('#preview-logo img').remove();
    // Si on a chargé un logo ou changé le fichier
    } else {
      $('#preview-logo').append(
        `<img src="${URL.createObjectURL(event.target.files[0])}" width="75%">`
      );
    }
  });
  // Affichage de l'image de fond
  $('#image_fond.input-file').on('change', evt => {
    if (!$.isEmptyObject(evt.target.files[0])) {
      $('.widget-renderer').css('background' ,`url(${URL.createObjectURL(evt.target.files[0])}) no-repeat fixed center center`);
    } else {
      $('.widget-renderer')[0].style.removeProperty('background');
    }
  });
}

// Affichage des infos dès que disponibles
// pour les champs classiques
const renderFields = ($source, $taget) => {
  let text = new DOMParser().parseFromString($source.val(), 'text/html');

  text = text.body.textContent || '';
  if ($source.val()) {
    $taget.text(text);
  }
  $source.on('change', () => $taget.text(text));
}


/*****************************************************
 *  Fonction d'affichage des champs supplémentaires  *
 *****************************************************/
// Prévisualisation des nouveaux champs
export const newFieldsPreview = function() {
  const count = $('fieldset').last().data('id');
  let $thisFieldset;

  // Si on a déjà prévisualisé on efface tout pour recommencer
  if (0 < $('.preview-fields').length) {
    $('.preview-fields').each(function () {
      $(this).remove();
    });
  }
  // Au premier ajout d'un champ dans la prévisualisation on ajoute un titre et un message
  if (true === firstClick) {
    $('#zone-supp').prepend(
      `<h2>Informations propres au projet</h2>
      <div class="message">L’objectif principal de cet aperçu est de vérifier les contenus et repérer d’éventuelles erreurs</div>`
    );
  }
  // Parcourir tous les blocs d'infos de champs supplémentaires
  for(let index = $('fieldset').first().data('id'); index <= count; index++) {
    $thisFieldset = findFieldset(index);
    // Certains indices peuvent correspondre à un champ supprimé
    if (0 < $($thisFieldset).length) {
      // Prévisualisation d'un champ
      $('#zone-supp .preview-container').append(
        `<div class="preview-fields col-sm-12 row" data-id="${index}">
          ${onClickPreviewField($thisFieldset, index)}
        </div>`
      );
      // Ajout/suppression d'un champ texte "Autre"
      if ($('.option-other-value', $thisFieldset).is(':checked')) {
        onOtherOption($thisFieldset, index);
      }
    }
  }
  // Le titre+message de la section prévisualisation ne sont ajoutés qu'une fois
  firstClick = false;
};

// Construction des éléments à visualiser
const onClickPreviewField = (thisFieldset, index) => {
  // Récupération des données
  const fieldKey    = $('.field-key'         , thisFieldset).val() || '',//clé
    fieldElement    = $('.field-element'     , thisFieldset).val() || '',//élément
    // Champs à valeur numérique ou date
    fieldStep       = $('.step'              , thisFieldset).val() || '',
    fieldMin        = $('.min'               , thisFieldset).val() || '',
    fieldMax        = $('.max'               , thisFieldset).val() || '',
    // Champs "listes"
    fieldDefaultNum = $('.default'           , thisFieldset).val() || '',// value range/number par default
    fieldOtherValue = $('.option-other-value', thisFieldset).is(':checked'),//option autre
    fieldOptions    = collectListOptions(thisFieldset);//Array: toutes les options
  let fieldLabel     = $('.field-name'        , thisFieldset).val() || '',//nom
    fieldTooltip     = $('.field-description' , thisFieldset).val() || '',//info-bulle
    fieldPlaceholder = $('.aide-saisie'       , thisFieldset).val() || '';//placeholder
  // Variables d'affichage
  const count     = fieldOptions.length,//nombre d'options, pour les boucles for
    replaceQuotes = text => text.replace(/(')/gm, '&apos;').replace(/(")/gm, '&quot;');
  let fieldHtml = '',//variable contenant tout le html à afficher
    fieldOption;

  // réafficher les apostrophes
  $.each([fieldLabel,fieldTooltip,fieldPlaceholder], (i,fieldValue) => replaceQuotes(fieldValue));

  //valeurs initiales des chaînes de caractères
  //Éléments simples ou chaînes communes aux "listes"
  let commonFieldsHtml = {//Éléments simples ou chaînes communes aux "listes"
    dataIdAttr : ' data-id="'+index+'"',
    helpButton : '',//bouton aide
    helpClass  : '',//classe de l'élément associé au bouton aide
    titleAttr  : '',//info-bulle
    fieldInput : {//attributs de l'élément
      typeAttr        : ' type="'+fieldElement+'"',
      nameAttr        : ' name="'+fieldKey+'"',
      classAttr       : ' class="'+fieldKey+'"',
      placeholderAttr : '',
      mandatoryAttr   : '',//required
      otherAttr       : ''
    },
    fieldLabel : {//attributs et contenu du label
      labelContent    : fieldLabel,//label
      forAttr         : ' for="'+fieldKey+'"',//attribut for
      classAttr       : '',//classe du label
      otherAttr       : ''//tous autres attributs
    }
  };
  // Pour les éléments de listes (select, checkbox, etc.)
  let listFieldsHtml = {//chaînes & html spécifiques aux listes
    containerContent : fieldLabel,//les options peuvent avoir chacune un label
    containerClass   : '',//une classe pour le conteneur
    forAttr          : '',//correspond à l'id d'une checkbox/radio/list-checkbox
    optionIdAttr     : '',//value-id
    defaultAttr      : ''//default
  };
  // Changement d'un élément existant:
  // supprimer le précédent pour ajouter le nouveau
  if (0 < $('.preview-fields', thisFieldset).length) {
    $('.preview-fields', thisFieldset).remove();
  }
  // Élément requis
  if ($('.field-is_mandatory', thisFieldset).is(':checked')) {
    // Attribut required pour le listes
    commonFieldsHtml.fieldInput.mandatoryAttr = ' required="required"';
    // Nom du champ (éléments listes)
    listFieldsHtml.containerContent = '* '+listFieldsHtml.containerContent;
    // Nom du champ (éléments simples)
    commonFieldsHtml.fieldLabel.labelContent = '* '+commonFieldsHtml.fieldLabel.labelContent;
  }
  // Infobulle
  if ('' !== fieldTooltip) {
    commonFieldsHtml.titleAttr = ' title="'+fieldTooltip+'"';
  }
  // Placeholder
  if ('' !== fieldPlaceholder) {
    commonFieldsHtml.fieldInput.placeholderAttr = ' placeholder="'+fieldPlaceholder+'"';
  }
  // Fichier d'aide
  if ('' !== $('.file-return.help-doc-'+index).text()) {
    // Bouton 'aide'
    commonFieldsHtml.helpButton = '<div class="help-button btn btn-outline-info btn-sm border-0"><i class="fas fa-info-circle"></i></div>';
    // classe 'aide'
    commonFieldsHtml.helpClass = ' and-help';
  }
  // html à ajouter en fonction de l'élément choisi
  switch(fieldElement) {
    case 'checkbox' :
    case 'radio' :
      listFieldsHtml.containerClass = ' class="'+fieldElement+'"';
      commonFieldsHtml.fieldLabel.classAttr = ' class="radio-label"';
      fieldHtml =
        // Conteneur
        '<div style="width:100%"'+
          // Class="L'élément choisi"
          listFieldsHtml.containerClass+
          // DataId
          commonFieldsHtml.dataIdAttr+
          // Required
          commonFieldsHtml.fieldInput.mandatoryAttr+
          // Info bulle
          commonFieldsHtml.titleAttr+
        ' >'+
          // Nom du champ
          // Classe 'and-help'
          '<div class="mt-3 list-label'+commonFieldsHtml.helpClass+'">'+
            // Label
            listFieldsHtml.containerContent+
            // Bouton 'help'
            commonFieldsHtml.helpButton+
          '</div>';
      // On déroule les différentes valeurs
      for( let i = 0; i < count; i++) {
        fieldOption = fieldOptions[i];
        // L'id de input
        listFieldsHtml.inputIdAttr = ' id="'+fieldOption.optionValue+'"';
        listFieldsHtml.forAttr = ' for="'+fieldOption.optionValue+'"';
        // Default
        listFieldsHtml.defaultAttr = '';//réinitialisation
        if (fieldOption.isDefault) {//affectation
          listFieldsHtml.defaultAttr = ' checked';
        }
        // L'indice de chaque option
        // L'option "autre" n'en a pas
        if ('' !== fieldOption.optionIndex) {
          listFieldsHtml.optionIdAttr = ' value-id="'+fieldOption.optionIndex+'"';
        }

        fieldHtml +=
          '<label'+
            // For
            listFieldsHtml.forAttr+
            // value-id
            listFieldsHtml.optionIdAttr+
            // Class du label
            commonFieldsHtml.fieldLabel.classAttr+
          '>'+
            '<input'+
              // Type
              commonFieldsHtml.fieldInput.typeAttr+
              // Id
              listFieldsHtml.inputIdAttr+
              // DataId
              commonFieldsHtml.dataIdAttr+
              // value-id
              listFieldsHtml.optionIdAttr+
              // Name
              commonFieldsHtml.fieldInput.nameAttr+
              // Value
              ' value="'+replaceQuotes(fieldOption.optionValue)+
              // Checked
              listFieldsHtml.defaultAttr+
              // Class="nom du champ"
              commonFieldsHtml.fieldInput.classAttr+
            '>'+
            // Label de l'option
            replaceQuotes(fieldOption.optionText)+
          '</label>';
      }
      // Si valeur "autre" est cochée
      if (fieldOtherValue) {
        fieldHtml +=
          '<label for="other"'+
            commonFieldsHtml.dataIdAttr+
            commonFieldsHtml.fieldLabel.classAttr+
          '>'+
            '<input'+
              commonFieldsHtml.fieldInput.typeAttr+
              ' id="other-'+fieldElement+'-'+index+'"'+
              commonFieldsHtml.fieldInput.nameAttr+
              ' value="other"'+
              commonFieldsHtml.fieldInput.classAttr+
              commonFieldsHtml.dataIdAttr+
            '>'+
          'Autre</label>';
        }
      // Fin du conteneur
      fieldHtml += '</div>';
      break;

    case 'list-checkbox':
      commonFieldsHtml.fieldLabel.classAttr = ' class="radio-label"';
      fieldHtml =
        // Classe 'and-help'
        '<div class="multiselect  add-field-select'+commonFieldsHtml.helpClass+'"'+
          // DataId
          commonFieldsHtml.dataIdAttr+
        '>'+
          '<label style="width:100%">'+
            // Nom du champ
            listFieldsHtml.containerContent+
            // Bouton 'help'
            commonFieldsHtml.helpButton+
          '</label>'+
          '<div class="mt-3">'+
            '<div class="selectBox"'+
              // DataId
              commonFieldsHtml.dataIdAttr+
            '>'+
              '<select'+
                // DataId
                commonFieldsHtml.dataIdAttr+
                // Required
                commonFieldsHtml.fieldInput.mandatoryAttr+
                // Info bulle
                commonFieldsHtml.titleAttr+
                // Class
                ' class="form-control custom-select '+fieldElement+'"'+
              '>'+
                // Apparait dans la barre de sélection
                '<option>Plusieurs choix possibles</option>'+
              '</select>'+
              '<div class="overSelect"></div>'+
            '</div>'+
            '<div class="checkboxes hidden"'+
              // DataId
              commonFieldsHtml.dataIdAttr+
            '>';
      // On déroule les différentes valeurs
      for( let i = 0; i < count; i++) {
        fieldOption = fieldOptions[i];
        // Type="checkbox"
        commonFieldsHtml.fieldInput.typeAttr = ' type="checkbox"';
        // Id
        listFieldsHtml.inputIdAttr = ' id="'+replaceQuotes(fieldOption.optionValue).toLowerCase()+'"';
        // For
        listFieldsHtml.forAttr = ' for="'+replaceQuotes(fieldOption.optionValue).toLowerCase()+'"';
        // Default
        listFieldsHtml.defaultAttr = '';//réinitialisation
        if (fieldOption.isDefault) {
          listFieldsHtml.defaultAttr = ' checked';//affectation
        }
        // value-id
        if ('' !== fieldOption.optionIndex) {
          listFieldsHtml.optionIdAttr = ' value-id="'+fieldOption.optionIndex+'"';
        }

        fieldHtml +=
          '<label'+
            // For
            listFieldsHtml.forAttr+
            // value-id
            listFieldsHtml.optionIdAttr+
            // Class du label
            commonFieldsHtml.fieldLabel.classAttr+
          '>'+
            '<input type="checkbox"'+
              // Id
              listFieldsHtml.inputIdAttr+
              // value-id
              listFieldsHtml.optionIdAttr+
              // Name
              commonFieldsHtml.fieldInput.nameAttr+
              // Value
              ' value="'+replaceQuotes(fieldOption.optionValue)+'"'+
              // Checked
              listFieldsHtml.defaultAttr+
              // Class="nom du champ"
              commonFieldsHtml.fieldInput.classAttr+
              // DataId
              commonFieldsHtml.dataIdAttr+
            '>'+
            // Label de l'option
            replaceQuotes(fieldOption.optionText)+
          '</label>';
      }
      // Si valeur "autre" est cochée
      if (fieldOtherValue) {
        fieldHtml +=
          '<label for="other"'+
            // DataId
            commonFieldsHtml.dataIdAttr+
          '>'+
            '<input type="checkbox"'+
              ' id="other-'+fieldElement+'-'+index+'"'+
              commonFieldsHtml.fieldInput.nameAttr+
              ' value="other"'+
              commonFieldsHtml.fieldInput.classAttr+
              // DataId
              commonFieldsHtml.dataIdAttr+
            '>'+
          'Autre</label>';
      }
      // Fermeture des conteneurs .multiselect .checkboxes
      fieldHtml +=
            '</div>'+
          '</div>'+
        '</div>';
      break;

    case 'select':
      commonFieldsHtml.fieldInput.classAttr = commonFieldsHtml.fieldInput.classAttr.slice(0, -1);
      commonFieldsHtml.fieldInput.classAttr += ' form-control custom-select"';
      fieldHtml =
        // Conteneur/Wrapper
        // +Classe 'and-help'
        '<div class="add-field-select '+fieldElement+commonFieldsHtml.helpClass+'"'+
          // DataID
          commonFieldsHtml.dataIdAttr+
        '>'+
          '<label class="mt-3" style="width:100%"'+
            commonFieldsHtml.fieldLabel.forAttr+
            // Info bulle
            commonFieldsHtml.titleAttr+
          '>'+
            // Nom du champ
            listFieldsHtml.containerContent+
            // Bouton 'help'
            commonFieldsHtml.helpButton+
          '</label>'+
          '<select'+
            commonFieldsHtml.fieldInput.nameAttr+
            ' id="'+fieldKey+'"'+
            // Class
            commonFieldsHtml.fieldInput.classAttr+
            // Required
            commonFieldsHtml.fieldInput.mandatoryAttr+
            // DataId
            commonFieldsHtml.dataIdAttr+
          '>';

      // On déroule les différentes valeurs
      for( let i = 0; i < count; i++) {
        fieldOption = fieldOptions[i];
        // Default
        listFieldsHtml.defaultAttr = '';//réinitialisation
        if (fieldOption.isDefault) {//affectation
          listFieldsHtml.defaultAttr = ' selected="selected"';
        }
        // value-id
        if ('' !== fieldOption.optionIndex) {
          listFieldsHtml.optionIdAttr = ' value-id="'+fieldOption.optionIndex+'"';
        }

        fieldHtml +=
          '<option'+
            // Value
            ' value="'+replaceQuotes(fieldOption.optionValue)+'"'+
            // Value-id
            listFieldsHtml.optionIdAttr+
            // Selected
            listFieldsHtml.defaultAttr+
          '>'+
            // Option
            replaceQuotes(fieldOption.optionText)+
          '</option>';
      }
      // Si valeur "autre" est cochée
      if (fieldOtherValue) {
        fieldHtml +=
          '<option class="other" value="other"'+commonFieldsHtml.dataIdAttr+'>'+
            'Autre'+
          '</option>';
      }
      // Fermeture des conteneurs
      fieldHtml +=
          '</select>'+
        // Fin du conteneur/wrapper
        '</div>';
      break;

    case 'textarea':
    // Ouvrir l'attribut class (suppression de '"')
      commonFieldsHtml.fieldInput.classAttr = commonFieldsHtml.fieldInput.classAttr.slice(0, -1);
      // Classe 'custom-range'
      commonFieldsHtml.fieldInput.classAttr += ' form-control"';
      // Classe 'and-help'
      commonFieldsHtml.fieldLabel.classAttr = ' class="mt-3 '+commonFieldsHtml.helpClass+'"';
      // Autres attributs
      commonFieldsHtml.fieldInput.otherAttr += ' id="'+fieldKey+'"';

      fieldHtml =
        '<label  style="width:100%"'+
          // For
          commonFieldsHtml.fieldLabel.forAttr+
          // Class
          commonFieldsHtml.fieldLabel.classAttr+
          // Info-bulle
          commonFieldsHtml.titleAttr+
          // Autres attributs
          commonFieldsHtml.fieldLabel.otherAttr+
        '>'+
          // Nom du champ
          commonFieldsHtml.fieldLabel.labelContent+
          // Bouton 'help'
          commonFieldsHtml.helpButton+
        '</label>'+
        '<textarea'+
          // Name
          commonFieldsHtml.fieldInput.nameAttr+
          // DataId
          commonFieldsHtml.dataIdAttr+
          // Class
          commonFieldsHtml.fieldInput.classAttr+
          // Info-bulle
          commonFieldsHtml.titleAttr+
          // Info-bulle
          commonFieldsHtml.fieldInput.placeholderAttr+
          // Required
          commonFieldsHtml.fieldInput.mandatoryAttr+
          // Autres attributs
          commonFieldsHtml.fieldInput.otherAttr+
        '></textarea>';
        break;

    case 'range':
      // Ouvrir l'attribut class (suppression de '"')
      commonFieldsHtml.fieldInput.classAttr = commonFieldsHtml.fieldInput.classAttr.slice(0, -1);
      // Classe 'custom-range'
      commonFieldsHtml.fieldInput.classAttr += ' custom-range form-control pl-3"';
      // Classe 'and-help'
      commonFieldsHtml.fieldLabel.classAttr = ' class="mt-3 '+commonFieldsHtml.helpClass+'"';
      // Step
      if ('' !== fieldStep) {
        commonFieldsHtml.fieldInput.otherAttr += ' step="'+fieldStep+'"';
      }
      // Min
      if ('' !== fieldMin) {
        commonFieldsHtml.fieldInput.otherAttr += ' min="'+fieldMin+'"';
      }
      //Max
      if ('' !== fieldMax) {
        commonFieldsHtml.fieldInput.otherAttr += ' max="'+fieldMax+'"';
      }
      fieldHtml =
        '<div'+
          ' class="range"'+
          ' id="'+fieldKey+'"'+
        '>'+
          '<label style="width:100%"'+
            // For
            commonFieldsHtml.fieldLabel.forAttr+
            // Class
            commonFieldsHtml.fieldLabel.classAttr+
            // Info-bulle
            commonFieldsHtml.titleAttr+
            // Autres attributs
            commonFieldsHtml.fieldLabel.otherAttr+
          '>'+
            // Nom du champ
            commonFieldsHtml.fieldLabel.labelContent+
            // Bouton 'help'
            commonFieldsHtml.helpButton+
          '</label>'+
          '<div class="col-sm-12 row" style="max-width=100%">'+
          // Visualiser min max et la valeur de range
            '<p class="col-sm-2 range-values text-center font-weight-bold">'+
              'Min '+fieldMin+
            '</p>'+
            '<div class="range-live-value range-values text-center font-weight-bold col-sm-7">'+
              fieldDefaultNum+
            '</div>'+
            '<p class="col-sm-2 range-values text-center font-weight-bold">'+
              'Max '+fieldMax+
            '</p>'+

            '<input'+
              // Type
              commonFieldsHtml.fieldInput.typeAttr+
              // Name
              commonFieldsHtml.fieldInput.nameAttr+
              // DataId
              commonFieldsHtml.dataIdAttr+
              // Class
              commonFieldsHtml.fieldInput.classAttr+
              // Info-bulle
              commonFieldsHtml.titleAttr+
              // Required
              commonFieldsHtml.fieldInput.mandatoryAttr+
              // Default
              ' value="'+fieldDefaultNum+'"'+
              // Autres attributs
              commonFieldsHtml.fieldInput.otherAttr+
            '>'+
          '</div>'
        '</div>';
        break;

    case 'number':
      // Step
      if ('' !== fieldStep) {
        commonFieldsHtml.fieldInput.otherAttr += ' step="'+fieldStep+'"';
      }
    case 'date':
      // Ouvrir l'attribut class (suppression de '"')
      commonFieldsHtml.fieldInput.classAttr = commonFieldsHtml.fieldInput.classAttr.slice(0, -1);
      // Classe 'and-help'
      commonFieldsHtml.fieldInput.classAttr += commonFieldsHtml.helpClass+' form-control"';
      // Min
      if ('' !== fieldMin) {
        commonFieldsHtml.fieldInput.otherAttr += ' min="'+fieldMin+'"';
      }
      // Max
      if ('' !== fieldMax) {
        commonFieldsHtml.fieldInput.otherAttr += ' max="'+fieldMax+'"';
      }
      // Class du label
      commonFieldsHtml.fieldLabel.classAttr = 'class="mt-3"';
      fieldHtml =
        '<div class="number">'+
          '<label style="width:100%"'+
            // For
            commonFieldsHtml.fieldLabel.forAttr+
            // Class
            commonFieldsHtml.fieldLabel.classAttr+
            // Info-bulle
            commonFieldsHtml.titleAttr+
            // Autres attributs
            commonFieldsHtml.fieldLabel.otherAttr+
          '>'+
            // Nom du champ
            commonFieldsHtml.fieldLabel.labelContent+
            // Bouton 'help'
            commonFieldsHtml.helpButton+
          '</label>'+
          '<input'+
            // Type
            commonFieldsHtml.fieldInput.typeAttr+
            // Name
            commonFieldsHtml.fieldInput.nameAttr+
            // DataId
            commonFieldsHtml.dataIdAttr+
            // Class
            commonFieldsHtml.fieldInput.classAttr+
            // Info-bulle
            commonFieldsHtml.titleAttr+
            // Placeholder
            commonFieldsHtml.fieldInput.placeholderAttr+
            // Required
            commonFieldsHtml.fieldInput.mandatoryAttr+
            // Default
            ' value="'+fieldDefaultNum+'"'+
            // Autres attributs
            commonFieldsHtml.fieldInput.otherAttr+
          '>'+
        '</div>';
        break;

    case 'text' :
    case 'email':
    default:
      // Ouvrir l'attribut class (suppression de '"')
      commonFieldsHtml.fieldInput.classAttr = commonFieldsHtml.fieldInput.classAttr.slice(0, -1);
      // Classe 'and-help'
      commonFieldsHtml.fieldInput.classAttr += commonFieldsHtml.helpClass+' form-control"';
      // Class du label
      commonFieldsHtml.fieldLabel.classAttr = 'class="mt-3"';

      fieldHtml =
        '<label style="width:100%"'+
          // For
          commonFieldsHtml.fieldLabel.forAttr+
          // Class
          commonFieldsHtml.fieldLabel.classAttr+
          // Info-bulle
          commonFieldsHtml.titleAttr+
          // Autres attributs
          commonFieldsHtml.fieldLabel.otherAttr+
        '>'+
          // Nom du champ
          commonFieldsHtml.fieldLabel.labelContent+
          // Bouton 'help'
          commonFieldsHtml.helpButton+
        '</label>'+
        '<input'+
          // Type
          commonFieldsHtml.fieldInput.typeAttr+
          // Name
          commonFieldsHtml.fieldInput.nameAttr+
          // DataId
          commonFieldsHtml.dataIdAttr+
          // Class
          commonFieldsHtml.fieldInput.classAttr+
          // Info-bulle
          commonFieldsHtml.titleAttr+
          // Placeholder
          commonFieldsHtml.fieldInput.placeholderAttr+
          // Required
          commonFieldsHtml.fieldInput.mandatoryAttr+
          // Autres attributs
          commonFieldsHtml.fieldInput.otherAttr+
        '>';
      break;
  }
  return fieldHtml;
}

// Construire un tableau des options pour chaque élément de listes
const collectListOptions = thisFieldset => {
  const $details = $('.field-details', thisFieldset),
    options = [];

  $details.find('.new-value').each(function () {
    options.push({
      // Valeur transmise (value)
      optionValue : $(this).find('.list-value').val().toLowerCase(),
      // Valeur Visible
      optionText  : $(this).find('.displayed-label').val(),
      // Booléen "default"
      isDefault   : $(this).find('.is-defaut-value').is(':checked'),
      // Indice de l'option
      optionIndex : $(this).data('list-value-id')
    });
  });
  return options;
}

// Faire apparaitre un champ text "Autre"
const onOtherOption = ($thisFieldset , index) => {
  // L'élément choisi
  const element         = $('.field-element', $thisFieldset).val(),
    thisPreviewFieldset = $(`.preview-fields[data-id=${index}]`),
    // html du champ "Autre"
    collectOther        =
      `<div class="col-sm-12 mt-1 collect-other-block">
        <label data-id="${index}" for="collect-other" style="font-weight:300">Autre option :</label>
        <input type="text" name="collect-other" data-id="${index}" class="collect-other form-control">
      </div>`,
    hasCheckboxes       = ['list-checkbox','checkbox'].includes(element),
    eventType           = hasCheckboxes ? 'click' : 'change';
  let fieldSelector = 'input';

  if('select' === element) {
    fieldSelector = 'select';
  } else if (hasCheckboxes) {
    fieldSelector += `#other-${element}-${index}`;
  }

  const $field = $(fieldSelector, thisPreviewFieldset);

  $field.on(eventType, function() {
    const hasOtherOption = hasCheckboxes ? ($field.is(':checked')) : ('other' === $field.val());

    if (hasOtherOption) {
      // Insertion du champ "Autre" après les boutons
      if ('list-checkbox' === element) {
        $('.checkboxes', thisPreviewFieldset).append(collectOther);
      } else {
        $('.'+element, thisPreviewFieldset).after(collectOther);
      }
    } else {
      // Suppression du champ autre
      $('.collect-other-block', thisPreviewFieldset).remove();
    }
  });
};