Subversion Repositories eFlore/Applications.cel

Rev

Rev 3376 | Rev 3424 | Go to most recent revision | Details | Compare with Previous | Last modification | View Log | RSS feed

Rev Author Line No. Line
3167 idir 1
"use strict";
3165 idir 2
 
3174 idir 3
/*************************************
4
 *  Fonctions de Style et Affichage  *
5
 *      des éléments "spéciaux"      *
6
 *************************************/
3168 idir 7
 
3174 idir 8
// Logique d'affichage pour le input type=file
9
function inputFile() {
10
  // Initialisation des variables
11
  var $fileInput  = $( '.input-file' ),
12
      $button     = $( '.label-file' ),
13
      thisId = '';
14
  // Action lorsque la "barre d'espace" ou "Entrée" est pressée
15
  $( '.label-file' ).keydown( function( event ) {
16
    if ( event.keyCode == 13 || event.keyCode == 32 ) {
17
      $( '#' + $( this ).attr( 'for' ) + '.input-file' ).focus();
18
    }
19
  });
20
  // Action lorsque le label est cliqué
21
  $( '.label-file' ).click( function(event) {
22
    $( '#' + $( this ).attr( 'for' ) + '.input-file' ).focus();
23
    return false;
24
  });
25
  // Affiche un retour visuel dès que input:file change
26
  $fileInput.change( function( event ) {
27
    // Il est possible de supprimer un fichier
3226 idir 28
    // donc on vérifie que le 'change' est un ajout ou modificationis-defaut-value
3174 idir 29
    if( !$.isEmptyObject( event.target.files[0] ) ) {
3233 idir 30
 
3174 idir 31
      var file = event.target.files[0],
3233 idir 32
          fileInputId = $( this ).attr( 'id' ),
33
          $theReturn = $( '.' + fileInputId );
3174 idir 34
      // Affichage du nom du fichier
3233 idir 35
      $theReturn.text( file.name ).removeClass( 'hidden') ;
36
 
37
      if( 5242880 < file.size ) {
38
        $theReturn.append(
39
          '<p class="message">'+
40
            '<i class="fa fa-exclamation-triangle" aria-hidden="true" style="color:#ff5d55"></i> '+
41
            'La taille du fichier ne doit pas dépasser 5Mo'+
42
          '</p>'
43
        )
44
        .addClass( 'invalid' );
45
        // lib : https://resources.tela-botanica.org/jquery/form/3.51/jquery.form.min.js
46
        $( this ).clearInputs();
47
        console.log(file);
48
 
49
      } else if( file.type.match( 'image/*' ) && 'especes' !== fileInputId ) {
50
      // Si le fichier est une image (et qu'on est pas sur "especes") on l'affiche
3174 idir 51
        // Chemin temporaire de l'image et affichage
52
        var tmppath = URL.createObjectURL( file );
3233 idir 53
        $theReturn.append( '<img src="' + tmppath + '" width="50%">' ).removeClass( 'invalid' );;
54
 
3376 idir 55
      } else if ( !( 'especes' === fileInputId && file.type.match( 'text/(:?csv|tab-separated-values)' ) ) ) {
3233 idir 56
        // on a pas un type image, ou on est sur une liste d'espèces mais on a pas un csv
3376 idir 57
        console.log(file.type);
3233 idir 58
 
59
        if( 'especes' === fileInputId ) {// cas où on demandait un csv
60
          $theReturn.append(
61
            '<p class="message">'+
62
              '<i class="fa fa-exclamation-triangle" aria-hidden="true" style="color:#ff5d55"></i> '+
3376 idir 63
              'Le fichier doit être au format csv ou tsv'+
3233 idir 64
            '</p>'
65
          )
66
          .addClass( 'invalid' );
67
        } else { // cas où on demandait un format image
68
          $theReturn.append(
69
            '<p class="message">'+
70
              '<i class="fa fa-exclamation-triangle" aria-hidden="true" style="color:#ff5d55"></i> '+
71
              'Le fichier doit être au format image (jpg, png, etc.)'+
72
            '</p>'
73
          )
74
          .addClass( 'invalid' );
75
        }
3226 idir 76
        // lib : https://resources.tela-botanica.org/jquery/form/3.51/jquery.form.min.js
77
        $( this ).clearInputs();
78
        console.log(file);
3233 idir 79
      } else {// file "especes" csv ok
80
        $theReturn.append( ' <i class="fa fa-check-circle" aria-hidden="true" style="color:#B3C954;font-size:1.3rem"></i>' ).removeClass( 'invalid' );
3174 idir 81
      }
82
    }
83
  });
84
  // Annuler le téléchargement
85
  $( '.remove-file' ).click( function() {
86
    var $thisFileInput = $( this ).prev( '.input-file-container' ).find( '.input-file' );
3226 idir 87
    // lib : https://resources.tela-botanica.org/jquery/form/3.51/jquery.form.min.js
88
    $thisFileInput.clearInputs();
3174 idir 89
    $thisFileInput.triggerHandler( 'change' );
3226 idir 90
    // $thisFileInput.unwrap();
3174 idir 91
    $( this ).next( '.file-return' ).addClass( 'hidden' ).empty();
92
  });
93
}
3165 idir 94
 
3174 idir 95
// Style et affichage des list-checkboxes
96
function inputListCheckbox() {
97
  // On écoute le click sur une list-checkbox ('.selectBox')
98
  // à tout moment de son insertion dans le dom
3185 idir 99
  $( '#zone-appli' ).on( 'click' , '.selectBox' , function() {
3226 idir 100
    $( '.checkboxes[data-id="' + $(this).data( 'id' ) + '"]' ).toggleClass( 'hidden' );
3174 idir 101
  });
102
}
3165 idir 103
 
3186 idir 104
// Style et affichage des input type="range"
3185 idir 105
function inputRangeDisplayNumber() {
3241 idir 106
  $( '#zone-appli' ).on( 'input' , 'input[type="range"]' , function () {
107
    $( this ).siblings( '.range-live-value' ).text( $( this ).val() );
3185 idir 108
  });
3174 idir 109
}
3168 idir 110
 
3167 idir 111
/***********************************************************
112
 *  Fonctions pour la création des champs supplémentaires  *
113
 ***********************************************************/
114
 
115
// Logique globale pour l'ajout de nouveaux champs
3171 idir 116
function onClickAddNewFields( fieldIndex ) {
3174 idir 117
  // Bouton ajouter un champ
3167 idir 118
  $( '#add-fields' ).click( function() {
3174 idir 119
    // Affichage du formulaire pour un champ
3171 idir 120
    displayNewField( fieldIndex );
3174 idir 121
    // Affichage du nom du champ
3171 idir 122
    onChangeDisplayFieldLabel( fieldIndex );
3176 idir 123
    // Empêcher de créer plus d'une fois la même clé
124
    onChangeCheckKeyUnique();
3174 idir 125
    // Affichage des images/nom des documents importés dans les champs ajoutés
126
    inputFile();
127
    // Recueil des informations correspondantes au nouveau champ
3171 idir 128
    onChangeFieldTypeCollectDetails( fieldIndex );
3167 idir 129
    // Suppression d'un champ
130
    onClickRemoveField();
131
 
3171 idir 132
    fieldIndex++;
3167 idir 133
  });
3165 idir 134
}
135
 
3174 idir 136
// Création/affichage du formulaire d'un nouveau champ
3171 idir 137
function displayNewField( fieldIndex ) {
3174 idir 138
  // Html du formulaire du nouveaux champs inséré dans le dom
3168 idir 139
  $( '#new-fields' ).append(
3174 idir 140
    '<fieldset data-id="' + fieldIndex + '" class="new-field">'+
141
      '<h3>Nouveau champ :<br><strong class="field-title" data-id="' + fieldIndex + '"></strong></h3>'+
3167 idir 142
      // Nom du champ
3241 idir 143
      '<div class="row">'+
144
        '<div class="col-sm-12  mt-3">'+
145
          '<label for="field-name" title="Donnez un titre à votre champ">Nom du champ *</label>'+
146
          '<input type="text" name="field-name" data-id="' + fieldIndex + '" class="field-name form-control" placeholder="Titre de votre champ" title="Le titre du champ" required>'+
147
        '</div>'+
148
        // Clé du champ
149
        '<div class="col-sm-12  mt-3">'+
150
          '<label for="field-key" title="Nom du champ dans la base de données">'+
151
            'Clé du champ *'+
152
          '</label>'+
153
          '<input type="text" name="field-key" data-id="' + fieldIndex + '" class="field-key form-control" placeholder="Clé du champ" pattern="^(?:[a-z]+(?:(?:[A-Z]+[a-z]+)+)?|[a-z]+(?:(?:-[a-z]+)+)?)$" title="Clé Unique en Camelcase ou minuscule séparés par tirets, pas d\'accents pas de caractères spéciaux." required>'+
154
        '</div>'+
155
        '<p class="message ml-2 mr-2">' +
156
          '<i class="fa fa-exclamation-triangle" aria-hidden="true" style="color:#ff5d55"></i> '+
157
          'Une clé doit être unique<br>' +
158
          'En "camelCase" (ecriture chameau)<br>'+
159
          'Ou en minuscule avec tirets ("-") si nécessaire<br>'+
160
          'Pas d\'espaces, aucuns caractères spéciaux (accents, cédilles, etc.).' +
161
        '</p>' +
162
        // Type de champ
163
        '<div class="col-sm-12 mt-3 add-field-select" data-id="' + fieldIndex + '">'+
164
          '<label for="field-element" title="Quel type de champ">Type de champ *</label>'+
3262 idir 165
          '<select name="field-element" data-id="' + fieldIndex + '" class="field-element form-control custom-select">'+
3241 idir 166
            '<option value="text">Champ texte</option>'+
167
            '<option value="email">Champ email</option>'+
168
            '<option value="textarea">Champ rédaction</option>'+
169
            '<option value="select">Menu déroulant</option>'+
170
            '<option value="checkbox">Cases à cocher</option>'+
171
            '<option value="list-checkbox">Liste de cases à cocher</option>'+
172
            '<option value="radio">Boutons radio</option>'+
173
            '<option value="date">Calendrier</option>'+
174
            '<option value="range">Curseur (entre 2 bornes)</option>'+
175
            '<option value="number">Nombre</option>'+
176
          '</select>'+
177
        '</div>'+
178
        // Checkbox "champ requis"
179
        '<div class="col-sm-12 radio mt-3">'+
180
          '<label class="radio-label" for="field-is_mandatory" title="Ce champ est obligatoire">'+
181
            '<input type="checkbox" name="field-is_mandatory" data-id="' + fieldIndex + '" class="field-is_mandatory form-control">'+
182
            'Champ requis ?'+
183
          '</label>'+
184
        '</div>'+
185
        // Unité des valeurs
186
        '<div class="col-sm-12  mt-3">'+
187
          '<label for="field-unit" title="Unité de mesure de vos valeurs">Unités ( cm, kg, ha, etc.)</label>'+
188
          '<input type="text" name="field-unit" data-id="' + fieldIndex + '" class="field-unit form-control" placeholder="symbole de vos unités">'+
189
        '</div>'+
190
        // Tooltip
191
        '<div class="col-sm-12  mt-3">'+
192
          '<label for="field-description" title="Ajoutez une info-bulle">Info-bulle</label>'+
193
          '<input type="text" name="field-description" data-id="' + fieldIndex + '" class="field-description form-control" placeholder="Quelques mots">'+
194
        '</div>'+
195
        // Import d'une image d'aide à afficher en popup
196
        '<div class="input-file-row row">'+
197
          '<div class="input-file-container col-sm-10">'+
198
            '<input type="file" class="input-file field-help" name="field-help' + fieldIndex + '" data-id="' + fieldIndex + '" id="help-doc-' + fieldIndex + '" accept="image/*">'+
199
            '<label for="field-help' + fieldIndex + '" class="label-file"><i class="fas fa-download"></i> Popup aide image (.jpg)</label>'+
200
          '</div>'+
201
          '<div class="btn btn-danger btn-sm remove-file" name="remove-file" data-id="' + fieldIndex + '" title="Supprimer le fichier"><i class="fas fa-times" aria-hidden="true"></i></div>'+
202
          '<div class="file-return help-doc-' + fieldIndex + ' hidden"></div>'+
203
        '</div>'+
204
        // Boutons supprimer
205
        '<div class="col-sm-12  mt-3">'+
206
          '<label for="remove-field">Supprimer</label>'+
207
          '<div class="remove-field button" name="remove-field" data-id="' + fieldIndex + '" title="Supprimer un champ"><i class="fa fa-skull" aria-hidden="true"></i></div>'+
208
        '</div>'+
3167 idir 209
      '</div>'+
3174 idir 210
    '</fieldset>'
3168 idir 211
  );
212
  // Animation de l'affichage
3174 idir 213
  $( 'fieldset.new-field[data-id="' + fieldIndex + '"]').hide().show( 200 );
3168 idir 214
}
3167 idir 215
 
3168 idir 216
// Affichage du nom du champ dès qu'il est renseigné
3171 idir 217
function onChangeDisplayFieldLabel( fieldIndex ) {
3174 idir 218
  $('.field-name[data-id="' + fieldIndex + '"]').change( function() {
219
    $( '.field-title[data-id="' + fieldIndex + '"]' ).text( $( this ).val() );
3168 idir 220
  });
3167 idir 221
}
3166 idir 222
 
3174 idir 223
// Supprimer un nouveau champ
3226 idir 224
function onClickRemoveField () {
3174 idir 225
  $( '.remove-field' ).click( function() {
3226 idir 226
    $( this ).closest('fieldset').hide( 200 , function () {
227
      $( this ).remove();
3174 idir 228
    });
3167 idir 229
  });
230
}
3165 idir 231
 
3171 idir 232
 
3167 idir 233
/**** Recueil des informations et détails qui dépendent du type de champ choisi ****/
3166 idir 234
 
3167 idir 235
// Logique de recueil d'informations en fonction du type de champ choisi
3171 idir 236
function onChangeFieldTypeCollectDetails( fieldIndex ) {
3174 idir 237
  // On insère les champs par défaut de recueil d'informations
238
  displayFieldDetailsCollect(
239
    fieldIndex,
3168 idir 240
    // Placeholder (champ type text par défaut)
3241 idir 241
    '<div class="col-sm-12  mt-3">'+
242
      '<label for="aide-saisie" title="Aidez les utilisateurs en deux ou 3 mots ou chiffres à comprendre ce que doit contenir le champ">Texte d\'aide à la saisie</label>'+
243
      '<input type="text" name="aide-saisie" data-id="' + fieldIndex + '" class="aide-saisie form-control" placeholder="Ce que doit contenir le champ">'+
244
    '</div>'
3174 idir 245
  );
3171 idir 246
  // Sinon :
3174 idir 247
  $( '.field-element[data-id="' + fieldIndex + '"]' ).change( function() {
3171 idir 248
    // On intialise l'index pour les listes la variable qui contiendra un id pour chaque option
249
    var valueIndex = 0;
3167 idir 250
    // Si on hésite on qu'on se trompe dans la liste :
251
    // les champs de détails de l'option précédente doivent être supprimés
3174 idir 252
    $( '.field-details[data-id="' + fieldIndex + '"]' ).hide( 200 , function () {
3226 idir 253
      $( this ).remove();
3174 idir 254
    });
3167 idir 255
 
3174 idir 256
    // Html de recueil de données en fonction de l'élément choisi
3167 idir 257
    switch( $( this ).val() ) {
3241 idir 258
      case 'range':
3167 idir 259
      case 'number':
3174 idir 260
        displayFieldDetailsCollect(
261
          fieldIndex,
3241 idir 262
          '<p class="message">'+
263
            '<i class="fa fa-exclamation-triangle" aria-hidden="true" style="color:#ff5d55"></i> '+
264
            'Ne pas oublier de prévisualiser !!<br>'+
265
            'Vérifier le bon fonctionnement et changer, si nécessaire, les valeurs de défaut, incrémentation (step), min et max.<br>'+
266
            'Si le navigateur considère que certaines valeurs sont incohérentes il pourrait les modifier automatiquement'+
267
          '</p>' +
3167 idir 268
          // Placeholder
3241 idir 269
          '<div class="col-sm-12  mt-3">'+
270
            '<label for="aide-saisie" title="Deux ou 3 mots ou chiffres pour comprendre ce que doit contenir le champ (ex: min 20, 10 par 10, etc.)">Texte d\'aide à la saisie</label>'+
271
            '<input type="text" name="aide-saisie" data-id="' + fieldIndex + '" class="aide-saisie form-control" placeholder="Ce que doit contenir le champ">'+
272
          '</div>'+
3167 idir 273
          // Valeur par défaut
3241 idir 274
          '<div class="col-sm-12  mt-3">'+
275
            '<label for="default" title="Valeur par défaut">Valeur par défaut</label>'+
276
            '<input type="number" name="default" data-id="' + fieldIndex + '" class="default form-control" step="0.01" lang="en">'+
277
          '</div>'+
3167 idir 278
          // Incrémentation ( attribut step="" )
3241 idir 279
          '<div class="col-sm-12  mt-3">'+
280
            '<label for="step" title="De 10 en 10, de 0.5 en 0.5, etc.">Incrémentation (step)</label>'+
281
            '<input type="number" name="step" data-id="' + fieldIndex + '" class="step form-control" step="0.01" value="1" lang="en">'+
282
          '</div>'+
3167 idir 283
          // Min
3241 idir 284
          '<div class="col-sm-12  mt-3">'+
285
            '<label for="min" title="valeur min">Valeur minimale</label>'+
286
            '<input type="number" name="min" data-id="' + fieldIndex + '" class="min form-control" step="0.01" value="0" lang="en">'+
287
          '</div>'+
3167 idir 288
          // Max
3241 idir 289
          '<div class="col-sm-12  mt-3">'+
290
            '<label for="max" title="valeur max">Valeur maximale</label>'+
291
            '<input type="number" name="max" data-id="' + fieldIndex + '" class="max form-control" step="0.01" value="1" lang="en">'+
292
          '</div>'
3174 idir 293
        );
3167 idir 294
        break;
295
 
296
      case 'date':
3174 idir 297
        displayFieldDetailsCollect(
298
          fieldIndex,
3167 idir 299
          // Date min
3241 idir 300
          '<div class="col-sm-12 mt-3">'+
301
            '<label for="min" title="date min">Date minimale</label>'+
302
            '<input type="date" name="min" data-id="' + fieldIndex + '" class="min form-control" pattern="(^(((0[1-9]|1[0-9]|2[0-8])[\/](0[1-9]|1[012]))|((29|30|31)[\/](0[13578]|1[02]))|((29|30)[\/](0[4,6,9]|11)))[\/](19|[2-9][0-9])\d\d$)|(^29[\/]02[\/](19|[2-9][0-9])(00|04|08|12|16|20|24|28|32|36|40|44|48|52|56|60|64|68|72|76|80|84|88|92|96)$)" title="jj/mm/aaaa">'+
303
          '</div>'+
3167 idir 304
          // Date max
3241 idir 305
          '<div class="col-sm-12 mt-3">'+
306
            '<label for="max" title="date max">Date maximale</label>'+
307
            '<input type="date" name="max" data-id="' + fieldIndex + '" class="max form-control"  pattern="(^(((0[1-9]|1[0-9]|2[0-8])[\/](0[1-9]|1[012]))|((29|30|31)[\/](0[13578]|1[02]))|((29|30)[\/](0[4,6,9]|11)))[\/](19|[2-9][0-9])\d\d$)|(^29[\/]02[\/](19|[2-9][0-9])(00|04|08|12|16|20|24|28|32|36|40|44|48|52|56|60|64|68|72|76|80|84|88|92|96)$)" title="jj/mm/aaaa">'+
308
          '</div>'
3174 idir 309
        );
3167 idir 310
        break;
311
 
312
      case 'select':
313
      case 'checkbox':
314
      case 'list-checkbox':
315
      case 'radio':
3174 idir 316
        displayFieldDetailsCollect(
317
          fieldIndex,
3188 idir 318
          '<p class="message element-message">' +
319
            '<i class="fa fa-exclamation-triangle" aria-hidden="true" style="color:#ff5d55"></i> ' +
320
            'Entrez au moins une valeur de ' + $( this ).children( 'option:selected' ).text() +
3346 idir 321
            '<br>Si aucun label à afficher n\'est indiqué, la valeur entrée sera utilisée (première lettre en majuscule).'+
3188 idir 322
          '</p>'+
323
          // Première option
3241 idir 324
          '<div class="new-value center-block row" data-list-value-id="' + valueIndex +'">'+
3188 idir 325
            // Recueil d'une valeur de la liste
3241 idir 326
            '<div class="col-sm-12 mt-3">'+
3346 idir 327
              '<label for="list-value">Valeur *</label>'+
3241 idir 328
              '<input type="text" name="list-value" data-id="' + fieldIndex + '" class="list-value form-control" data-list-value-id="' + valueIndex +'" placeholder="Une des valeurs de la liste" required>'+
329
            '</div>' +
3346 idir 330
            // Recueil du label à afficher
331
            '<div class="col-sm-12 mt-3">'+
332
              '<label for="displayed-label">Label</label>'+
333
              '<input type="text" name="displayed-label" data-id="' + fieldIndex + '" class="displayed-label form-control" data-list-value-id="' + valueIndex +'" placeholder="Label à afficher">'+
334
            '</div>' +
3188 idir 335
            // Checkbox valeur par défaut
3241 idir 336
            '<div class="col-sm-12 radio mt-3">'+
337
              '<label for="is-defaut-value" title="Ceci est la valeur par défaut" class="radio-label">'+
338
                '<input type="checkbox" name="is-defaut-value" data-id="' + fieldIndex + '" class="is-defaut-value" title="entrez une valeur pour activer cette case" data-list-value-id="' + valueIndex +'" disabled >'+
339
                'Valeur par défaut'+
340
              '</label>'+
341
            '</div>' +
3188 idir 342
          '</div>' +
3167 idir 343
          // Bouton ajout d'une valeur à la liste
3241 idir 344
          '<div class="col-sm-12 mt-3 add-value-container" data-id="' + fieldIndex + '">'+
345
            '<label for="add-value" class="add-value" data-id="' + fieldIndex + '" title="Ajouter une valeur à la liste">Ajouter une valeur</label>'+
346
            '<div class="button add-value-button" name="add-value" data-id="' + fieldIndex + '" title="Ajouter une valeur à la liste"><i class="fa fa-puzzle-piece" aria-hidden="true"></i></div>'+
347
          '</div>' +
3167 idir 348
          // checkbox ajouter une valeur "Autre:"
3241 idir 349
          '<div class="col-sm-12 radio mt-3">'+
350
            '<label for="option-other-value" title="Ajouter une option \'Autre:\' à la fin" class="radio-label">'+
351
              '<input type="checkbox" name="option-other-value" data-id="' + fieldIndex + '" class="option-other-value" title="Ajouter une option \'Autre\' à la fin">'+
352
              'Valeur "Autre"'+
353
            '</label>'+
354
          '</div>'
3174 idir 355
        );
3168 idir 356
        break;
357
 
358
      case 'email':
3167 idir 359
      case 'text':
360
      case 'textarea':
361
      default:
3174 idir 362
        displayFieldDetailsCollect(
363
          fieldIndex,
3167 idir 364
        // Placeholder
3241 idir 365
        '<div class="col-sm-12 mt-3">'+
366
          '<label for="aide-saisie" title="Aidez les utilisateurs en deux ou 3 mots ou chiffres à comprendre ce que doit contenir le champ">Texte d\'aide à la saisie</label>'+
3244 idir 367
          '<input type="text" name="aide-saisie" data-id="' + fieldIndex + '" class="aide-saisie form-control" placeholder="Ce que doit contenir le champ">'+
3241 idir 368
        '</div>'
3174 idir 369
      );
3167 idir 370
        break;
371
    }
372
    // Ajout des valeurs possibles
373
    // lorsque le champ est une liste ou case à cocher
3171 idir 374
    onClickAddNewValueToList( fieldIndex , valueIndex );
3167 idir 375
  });
3165 idir 376
}
377
 
3167 idir 378
// Insertion dans le dom des champs de recueil d'informations
3171 idir 379
function displayFieldDetailsCollect( fieldIndex , fieldDetails ) {
3174 idir 380
  $( '.add-field-select[data-id="' + fieldIndex + '"]' ).after(
3241 idir 381
    '<div class="field-details col-sm-11 mt-3 row" data-id="' + fieldIndex + '">' +
3174 idir 382
      fieldDetails +
383
    '</div>'
384
  ).hide().show( 200);
3167 idir 385
}
3165 idir 386
 
3167 idir 387
/**** Ajout des valeurs (options) des "champs de listes" (select, checkbox, radio, etc.) ****/
3165 idir 388
 
3174 idir 389
// Ajout des options des listes (deroulantes, cases à cocher etc.)
3171 idir 390
function onClickAddNewValueToList( fieldIndex , valueIndex ) {
3174 idir 391
  $( '.add-value-button[data-id="' + fieldIndex + '"]' ).click( function() {
3188 idir 392
    valueIndex++;
3241 idir 393
    $( '.add-value-container[data-id="' + fieldIndex + '"]' ).before(
394
      '<div class="new-value center-block row" data-list-value-id="' + valueIndex +'">'+
3167 idir 395
        // Recueil d'une valeur de la liste
3241 idir 396
        '<div class="col-sm-12 mt-3">'+
3346 idir 397
          '<label for="list-value">Valeur *</label>'+
3241 idir 398
          '<input type="text" name="list-value" data-id="' + fieldIndex + '" class="list-value form-control" data-list-value-id="' + valueIndex +'" placeholder="Une des valeurs de la liste" required>'+
399
        '</div>' +
3346 idir 400
        // Recueil du label à afficher
401
        '<div class="col-sm-12 mt-3">'+
402
          '<label for="displayed-label">Label</label>'+
403
          '<input type="text" name="displayed-label" data-id="' + fieldIndex + '" class="displayed-label form-control" data-list-value-id="' + valueIndex +'" placeholder="Label à afficher">'+
404
        '</div>' +
3174 idir 405
        // Checkbox valeur par défaut+bouton supprimer
3241 idir 406
        '<div class="col-sm-12 mt-3 row">'+
407
          // Bouton supprimer une option
408
          '<div class="col-sm-5">'+
3174 idir 409
            '<div class="remove-value button" name="remove-value" data-id="' + fieldIndex + '" data-list-value-id="' + valueIndex + '" title="Supprimer une valeur"><i class="fa fa-trash" aria-hidden="true"></i></div>'+
3167 idir 410
          '</div>'+
3241 idir 411
          // Valeur par défaut
412
          '<div class="col-sm-7 radio">'+
413
            '<label for="is-defaut-value" title="Ceci est la valeur par défaut" class="radio-label">'+
414
              '<input type="checkbox" name="is-defaut-value" data-id="' + fieldIndex + '" class="is-defaut-value" title="entrez une valeur pour activer cette case" data-list-value-id="' + valueIndex +'" disabled >'+
415
              'Valeur défaut'+
416
            '</label>'+
417
          '</div>'+
3167 idir 418
        '</div>'+
3168 idir 419
      '</div>'
3174 idir 420
    ).hide().show( 200);
421
    // Une seule valeur par défaut pour select et radio
3171 idir 422
    onClickDefaultValueRemoveOthers( fieldIndex );
3174 idir 423
    // Supprimer une valeur
3171 idir 424
    onClickRemoveListValue( fieldIndex );
425
  });
426
}
3167 idir 427
 
3171 idir 428
// Activer la checkbox de valeur par default uniquement si une valeur est entrée
3226 idir 429
function onInputListValueLabelEnableDefaultCheckbox() {
430
  $( '#new-fields' ).on( 'input' , '.list-value' , function() {
3241 idir 431
    var $thisDefautValue = $( '.is-defaut-value[data-id="' + $( this ).data( 'id' ) + '"][data-list-value-id="' + $( this ).data( 'list-value-id' ) + '"]' );
3226 idir 432
    if( '' !== $( this ).val() ) {
3241 idir 433
      $thisDefautValue.removeAttr( 'disabled' );
3174 idir 434
    } else {
3241 idir 435
      $thisDefautValue.attr( 'disabled', true ).attr( 'checked' , false );
3174 idir 436
    }
3167 idir 437
  });
438
}
439
 
3174 idir 440
// Pour les éléments "select" et "radio" il ne peut y avoir qu'une valeur par défaut cochée
3171 idir 441
function onClickDefaultValueRemoveOthers( fieldIndex ) {
3174 idir 442
  var selectedFieldElement = $( '.field-element[data-id="' + fieldIndex + '"]' ).val();
3167 idir 443
 
3174 idir 444
  if( selectedFieldElement === 'select' || selectedFieldElement === 'radio' ) {
445
    $( '.is-defaut-value[data-id="' + fieldIndex + '"]' ).click( function() {
3233 idir 446
     if( $( this ).is( ':checked' ) ) {
3174 idir 447
        // Décocher tous les autres
3233 idir 448
        $( '.is-defaut-value[data-id="' + fieldIndex + '"]:checked' ).not( $( this) ).attr( 'checked' , false );
3174 idir 449
      }
450
    });
451
  }
3167 idir 452
}
453
 
3174 idir 454
// Bouton supprimer une valeur
3171 idir 455
function onClickRemoveListValue( fieldIndex ) {
3174 idir 456
  $( '.remove-value.button[data-id="' + fieldIndex + '"]' ).click( function() {
3226 idir 457
    $( '.new-value[data-list-value-id="' + $( this ).data( 'list-value-id' ) + '"]' ).hide( 200 , function () {
458
      $( this ).remove();
3174 idir 459
    });
3167 idir 460
  });
461
}
462
 
3171 idir 463
/*********************************************
464
 *  Validation et envoi des nouveaux champs  *
465
 *********************************************/
3168 idir 466
 
3176 idir 467
// Empêcher de créer plus d'une fois la même clé
468
function onChangeCheckKeyUnique() {
469
 if( 1 < $( '.field-key' ).length ) {
3177 idir 470
    // Marqueur de valeur dupliquée
3183 idir 471
    var notUnique = false;
3176 idir 472
 
473
    $( '.field-key' ).change( function () {
3177 idir 474
      let count = $( '.field-key' ).length;
3176 idir 475
 
476
      for(var index = 0 ; index < count ; index++) {
3177 idir 477
        let thisFieldKey = $( '.field-key[data-id="' + index + '"]' );
3241 idir 478
        // Le champ avec cet index pourrait avoir été supprimé
3177 idir 479
        if( 0 < thisFieldKey.length ) {
480
          for( var otherIndex = 0 ; otherIndex < count ; otherIndex++ ) {
481
            let otherFieldKey = $( '.field-key[data-id="' + otherIndex + '"]' );
482
            // Le champ avec cet index pourrait avoir été supprimé
483
            // On vérifie qu'on ne compare pas un champ avec lui-même
484
            // Que les champs ne sont pas vides
485
            // Les champs dupliqués déclanchent le marqueur et les alertes
486
            if(
487
 
488
              index !== otherIndex &&
489
              '' !== otherFieldKey.val() &&
490
              '' !== thisFieldKey.val() &&
491
              thisFieldKey.val() === otherFieldKey.val()
492
            ) {
493
              // Le marqueur de valeur dupliquée passe à true
494
              notUnique = true;
495
              if( 0 === $( '.invalid-field-key[data-id="' + index + '"]' ).length ) {
496
                // Le champ est signalé en rouge
497
                // Un message d'alerte apparait sous le champ
3188 idir 498
                thisFieldKey.addClass( 'invalid-key' );
3177 idir 499
                thisFieldKey.after(
500
                  '<p class="message invalid-field-key" data-id="' + index + '">' +
501
                    '<i class="fa fa-exclamation-triangle" aria-hidden="true" style="color:#ff5d55"></i>' +
502
                    ' Vérifiez qu\'aucune clé n\'ait été utilisée plus d\'une fois'  +
503
                  '</p>'
504
                );
505
              }
506
            }
507
          }
3176 idir 508
        }
509
      }
510
      if( notUnique ) {
511
        // Un message d'alerte apparait au dessus des boutons prévisualiser/valider
512
        if( 0 === $( '.invalid-field-key-bottom' ).length ) {
3177 idir 513
          $( '#new-fields' ).after(
3176 idir 514
            '<p class="message invalid-field-key-bottom">' +
515
              '<i class="fa fa-exclamation-triangle" aria-hidden="true" style="color:#ff5d55"></i>' +
516
              ' Une clé a été utilisée plusieurs fois' +
517
            '</p>'
518
          );
519
        }
520
        // Les boutons prévisualiser/valider sont désactivés et signalés en rouge
3188 idir 521
        $( '#preview-field , #validate-new-fields' ).addClass( 'invalid-key' ).css( 'pointer-events', 'none' );
3177 idir 522
      } else {// Si on est ok on retire toutes les alertes
523
        // signalements rouges
524
        $( '.field-key' ).each( function() {
3188 idir 525
          $( this ).removeClass( 'invalid-key' );
3177 idir 526
        });
3188 idir 527
        $( '#preview-field , #validate-new-fields' ).removeClass( 'invalid-key' );
3177 idir 528
        // messages d'alerte
529
        $( '.invalid-field-key' ).each( function() {
530
          $( this ).hide( 200 , function () {
531
            $( this ).remove();
532
          });
3176 idir 533
        });
534
        $( '.invalid-field-key-bottom' ).hide( 200 , function () {
535
          $( this ).remove();
536
        });
3177 idir 537
        //réactivation des boutons prévisualiser/valider
3176 idir 538
        $( '#preview-field' )[0].style.removeProperty( 'pointer-events' );
539
        $( '#validate-new-fields' )[0].style.removeProperty( 'pointer-events' )
540
      }
541
      // Réinitialisation
542
      notUnique = false;
543
    });
544
  }
545
}
546
 
3188 idir 547
// Activation/desactivation des champs valider/previsualiser
548
function onClickButtonsTagMissingValues() {
549
  $( '#preview-field , #validate-new-fields' ).on( 'click' , function() {
550
    var $button = $( this );
551
    //S'il n'y a pas (plus) de bloc nouveau champ
3174 idir 552
    if( 0 === $( 'fieldset' ).length ) {
553
      return;
554
    }
3188 idir 555
    // Classe "invalid"
556
    missingValuesClass();
557
    if( !$( this ).hasClass( 'invalid' ) ) {
558
      if( $( this ).is( '#validate-new-fields') ) {
559
        // Lancement de l'enregistrement des valeurs à transmettre
560
        onClickStoreNewFields();
561
      } else if( $( this ).is( '#preview-field') ) {
562
        // Lancement de la prévisualisation
563
        newFieldsPreview();
3171 idir 564
      }
3174 idir 565
    }
3188 idir 566
  });
567
  // Si un champ manquant est renseigné
568
  // ou on choisit nouvel élément liste (au moins une option)
569
  // Cette action doit être prise en compte dans la validation
570
  $( '#new-fields' ).on( 'change' , '.invalid[type="text"] , .field-element' , function() {
571
    // S'il on a pas encore cliqué sur prévisualiser/valider
572
    // changer l'élément ne doit pas déclancher le signalement en rouge
573
    if( $( this ).is( '.field-element' ) && !$( '#preview-field , #validate-new-fields' ).hasClass( 'invalid' ) ) {
574
      return;
575
    } else {
576
      // Classe "invalid"
577
      missingValuesClass();
578
    }
579
  });
580
}
581
 
582
// Classe "invalid"
583
function missingValuesClass() {
584
  // Si au moins un champ "required" n'est pas rempli
585
  $( '#new-fields input[required]' ).each( function() {
586
    if( 0 === $( this ).val().length ) {
587
      // Le champ est signalé en rouge
588
      $( this ).addClass( 'invalid' );
589
      // Un message d'alerte apparait après le champ
3226 idir 590
      if( 0 === $( this ).next( '.validation-warning' ).length ) {
591
        $( this ).after(
3174 idir 592
          '<p class="validation-warning message">' +
593
            '<i class="fa fa-exclamation-triangle" aria-hidden="true" style="color:#ff5d55"></i>' +
3188 idir 594
             '&nbsp;Ce champ est requis' +
3174 idir 595
          '</p>'
596
        );
597
      }
598
    } else {
3188 idir 599
      // Le champ est signalé en rouge
600
      $( this ).removeClass( 'invalid' );
601
      // Le message d'alerte du champ est supprimé
3226 idir 602
      if( 0 < $( this ).next( '.validation-warning' ).length ) {
3188 idir 603
        $( this ).next( '.validation-warning' ).hide( 200 , function () {
604
          $( this ).remove();
605
        });
3174 idir 606
      }
607
    }
608
  });
3188 idir 609
  // Si on a des champs à compléter
610
  if( 0 < $( '.invalid[type="text"]' ).length ) {
611
    // Les boutons sont signalés en rouge
612
    $( '#preview-field , #validate-new-fields' ).addClass( 'invalid' );
613
    // Un message d'alerte apparait avant les boutons
614
    if( 0 === $( '#new-fields' ).next( '.validation-warning' ).length ) {
615
      $( '#new-fields' ).after(
616
        '<p class="validation-warning message">' +
617
          '<i class="fa fa-exclamation-triangle" aria-hidden="true" style="color:#ff5d55"></i>' +
618
           '&nbsp;Des informations sont manquantes pour certains champs,' +
619
           ' vérifiez ceux signalés en rouge' +
620
        '</p>'
621
      );
622
    }
623
  } else {
624
    // Les signalements et messages sont supprimés
625
    $( '#preview-field , #validate-new-fields' ).removeClass( 'invalid' );
626
    $( '#new-fields' ).next( '.validation-warning' ).hide( 200 , function () {
627
        $( this ).remove();
628
    });
629
  }
3174 idir 630
}
3168 idir 631
 
3189 idir 632
/**** Envoi des nouveaux champs ****/
633
 
3174 idir 634
// Enregistrement des valeurs à transmettre
635
function onClickStoreNewFields() {
636
  // Lorsqu'on valide
637
  var resultArrayIndex = 0;
3226 idir 638
  var count = $( 'fieldset' ).last().data( 'id' );
3174 idir 639
  var helpFileExists = false;
640
  // Savoir si au moins un fichier "aide" est enregistré
641
  $( '.field-help' ).each( function () {
642
    if( '' !== $( this ).val() ){
643
      helpFileExists = true;
644
    }
645
  })
646
  // dans ce cas intégrer dans le formulaire à soumettre un bloc
647
  // qui contiendra une copie de chacun de ces input[type="file"]
648
  if( helpFileExists ){
3226 idir 649
    $( '#submit-button' ).before( '<div id="help-doc-submit" style="position:fixed;visibility:hidden;"></div>' );
3174 idir 650
  }
651
  // On déroule les blocs de champs supplémentaires
3226 idir 652
  for( var index = $( 'fieldset' ).first().data( 'id' ) ; index <= count ; index++ ) {
3174 idir 653
    var thisFieldset = $( 'fieldset[data-id="' + index + '"]');
654
    // Certains indices peuvent correspondre à un champ supprimé
655
    if( 0 < $( thisFieldset ).length ) {
656
      // initialisation du tableau de résultats
3185 idir 657
      datasToSubmit[ resultArrayIndex ]             = { fieldValues:{} };
3174 idir 658
      // Ajout de la clé au tableau de resultats
3185 idir 659
      datasToSubmit[ resultArrayIndex ].key         = $( '.field-key' , thisFieldset ).val();
3174 idir 660
      // Ajout de le nom au tableau de resultats
3185 idir 661
      datasToSubmit[ resultArrayIndex ].name        = $( '.field-name' , thisFieldset ).val();
3174 idir 662
      // Recueil de l'élément choisi pour le tableau de resultats
3185 idir 663
      datasToSubmit[ resultArrayIndex ].element     = $( '.field-element' , thisFieldset ).val();
3174 idir 664
      // Ajout de la valeur 'requis' ou non au tableau de resultats
3185 idir 665
      datasToSubmit[ resultArrayIndex ].mandatory   = $( '.field-is_mandatory' , thisFieldset ).is( ':checked' );
3174 idir 666
      // Ajout de l'unité au tableau de resultats
3185 idir 667
      datasToSubmit[ resultArrayIndex ].unit        = $( '.field-unit' , thisFieldset ).val() || null;
3174 idir 668
      // Ajout du tooltip au tableau de resultats
3176 idir 669
      datasToSubmit[ resultArrayIndex ].description = $( '.field-description' , thisFieldset ).val() || null;
3174 idir 670
      // Collecte les des données dépendantes de l'élément choisi
671
      // sous forme d'un tableau de resultats
672
      onSelectCollectDataValuesToSubmit( datasToSubmit[ resultArrayIndex ] , thisFieldset );
3226 idir 673
 
674
      if( $.isEmptyObject( datasToSubmit[ resultArrayIndex ].fieldValues ) ){
3174 idir 675
        delete datasToSubmit[ resultArrayIndex ].fieldValues;
676
      }
677
      // Copie d'un champ de fichier d'aide dans le bloc d'envoi
3233 idir 678
      if( 0 < $( '.field-help' , thisFieldset ).get(0).files.length ) {
679
        // Présence d'un document d'aide
680
        datasToSubmit[ resultArrayIndex ].help = $( '.field-help' , thisFieldset ).get(0).files[0].type;
3174 idir 681
        $( '.field-help' , thisFieldset ).clone()
3226 idir 682
          .attr( 'name' , 'help-' + datasToSubmit[ resultArrayIndex ].key )// l'attribut name prend la valeur de la clé
3174 idir 683
          .appendTo( '#help-doc-submit' );
3233 idir 684
      } else {
685
        datasToSubmit[ resultArrayIndex ].help = null;
3174 idir 686
      }
687
      resultArrayIndex++;
3171 idir 688
    }
3174 idir 689
  }
3233 idir 690
 
691
  var resultsArrayJson = JSON.stringify( datasToSubmit , replacer );
692
 
693
  // JSON.strigify : Gestion des apostrophes dans les valeurs :
694
  function replacer( key , value ) {
695
    if ( 'fieldValues' === key && 'object' === typeof value ) {
696
      for ( var i in value ) {
697
        if ( typeof value[i] === 'string' ) {
3235 idir 698
          // value[i] = value[i].replace( /\u0027/g, "&apos;&apos;" );
699
          // La solution ci-dessus convient pour stockage dans la base mais pas pour la lecture dans saisie
700
          // du coup astuce moisie:
701
          value[i] = value[i].replace( /\u0027/g, "@apos@" ).replace( /\u0022/g, '@quot@' )
3233 idir 702
        }
703
      }
704
    } else if ( typeof value === 'string' ) {
3235 idir 705
      // value = value.replace( /\u0027/g, "&apos;&apos;" );
706
      // La solution ci-dessus convient pour stockage dans la base mais pas pour la lecture dans saisie
707
      // du coup astuce moisie:
708
      value = value.replace( /\u0027/g, "@apos@" ).replace( /\u0022/g, '@quot@' )
3233 idir 709
    }
710
    return value;
711
  }
712
 
713
  console.log( resultsArrayJson );
714
 
3174 idir 715
  // Désactivation de tous les champs et boutons (nouveaux champs)
716
  $( '#new-fields, #new-fields .button , #add-fields , #preview-field' ).addClass( 'disabled' );
717
  $( '#validate-new-fields' ).addClass( 'validated' );
718
  $( '.validate-new-fields' ).text( 'Champs validés' );
719
  // Mise à disposition des données pour le bouron submit
3226 idir 720
  $( '#submit-button' ).before(
3233 idir 721
    //la value est passée avec des apostrophes pour que les guillemets de la string json passent bien en string de l'attribut
722
    '<input type="hidden" name="champs-supp" id="champs-supp" value=\'' + resultsArrayJson + '\'>'
3174 idir 723
  );
3171 idir 724
}
725
 
726
// Renseigne le tableau de resultat
727
// pour les données dépendant de l'élément choisi
3174 idir 728
function onSelectCollectDataValuesToSubmit( datasToSubmitObject , thisFieldset ) {
3171 idir 729
    switch( datasToSubmitObject.element ) {
730
      case 'select':
731
      case 'checkbox':
732
      case 'list-checkbox':
733
      case 'radio':
3173 idir 734
        datasToSubmitObject.fieldValues.listValue = [];
3171 idir 735
        // Ajout des valeurs de liste
3174 idir 736
        onChangeStoreListValueLabel( datasToSubmitObject , thisFieldset );
3171 idir 737
        // S'il y a une valeur 'autre' on l'indique à la fin de la liste
3233 idir 738
        if( $( '.option-other-value' , thisFieldset ).is( ':checked' ) && -1 === datasToSubmitObject.fieldValues.listValue.indexOf( 'other' ) ) {
3171 idir 739
          datasToSubmitObject.fieldValues.listValue.push( 'other' );
740
        }
741
        break;
742
 
743
      case 'number':
744
      case 'range':
745
        // Placeholder
3176 idir 746
        datasToSubmitObject.fieldValues.placeholder = $( '.aide-saisie' , thisFieldset ).val() || null;
3171 idir 747
        // Valeur par défaut
3176 idir 748
        datasToSubmitObject.fieldValues.default = $( '.default' , thisFieldset ).val() || null;
3171 idir 749
        // Incrémentation ( attribut step="" )
3176 idir 750
         datasToSubmitObject.fieldValues.step = $( '.step' , thisFieldset ).val() || null;
3171 idir 751
        // Min
3176 idir 752
        datasToSubmitObject.fieldValues.min = $( '.min' , thisFieldset ).val() || null;
3171 idir 753
        // Max
3176 idir 754
        datasToSubmitObject.fieldValues.max = $( '.max' , thisFieldset ).val() || null;
3171 idir 755
        break;
756
 
757
      case 'date':
758
        // Min
3176 idir 759
        datasToSubmitObject.fieldValues.min = $( '.min' , thisFieldset ).val() || null;
3171 idir 760
        // Max
3176 idir 761
        datasToSubmitObject.fieldValues.max = $( '.max' , thisFieldset ).val() || null;
3171 idir 762
        break;
763
 
764
      case 'email':
765
      case 'text':
766
      case 'textarea':
767
      default:
768
        // Placeholder
3176 idir 769
        datasToSubmitObject.fieldValues.placeholder = $( '.aide-saisie' , thisFieldset ).val() || null;
3171 idir 770
        break;
771
    }
3173 idir 772
    return datasToSubmitObject;
3171 idir 773
}
774
 
775
// Ajout d'une valeur d'un élément liste (select, checkbox etc.)
776
// dans le tableau de resultats
3174 idir 777
function onChangeStoreListValueLabel( datasToSubmitObject , thisFieldset ) {
778
  $( '.list-value' , thisFieldset ).each( function() {
3346 idir 779
    var valueId = $( this ).data( 'list-value-id' );
3174 idir 780
    var selectedFieldElement = $( '.field-element' , thisFieldset ).val();
3346 idir 781
    var displayedLabel = '';
3176 idir 782
 
3346 idir 783
    if ( valeurOk( $( '.displayed-label[data-list-value-id="' + valueId + '"]' ).val() ) ) {
784
      displayedLabel = $( '.displayed-label[data-list-value-id="' + valueId + '"]' ).val();
785
    }
786
    if( $( this ).val() ){
3176 idir 787
      // Is-default-value non cochée
3346 idir 788
      if( !$( '.is-defaut-value[data-list-value-id="' + valueId + '"]' , thisFieldset ).is( ':checked' ) ) {
789
        datasToSubmitObject.fieldValues.listValue.push( [ $( this ).val(), displayedLabel ] );
3176 idir 790
      // Is-default-value cochée pour select/radio
3174 idir 791
      } else if( 'select' ===  selectedFieldElement || 'radio' === selectedFieldElement ) {
3176 idir 792
        // Une seule valeur par defaut, devient la première valeur du tableau + '#'
3346 idir 793
        datasToSubmitObject.fieldValues.listValue.unshift( [ $( this ).val() + '#', displayedLabel ] );
3176 idir 794
      // Is-default-value cochée pour checkbox/list-checkbox
3171 idir 795
      } else {
3176 idir 796
        // On ajoute simplement la valeur au tableau + '#'
3346 idir 797
        datasToSubmitObject.fieldValues.listValue.push( [ $( this ).val() + '#', displayedLabel ] );
3171 idir 798
      }
799
    }
800
  });
801
}
802
 
3174 idir 803
/************************************************
804
 *  Fonction d'affichage des champs classiques  *
805
 ************************************************/
3171 idir 806
 
3176 idir 807
// Prévisualisation
3174 idir 808
function DisplayClassicFields() {
809
  // Affichage du titre du widget
3226 idir 810
  renderFields( $( '#titre' ) , $( '.widget-renderer h1' ) );
3174 idir 811
  // Affichage de la description
3226 idir 812
  renderFields( $( '#description' ) , $( '.preview-description' ) );
3241 idir 813
  // Affichage referentiel
814
  $( '#label-taxon span' ).text( ' (' + $( '#referentiel' ).val() + ')' );
815
  $( '#referentiel' ).change( function() {
816
    $( '#label-taxon span' ).text( ' (' + $( this ).val() + ')' );
817
  });
818
 
3174 idir 819
  // Affichage du logo s'il existe déjà
3226 idir 820
  if( 0 !== $( '#logo' ).val().length || $( '#logo' )[0].defaultValue ) {
3189 idir 821
    $( '#preview-logo' ).append(
822
      '<img src="' +
3226 idir 823
        $( '#group-settings-form .logo img' ).prop( 'src' ) +
3189 idir 824
        '" width="75%"' +
825
      '>'
826
    );
3174 idir 827
  }
828
  // Affichage du logo chargé
829
  $( '#logo.input-file' ).change( function( event ) {
3189 idir 830
    // Si le 'change' n'était pas une suppression
3176 idir 831
    if( $.isEmptyObject( event.target.files[0] ) ) {
3190 idir 832
      $( '#preview-logo img' ).remove();
3176 idir 833
    // Si on a chargé un logo ou changé le fichier
834
    } else {
3189 idir 835
      $( '#preview-logo' ).append(
836
        '<img src="' +
837
          URL.createObjectURL( event.target.files[0] ) +
838
          '" width="75%"' +
839
        '>'
840
      );
3167 idir 841
    }
842
  });
3174 idir 843
  // Affichage de l'image de fond
3235 idir 844
  $('#image_fond.input-file').change( function ( event ) {
3174 idir 845
    if( !$.isEmptyObject( event.target.files[0] ) ) {
3241 idir 846
      $( '.widget-renderer' ).css('background' ,'url(' + URL.createObjectURL( event.target.files[0] ) + ') no-repeat fixed center center');
3174 idir 847
    } else {
848
      $( '.widget-renderer' )[0].style.removeProperty( 'background' );
849
    }
850
  });
851
}
3167 idir 852
 
3176 idir 853
// Affichage des infos dès que disponibles
854
// pour les champs classiques
855
function renderFields( $source , $taget ) {
3378 idir 856
  var text = new DOMParser().parseFromString($source.val(), 'text/html');
857
 
858
  text = text.body.textContent || '';
3226 idir 859
  if( $source.val() ) {
3378 idir 860
    $taget.text( text );
3176 idir 861
  }
862
  $source.change( function () {
3378 idir 863
    $taget.text( text );
3176 idir 864
  });
865
}
3174 idir 866
 
867
 
3176 idir 868
/*****************************************************
869
 *  Fonction d'affichage des champs supplémentaires  *
870
 *****************************************************/
871
 
3174 idir 872
// Construction des éléments à visualiser
873
function onClickPreviewField( thisFieldset , index ) {
3176 idir 874
  // Récupération des données
875
      // Tous les champs
3185 idir 876
  var fieldLabel       = $( '.field-name'            , thisFieldset ).val() || '',//nom
877
      fieldKey         = $( '.field-key'             , thisFieldset ).val() || '',//clé
878
      fieldElement     = $( '.field-element'         , thisFieldset ).val() || '',//élément
3176 idir 879
      fieldIsMandatory = $( '.field-is_mandatory'    , thisFieldset ).is( ':checked' ),//champ requis
3185 idir 880
      fieldUnit        = $( '.field-unit'            , thisFieldset ).val() || '',//unités
881
      fieldTooltip     = $( '.field-description'     , thisFieldset ).val() || '',//info-bulle
882
      fieldHelp        = $( '.file-return.help-doc-' + index ).text()       || '',//nom du fichier d'aide
3176 idir 883
      fieldPlaceholder = $( '.aide-saisie'           , thisFieldset ).val() || '',//placeholder
884
      // Champs à valeur numérique ou date
3185 idir 885
      fieldStep        = $( '.step'                  , thisFieldset ).val() || '',
886
      fieldMin         = $( '.min'                   , thisFieldset ).val() || '',
887
      fieldMax         = $( '.max'                   , thisFieldset ).val() || '',
3176 idir 888
      // Champs "listes"
3185 idir 889
      fieldDefaultNum  = $( '.default'               , thisFieldset ).val() || '',// value range/number par default
3176 idir 890
      fieldOtherValue  = $( '.option-other-value'    , thisFieldset ).is( ':checked' ),//option autre
891
      fieldOptions     = collectListOptions( thisFieldset );//Array: toutes les options
892
  // Variables d'affichage
3346 idir 893
  var fieldHtml        = '',//variable contenant tout le html à afficher
894
      commonFieldsHtml = {},//Éléments simples ou chaînes communes aux "listes"
895
      listFieldsHtml   = {},//chaînes & html pour les listes mais non spécifiques
896
      listFieldsHtml   = {},//chaînes & html spécifiques aux listes
897
      count            = fieldOptions.length;//nombre d'options, pour les boucles for
3255 idir 898
  fieldLabel = fieldLabel.replace( /(')/gm, '&apos;' ).replace( /(")/gm, '&quot;' );
899
  fieldTooltip = fieldTooltip.replace( /(')/gm, '&apos;' ).replace( /(")/gm, '&quot;' );
900
  fieldPlaceholder = fieldPlaceholder.replace( /(')/gm, '&apos;' ).replace( /(")/gm, '&quot;' );
3233 idir 901
 
3176 idir 902
  //valeurs initiales des chaînes de caractères
903
  //Éléments simples ou chaînes communes aux "listes"
904
  commonFieldsHtml = {
905
    dataIdAttr : ' data-id="' + index + '"',
906
    helpButton : '',//bouton aide
907
    helpClass  : '',//classe de l'élément associé au bouton aide
908
    titleAttr  : '',//info-bulle
909
    fieldInput : {//attributs de l'élément
910
      typeAttr        : ' type="' + fieldElement + '"',
911
      nameAttr        : ' name="' + fieldKey + '"',
912
      classAttr       : ' class="' +  fieldKey + '"',
913
      placeholderAttr : '',
914
      mandatoryAttr   : '',//required
915
      otherAttr       : ''
3174 idir 916
    },
3176 idir 917
    fieldLabel : {//attributs et contenu du label
918
      labelContent    : fieldLabel,//label
919
      forAttr         : ' for="' + fieldKey + '"',//attribut for
920
      classAttr       : '',//classe du label
921
      otherAttr       : ''//tous autres attributs
3174 idir 922
    }
923
  }
924
  // Pour les éléments de listes (select, checkbox, etc.)
3176 idir 925
  listFieldsHtml = {
926
    containerContent : fieldLabel,//les options peuvent avoir chacune un label
927
    containerClass   : '',//une classe pour le conteneur
928
    forAttr          : '',//correspond à l'id d'une checkbox/radio/list-checkbox
929
    optionIdAttr     : '',//value-id
930
    defaultAttr      : ''//default
3174 idir 931
  };
932
  // Changement d'un élément existant:
933
  // supprimer le précédent pour ajouter le nouveau
934
  if( 0 < $( '.preview-fields' , thisFieldset ).length ) {
935
    $( '.preview-fields' , thisFieldset ).remove();
936
  }
3176 idir 937
  // Élément requis
3174 idir 938
  if( fieldIsMandatory ) {
3176 idir 939
    // Attribut required pour le listes
940
    commonFieldsHtml.fieldInput.mandatoryAttr = ' required="required"';
3174 idir 941
    // Nom du champ (éléments listes)
3241 idir 942
    listFieldsHtml.containerContent = '* ' + listFieldsHtml.containerContent;
3174 idir 943
    // Nom du champ (éléments simples)
3241 idir 944
    commonFieldsHtml.fieldLabel.labelContent = '* ' + commonFieldsHtml.fieldLabel.labelContent;
3174 idir 945
  }
3176 idir 946
  // Infobulle
3174 idir 947
  if( '' !== fieldTooltip ) {
3176 idir 948
    commonFieldsHtml.titleAttr = ' title="' +  fieldTooltip + '"';
3174 idir 949
  }
3176 idir 950
  // Placeholder
3174 idir 951
  if( '' !== fieldPlaceholder ) {
3176 idir 952
    commonFieldsHtml.fieldInput.placeholderAttr = ' placeholder="' +  fieldPlaceholder + '"';
3174 idir 953
  }
3176 idir 954
  // Fichier d'aide
3174 idir 955
  if( '' !== fieldHelp ) {
3176 idir 956
    // Bouton 'aide'
3241 idir 957
    commonFieldsHtml.helpButton = '<div class="help-button btn btn-outline-info btn-sm border-0"><i class="fas fa-info-circle"></i></div>';
3176 idir 958
    // classe 'aide'
959
    commonFieldsHtml.helpClass = ' and-help';
3174 idir 960
  }
961
  // html à ajouter en fonction de l'élément choisi
962
  switch( fieldElement ) {
963
    case 'checkbox' :
964
    case 'radio' :
3176 idir 965
      listFieldsHtml.containerClass = ' class="' + fieldElement +'"';
3241 idir 966
      commonFieldsHtml.fieldLabel.classAttr = ' class="radio-label"';
3174 idir 967
      fieldHtml =
968
        // Conteneur
3244 idir 969
        '<div style="width:100%"' +
3174 idir 970
          // Class="L'élément choisi"
3176 idir 971
          listFieldsHtml.containerClass +
3174 idir 972
          // DataId
3176 idir 973
          commonFieldsHtml.dataIdAttr +
3174 idir 974
          // Required
3176 idir 975
          commonFieldsHtml.fieldInput.mandatoryAttr +
3174 idir 976
          // Info bulle
3176 idir 977
          commonFieldsHtml.titleAttr +
3174 idir 978
        ' >'+
979
          // Nom du champ
3176 idir 980
          // Classe 'and-help'
3241 idir 981
          '<div class="mt-3 list-label' + commonFieldsHtml.helpClass + '">' +
3176 idir 982
            // Label
983
            listFieldsHtml.containerContent +
3241 idir 984
            // Bouton 'help'
985
            commonFieldsHtml.helpButton +
986
          '</div>';
3174 idir 987
      // On déroule les différentes valeurs
3176 idir 988
      for( let i = 0; i < count; i++ ) {
3174 idir 989
        let fieldOption = fieldOptions[i];
3176 idir 990
        // L'id de input
991
        listFieldsHtml.inputIdAttr = ' id="' + fieldOption.optionValue + '"';
992
        listFieldsHtml.forAttr = ' for="' + fieldOption.optionValue + '"';
993
        // Default
994
        listFieldsHtml.defaultAttr = '';//réinitialisation
995
        if( fieldOption.isDefault ) {//affectation
996
          listFieldsHtml.defaultAttr = ' checked';
3174 idir 997
        }
998
        // L'indice de chaque option
999
        // L'option "autre" n'en a pas
1000
        if( '' !== fieldOption.optionIndex ) {
3176 idir 1001
          listFieldsHtml.optionIdAttr = ' value-id="' + fieldOption.optionIndex + '"';
3174 idir 1002
        }
1003
 
1004
        fieldHtml +=
1005
          '<label' +
1006
            // For
3176 idir 1007
            listFieldsHtml.forAttr +
3174 idir 1008
            // value-id
3176 idir 1009
            listFieldsHtml.optionIdAttr +
3241 idir 1010
            // Class du label
1011
            commonFieldsHtml.fieldLabel.classAttr +
3174 idir 1012
          '>' +
1013
            '<input' +
1014
              // Type
3176 idir 1015
              commonFieldsHtml.fieldInput.typeAttr +
1016
              // Id
1017
              listFieldsHtml.inputIdAttr +
3174 idir 1018
              // DataId
3176 idir 1019
              commonFieldsHtml.dataIdAttr +
3174 idir 1020
              // value-id
3176 idir 1021
              listFieldsHtml.optionIdAttr +
3174 idir 1022
              // Name
3176 idir 1023
              commonFieldsHtml.fieldInput.nameAttr +
3174 idir 1024
              // Value
3255 idir 1025
              ' value="' + fieldOption.optionValue.replace( /(')/gm, '&apos;' ).replace( /(")/gm, '&quot;' ) + '"' +
3174 idir 1026
              // Checked
3176 idir 1027
              listFieldsHtml.defaultAttr +
3174 idir 1028
              // Class="nom du champ"
3176 idir 1029
              commonFieldsHtml.fieldInput.classAttr +
3174 idir 1030
            '>' +
1031
            // Label de l'option
3255 idir 1032
            fieldOption.optionText.replace( /(')/gm, '&apos;' ).replace( /(")/gm, '&quot;' ) +
3174 idir 1033
          '</label>';
3187 idir 1034
      }
1035
      // Si valeur "autre" est cochée
1036
      if( fieldOtherValue ) {
1037
        fieldHtml +=
1038
          '<label for="other"' +
1039
            commonFieldsHtml.dataIdAttr +
3241 idir 1040
            commonFieldsHtml.fieldLabel.classAttr +
3187 idir 1041
          '>' +
1042
            '<input' +
1043
              commonFieldsHtml.fieldInput.typeAttr +
3241 idir 1044
              ' id="other-' + fieldElement + '-' + index + '"' +
3187 idir 1045
              commonFieldsHtml.fieldInput.nameAttr +
1046
              ' value="other"' +
1047
              commonFieldsHtml.fieldInput.classAttr +
3176 idir 1048
              commonFieldsHtml.dataIdAttr +
3174 idir 1049
            '>' +
3187 idir 1050
          'Autre</label>';
3174 idir 1051
        }
1052
      // Fin du conteneur
1053
      fieldHtml += '</div>';
1054
      break;
1055
 
1056
    case 'list-checkbox':
3241 idir 1057
      commonFieldsHtml.fieldLabel.classAttr = ' class="radio-label"';
3174 idir 1058
      fieldHtml =
3176 idir 1059
        // Classe 'and-help'
3241 idir 1060
        '<div class="multiselect  add-field-select' + commonFieldsHtml.helpClass + '"' +
3174 idir 1061
          // DataId
3176 idir 1062
          commonFieldsHtml.dataIdAttr +
3174 idir 1063
        '>' +
3244 idir 1064
          '<label style="width:100%">' +
3174 idir 1065
            // Nom du champ
3176 idir 1066
            listFieldsHtml.containerContent +
3241 idir 1067
            // Bouton 'help'
1068
            commonFieldsHtml.helpButton +
3174 idir 1069
          '</label>' +
3241 idir 1070
          '<div class="mt-3">'+
1071
            '<div class="selectBox"' +
3174 idir 1072
              // DataId
3176 idir 1073
              commonFieldsHtml.dataIdAttr +
3174 idir 1074
            '>' +
3241 idir 1075
              '<select' +
1076
                // DataId
1077
                commonFieldsHtml.dataIdAttr +
1078
                // Required
1079
                commonFieldsHtml.fieldInput.mandatoryAttr +
1080
                // Info bulle
1081
                commonFieldsHtml.titleAttr +
1082
                // Class
3262 idir 1083
                ' class="form-control custom-select ' + fieldElement + '"' +
3241 idir 1084
              '>' +
1085
                // Apparait dans la barre de sélection
1086
                '<option>Plusieurs choix possibles</option>' +
1087
              '</select>' +
1088
              '<div class="overSelect"></div>' +
1089
            '</div>' +
1090
            '<div class="checkboxes hidden"' +
1091
              // DataId
1092
              commonFieldsHtml.dataIdAttr +
1093
            '>';
3174 idir 1094
      // On déroule les différentes valeurs
3176 idir 1095
      for( let i = 0; i < count; i++ ) {
3174 idir 1096
        let fieldOption = fieldOptions[i];
3176 idir 1097
        // Type="checkbox"
1098
        commonFieldsHtml.fieldInput.typeAttr = ' type="checkbox"';
1099
        // Id
3255 idir 1100
        listFieldsHtml.inputIdAttr = ' id="' + fieldOption.optionValue.replace( /(')/gm, '&apos;' ).replace( /(")/gm, '&quot;' ).toLowerCase() + '"';
3176 idir 1101
        // For
3255 idir 1102
        listFieldsHtml.forAttr = ' for="' + fieldOption.optionValue.replace( /(')/gm, '&apos;' ).replace( /(")/gm, '&quot;' ).toLowerCase() + '"';
3176 idir 1103
        // Default
1104
        listFieldsHtml.defaultAttr = '';//réinitialisation
3174 idir 1105
        if( fieldOption.isDefault ) {
3176 idir 1106
          listFieldsHtml.defaultAttr = ' checked';//affectation
3174 idir 1107
        }
3176 idir 1108
        // value-id
3174 idir 1109
        if( '' !== fieldOption.optionIndex ) {
3176 idir 1110
          listFieldsHtml.optionIdAttr = ' value-id="' + fieldOption.optionIndex + '"';
3174 idir 1111
        }
1112
 
1113
        fieldHtml +=
1114
          '<label' +
3176 idir 1115
            // For
1116
            listFieldsHtml.forAttr +
3174 idir 1117
            // value-id
3176 idir 1118
            listFieldsHtml.optionIdAttr +
3241 idir 1119
            // Class du label
1120
            commonFieldsHtml.fieldLabel.classAttr+
3174 idir 1121
          '>' +
1122
            '<input type="checkbox"' +
3176 idir 1123
              // Id
1124
              listFieldsHtml.inputIdAttr +
3174 idir 1125
              // value-id
3176 idir 1126
              listFieldsHtml.optionIdAttr +
3174 idir 1127
              // Name
3176 idir 1128
              commonFieldsHtml.fieldInput.nameAttr +
3174 idir 1129
              // Value
3255 idir 1130
              ' value="' + fieldOption.optionValue.replace( /(')/gm, '&apos;' ).replace( /(")/gm, '&quot;' ) + '"' +
3174 idir 1131
              // Checked
3176 idir 1132
              listFieldsHtml.defaultAttr +
3174 idir 1133
              // Class="nom du champ"
3176 idir 1134
              commonFieldsHtml.fieldInput.classAttr +
3174 idir 1135
              // DataId
3176 idir 1136
              commonFieldsHtml.dataIdAttr +
3174 idir 1137
            '>' +
1138
            // Label de l'option
3255 idir 1139
            fieldOption.optionText.replace( /(')/gm, '&apos;' ).replace( /(")/gm, '&quot;' ) +
3174 idir 1140
          '</label>';
1141
      }
1142
      // Si valeur "autre" est cochée
1143
      if( fieldOtherValue ) {
1144
        fieldHtml +=
1145
          '<label for="other"' +
1146
            // DataId
3176 idir 1147
            commonFieldsHtml.dataIdAttr +
3174 idir 1148
          '>' +
1149
            '<input type="checkbox"' +
3241 idir 1150
              ' id="other-' + fieldElement + '-' + index + '"' +
3176 idir 1151
              commonFieldsHtml.fieldInput.nameAttr +
3174 idir 1152
              ' value="other"' +
3176 idir 1153
              commonFieldsHtml.fieldInput.classAttr +
3174 idir 1154
              // DataId
3176 idir 1155
              commonFieldsHtml.dataIdAttr +
3174 idir 1156
            '>' +
1157
          'Autre</label>';
1158
      }
1159
      // Fermeture des conteneurs .multiselect .checkboxes
1160
      fieldHtml +=
3241 idir 1161
            '</div>'+
1162
          '</div>'+
1163
        '</div>';
3174 idir 1164
      break;
1165
 
1166
    case 'select':
3241 idir 1167
      commonFieldsHtml.fieldInput.classAttr = commonFieldsHtml.fieldInput.classAttr.slice(0, -1);
3262 idir 1168
      commonFieldsHtml.fieldInput.classAttr += ' form-control custom-select"';
3174 idir 1169
      fieldHtml =
1170
        // Conteneur/Wrapper
3176 idir 1171
        // +Classe 'and-help'
3241 idir 1172
        '<div class="add-field-select ' + fieldElement + commonFieldsHtml.helpClass + '"' +
3176 idir 1173
          // DataID
1174
          commonFieldsHtml.dataIdAttr +
3174 idir 1175
        '>' +
3244 idir 1176
          '<label class="mt-3" style="width:100%"' +
3241 idir 1177
            commonFieldsHtml.fieldLabel.forAttr +
1178
            // Info bulle
1179
            commonFieldsHtml.titleAttr +
1180
          '>' +
1181
            // Nom du champ
1182
            listFieldsHtml.containerContent +
1183
            // Bouton 'help'
1184
            commonFieldsHtml.helpButton +
1185
          '</label>' +
3174 idir 1186
          '<select' +
3176 idir 1187
            commonFieldsHtml.fieldInput.nameAttr +
3174 idir 1188
            ' id="' + fieldKey + '"' +
3176 idir 1189
            // Class
1190
            commonFieldsHtml.fieldInput.classAttr +
3174 idir 1191
            // Required
3176 idir 1192
            commonFieldsHtml.fieldInput.mandatoryAttr +
3174 idir 1193
            // DataId
3176 idir 1194
            commonFieldsHtml.dataIdAttr +
3174 idir 1195
          '>';
1196
 
1197
      // On déroule les différentes valeurs
3176 idir 1198
      for( let i = 0; i < count; i++ ) {
3174 idir 1199
        let fieldOption = fieldOptions[i];
3176 idir 1200
        // Default
1201
        listFieldsHtml.defaultAttr = '';//réinitialisation
1202
        if( fieldOption.isDefault ) {//affectation
1203
          listFieldsHtml.defaultAttr = ' selected="selected"';
3174 idir 1204
        }
3176 idir 1205
        // value-id
3174 idir 1206
        if( '' !== fieldOption.optionIndex ) {
3176 idir 1207
          listFieldsHtml.optionIdAttr = ' value-id="' + fieldOption.optionIndex + '"';
3174 idir 1208
        }
1209
 
1210
        fieldHtml +=
1211
          '<option' +
1212
            // Value
3255 idir 1213
            ' value="' + fieldOption.optionValue.replace( /(')/gm, '&apos;' ).replace( /(")/gm, '&quot;' ) + '"' +
3174 idir 1214
            // Value-id
3176 idir 1215
            listFieldsHtml.optionIdAttr +
3174 idir 1216
            // Selected
3176 idir 1217
            listFieldsHtml.defaultAttr +
3174 idir 1218
          '>' +
1219
            // Option
3255 idir 1220
            fieldOption.optionText.replace( /(')/gm, '&apos;' ).replace( /(")/gm, '&quot;' ) +
3174 idir 1221
          '</option>';
1222
      }
1223
      // Si valeur "autre" est cochée
1224
      if( fieldOtherValue ) {
1225
        fieldHtml +=
3176 idir 1226
          '<option class="other" value="other"' + commonFieldsHtml.dataIdAttr + '>' +
3174 idir 1227
            'Autre' +
1228
          '</option>';
1229
      }
3176 idir 1230
      // Fermeture des conteneurs
3174 idir 1231
      fieldHtml +=
1232
          '</select>' +
1233
        // Fin du conteneur/wrapper
3241 idir 1234
        '</div>';
3174 idir 1235
      break;
1236
 
1237
    case 'textarea':
3241 idir 1238
    // Ouvrir l'attribut class (suppression de '"')
1239
      commonFieldsHtml.fieldInput.classAttr = commonFieldsHtml.fieldInput.classAttr.slice(0, -1);
1240
      // Classe 'custom-range'
1241
      commonFieldsHtml.fieldInput.classAttr += ' form-control"';
3176 idir 1242
      // Classe 'and-help'
3241 idir 1243
      commonFieldsHtml.fieldLabel.classAttr = ' class="mt-3 ' + commonFieldsHtml.helpClass + '"';
3174 idir 1244
      // Autres attributs
3176 idir 1245
      commonFieldsHtml.fieldInput.otherAttr += ' id="' + fieldKey + '"';
3174 idir 1246
 
1247
      fieldHtml =
3244 idir 1248
        '<label  style="width:100%"' +
3174 idir 1249
          // For
3176 idir 1250
          commonFieldsHtml.fieldLabel.forAttr +
3174 idir 1251
          // Class
3176 idir 1252
          commonFieldsHtml.fieldLabel.classAttr +
3174 idir 1253
          // Info-bulle
3176 idir 1254
          commonFieldsHtml.titleAttr +
3174 idir 1255
          // Autres attributs
3176 idir 1256
          commonFieldsHtml.fieldLabel.otherAttr +
3174 idir 1257
        '>' +
1258
          // Nom du champ
3176 idir 1259
          commonFieldsHtml.fieldLabel.labelContent +
3241 idir 1260
          // Bouton 'help'
1261
          commonFieldsHtml.helpButton +
3174 idir 1262
        '</label>' +
1263
        '<textarea' +
1264
          // Name
3176 idir 1265
          commonFieldsHtml.fieldInput.nameAttr +
3174 idir 1266
          // DataId
3176 idir 1267
          commonFieldsHtml.dataIdAttr +
3174 idir 1268
          // Class
3176 idir 1269
          commonFieldsHtml.fieldInput.classAttr +
3174 idir 1270
          // Info-bulle
3176 idir 1271
          commonFieldsHtml.titleAttr +
3174 idir 1272
          // Info-bulle
3176 idir 1273
          commonFieldsHtml.fieldInput.placeholderAttr +
1274
          // Required
1275
          commonFieldsHtml.fieldInput.mandatoryAttr +
3174 idir 1276
          // Autres attributs
3176 idir 1277
          commonFieldsHtml.fieldInput.otherAttr +
3174 idir 1278
        '></textarea>';
1279
        break;
1280
 
1281
    case 'range':
3241 idir 1282
      // Ouvrir l'attribut class (suppression de '"')
1283
      commonFieldsHtml.fieldInput.classAttr = commonFieldsHtml.fieldInput.classAttr.slice(0, -1);
1284
      // Classe 'custom-range'
1285
      commonFieldsHtml.fieldInput.classAttr += ' custom-range form-control pl-3"';
3176 idir 1286
      // Classe 'and-help'
3241 idir 1287
      commonFieldsHtml.fieldLabel.classAttr = ' class="mt-3 ' + commonFieldsHtml.helpClass + '"';
3176 idir 1288
      // Step
3174 idir 1289
      if( '' !== fieldStep ) {
3176 idir 1290
        commonFieldsHtml.fieldInput.otherAttr += ' step="' +  fieldStep + '"';
3174 idir 1291
      }
3176 idir 1292
      // Min
3174 idir 1293
      if( '' !== fieldMin ) {
3176 idir 1294
        commonFieldsHtml.fieldInput.otherAttr += ' min="' +  fieldMin + '"';
3174 idir 1295
      }
3176 idir 1296
      //Max
3174 idir 1297
      if( '' !== fieldMax ) {
3176 idir 1298
        commonFieldsHtml.fieldInput.otherAttr += ' max="' +  fieldMax + '"';
3174 idir 1299
      }
1300
      fieldHtml =
3185 idir 1301
        '<div' +
1302
          ' class="range"' +
1303
          ' id="' + fieldKey + '"' +
1304
        '>' +
3244 idir 1305
          '<label style="width:100%"' +
3174 idir 1306
            // For
3176 idir 1307
            commonFieldsHtml.fieldLabel.forAttr +
3174 idir 1308
            // Class
3176 idir 1309
            commonFieldsHtml.fieldLabel.classAttr +
3174 idir 1310
            // Info-bulle
3176 idir 1311
            commonFieldsHtml.titleAttr +
3174 idir 1312
            // Autres attributs
3176 idir 1313
            commonFieldsHtml.fieldLabel.otherAttr +
3174 idir 1314
          '>' +
1315
            // Nom du champ
3176 idir 1316
            commonFieldsHtml.fieldLabel.labelContent +
3241 idir 1317
            // Bouton 'help'
1318
            commonFieldsHtml.helpButton +
3174 idir 1319
          '</label>' +
3241 idir 1320
          '<div class="col-sm-12 row" style="max-width=100%">' +
1321
          // Visualiser min max et la valeur de range
1322
            '<p class="col-sm-2 range-values text-center font-weight-bold">'+
1323
              'Min ' + fieldMin +
1324
            '</p>'+
1325
            '<div class="range-live-value range-values text-center font-weight-bold col-sm-7">'+
1326
              fieldDefaultNum +
1327
            '</div>'+
1328
            '<p class="col-sm-2 range-values text-center font-weight-bold">'+
1329
              'Max ' + fieldMax +
1330
            '</p>' +
1331
 
1332
            '<input' +
1333
              // Type
1334
              commonFieldsHtml.fieldInput.typeAttr +
1335
              // Name
1336
              commonFieldsHtml.fieldInput.nameAttr +
1337
              // DataId
1338
              commonFieldsHtml.dataIdAttr +
1339
              // Class
1340
              commonFieldsHtml.fieldInput.classAttr +
1341
              // Info-bulle
1342
              commonFieldsHtml.titleAttr +
1343
              // Required
1344
              commonFieldsHtml.fieldInput.mandatoryAttr +
1345
              // Default
1346
              ' value="' + fieldDefaultNum + '"' +
1347
              // Autres attributs
1348
              commonFieldsHtml.fieldInput.otherAttr +
1349
            '>' +
1350
          '</div>'
3174 idir 1351
        '</div>';
1352
        break;
1353
 
3185 idir 1354
    case 'number':
1355
      // Step
1356
      if( '' !== fieldStep ) {
1357
        commonFieldsHtml.fieldInput.otherAttr += ' step="' +  fieldStep + '"';
1358
      }
3174 idir 1359
    case 'date':
3176 idir 1360
      // Ouvrir l'attribut class (suppression de '"')
1361
      commonFieldsHtml.fieldInput.classAttr = commonFieldsHtml.fieldInput.classAttr.slice(0, -1);
1362
      // Classe 'and-help'
3241 idir 1363
      commonFieldsHtml.fieldInput.classAttr += commonFieldsHtml.helpClass + ' form-control"';
3176 idir 1364
      // Min
3174 idir 1365
      if( '' !== fieldMin ) {
3176 idir 1366
        commonFieldsHtml.fieldInput.otherAttr += ' min="' +  fieldMin + '"';
3174 idir 1367
      }
3176 idir 1368
      // Max
3174 idir 1369
      if( '' !== fieldMax ) {
3176 idir 1370
        commonFieldsHtml.fieldInput.otherAttr += ' max="' +  fieldMax + '"';
3174 idir 1371
      }
3241 idir 1372
      // Class du label
1373
      commonFieldsHtml.fieldLabel.classAttr = 'class="mt-3"';
3174 idir 1374
      fieldHtml =
1375
        '<div class="number">' +
3244 idir 1376
          '<label style="width:100%"' +
3174 idir 1377
            // For
3176 idir 1378
            commonFieldsHtml.fieldLabel.forAttr +
3174 idir 1379
            // Class
3176 idir 1380
            commonFieldsHtml.fieldLabel.classAttr +
3174 idir 1381
            // Info-bulle
3176 idir 1382
            commonFieldsHtml.titleAttr +
3174 idir 1383
            // Autres attributs
3176 idir 1384
            commonFieldsHtml.fieldLabel.otherAttr +
3174 idir 1385
          '>' +
1386
            // Nom du champ
3176 idir 1387
            commonFieldsHtml.fieldLabel.labelContent +
3241 idir 1388
            // Bouton 'help'
1389
            commonFieldsHtml.helpButton +
3174 idir 1390
          '</label>' +
1391
          '<input' +
1392
            // Type
3176 idir 1393
            commonFieldsHtml.fieldInput.typeAttr +
3174 idir 1394
            // Name
3176 idir 1395
            commonFieldsHtml.fieldInput.nameAttr +
3174 idir 1396
            // DataId
3176 idir 1397
            commonFieldsHtml.dataIdAttr +
3174 idir 1398
            // Class
3176 idir 1399
            commonFieldsHtml.fieldInput.classAttr +
3174 idir 1400
            // Info-bulle
3176 idir 1401
            commonFieldsHtml.titleAttr +
3185 idir 1402
            // Placeholder
3176 idir 1403
            commonFieldsHtml.fieldInput.placeholderAttr +
1404
            // Required
1405
            commonFieldsHtml.fieldInput.mandatoryAttr +
3185 idir 1406
            // Default
1407
            ' value="' + fieldDefaultNum + '"' +
3174 idir 1408
            // Autres attributs
3176 idir 1409
            commonFieldsHtml.fieldInput.otherAttr +
3174 idir 1410
          '>' +
1411
        '</div>';
1412
        break;
1413
 
1414
    case 'text' :
1415
    case 'email':
1416
    default:
3176 idir 1417
      // Ouvrir l'attribut class (suppression de '"')
1418
      commonFieldsHtml.fieldInput.classAttr = commonFieldsHtml.fieldInput.classAttr.slice(0, -1);
1419
      // Classe 'and-help'
3241 idir 1420
      commonFieldsHtml.fieldInput.classAttr += commonFieldsHtml.helpClass + ' form-control"';
1421
      // Class du label
1422
      commonFieldsHtml.fieldLabel.classAttr = 'class="mt-3"';
3174 idir 1423
 
1424
      fieldHtml =
3244 idir 1425
        '<label style="width:100%"' +
3174 idir 1426
          // For
3176 idir 1427
          commonFieldsHtml.fieldLabel.forAttr +
3174 idir 1428
          // Class
3176 idir 1429
          commonFieldsHtml.fieldLabel.classAttr +
3174 idir 1430
          // Info-bulle
3176 idir 1431
          commonFieldsHtml.titleAttr +
3174 idir 1432
          // Autres attributs
3176 idir 1433
          commonFieldsHtml.fieldLabel.otherAttr +
3174 idir 1434
        '>' +
1435
          // Nom du champ
3176 idir 1436
          commonFieldsHtml.fieldLabel.labelContent +
3241 idir 1437
          // Bouton 'help'
1438
          commonFieldsHtml.helpButton +
3174 idir 1439
        '</label>' +
1440
        '<input' +
1441
          // Type
3176 idir 1442
          commonFieldsHtml.fieldInput.typeAttr +
3174 idir 1443
          // Name
3176 idir 1444
          commonFieldsHtml.fieldInput.nameAttr +
3174 idir 1445
          // DataId
3176 idir 1446
          commonFieldsHtml.dataIdAttr +
3174 idir 1447
          // Class
3176 idir 1448
          commonFieldsHtml.fieldInput.classAttr +
3174 idir 1449
          // Info-bulle
3176 idir 1450
          commonFieldsHtml.titleAttr +
3233 idir 1451
          // Placeholder
3176 idir 1452
          commonFieldsHtml.fieldInput.placeholderAttr +
1453
          // Required
1454
          commonFieldsHtml.fieldInput.mandatoryAttr +
3174 idir 1455
          // Autres attributs
3176 idir 1456
          commonFieldsHtml.fieldInput.otherAttr +
3241 idir 1457
        '>';
3174 idir 1458
      break;
1459
  }
1460
  return fieldHtml;
1461
}
1462
 
1463
// Construire un tableau des options pour chaque élément de listes
1464
function collectListOptions( thisFieldset ) {
1465
  var $details = $( '.field-details' , thisFieldset ),
1466
      options = [];
1467
 
1468
  $details.find( '.new-value' ).each( function() {
1469
    options.push({
1470
      // Valeur transmise (value)
3346 idir 1471
      optionValue : $( this ).find( '.list-value' ).val().toLowerCase(),
3174 idir 1472
      // Valeur Visible
3346 idir 1473
      optionText  : $( this ).find( '.displayed-label' ).val(),
3174 idir 1474
      // Booléen "default"
3346 idir 1475
      isDefault   : $( this ).find( '.is-defaut-value' ).is( ':checked' ),
3174 idir 1476
      // Indice de l'option
3346 idir 1477
      optionIndex : $( this ).data( 'list-value-id' )
3174 idir 1478
    });
3167 idir 1479
  });
3174 idir 1480
  return options;
1481
}
3167 idir 1482
 
3174 idir 1483
// Faire apparaitre un champ text "Autre"
1484
function onOtherOption( thisFieldset , index ) {
3176 idir 1485
  // Ce champ (dans la prévisualisation)
1486
  var thisPreviewFieldset = $( '.preview-fields[data-id="' + index + '"]'),
3241 idir 1487
      // L'élément choisi
3176 idir 1488
      element             = $('.field-element' , thisFieldset ).val(),
3174 idir 1489
      // Où insérer le champ "Autre"
3176 idir 1490
      $element            = $( '.' + element , thisPreviewFieldset ),
3174 idir 1491
      // html du champ "Autre"
3176 idir 1492
      collectOther        =
3241 idir 1493
      '<div class="col-sm-12 mt-1 collect-other-block">'+
1494
        '<label data-id="' + index + '" for="collect-other" style="font-weight:300">Autre option :</label>' +
1495
        '<input type="text" name="collect-other" data-id="' + index + '" class="collect-other form-control" >'+
1496
      '</div>';
3174 idir 1497
  // Pouvoir supprimer le champ "Autre"
3176 idir 1498
  function optionRemove( thisPreviewFieldset ) {
3241 idir 1499
    $( '.collect-other-block' , thisPreviewFieldset ).remove();
3174 idir 1500
  }
3167 idir 1501
 
3174 idir 1502
  switch( element ) {
1503
    case 'radio' :
1504
      // Lorsqu'un nouveau bouton est coché
3176 idir 1505
      $( 'input' , thisPreviewFieldset ).on( 'change' , function () {
3174 idir 1506
        if( 'other' === $( this ).val() ) {
1507
          // Insertion du champ "Autre" après les boutons
1508
          $element.after( collectOther );
1509
        } else {
1510
          // Suppression du champ autre
3176 idir 1511
          optionRemove( thisPreviewFieldset );
3174 idir 1512
        }
1513
      });
1514
      break;
1515
 
1516
    case 'select' :
1517
      // Lorsque l'option "Autre" est selectionnée
3176 idir 1518
      $( 'select' , thisPreviewFieldset ).on( 'change' , function () {
3174 idir 1519
        if( 'other' === $( this).val() ) {
1520
          // Insertion du champ "Autre" après les boutons
1521
          $element.after( collectOther );
1522
          // Suppression du champ autre
1523
        } else {
3176 idir 1524
          optionRemove( thisPreviewFieldset );
3174 idir 1525
        }
1526
      });
1527
      break;
1528
 
1529
    case 'list-checkbox' :
1530
      // Lorsque "Autre" est coché
3241 idir 1531
      $( 'input#other-' + element + '-' + index, thisPreviewFieldset ).on( 'click' , function () {
3174 idir 1532
        // Insertion du champ "Autre" après les boutons
1533
        if( $( this ).is( ':checked' ) ) {
3241 idir 1534
          $( '.checkboxes', thisPreviewFieldset ).append( collectOther );
1535
        } else {
1536
          // Suppression du champ autre
1537
          optionRemove( thisPreviewFieldset );
1538
        }
1539
      });
1540
      break;
1541
    case 'checkbox' :
1542
      // Lorsque "Autre" est coché
1543
      $( 'input#other-' + element + '-' + index, thisPreviewFieldset ).on( 'click' , function () {
1544
        // Insertion du champ "Autre" après les boutons
1545
        if( $( this ).is( ':checked' ) ) {
3174 idir 1546
          $element.after( collectOther );
1547
        } else {
1548
          // Suppression du champ autre
3176 idir 1549
          optionRemove( thisPreviewFieldset );
3174 idir 1550
        }
1551
      });
1552
      break;
1553
 
1554
    default :
1555
      break;
1556
  }
1557
}
1558
 
1559
// Prévisualisation des nouveaux champs
1560
function newFieldsPreview() {
3226 idir 1561
  var count = $( 'fieldset' ).last().data( 'id' );
3174 idir 1562
  // Si on a déjà prévisualisé on efface tout pour recommencer
1563
  if( 0 < $( '.preview-fields' ).length ) {
1564
    $( '.preview-fields' ).each( function () {
1565
      $( this ).remove();
1566
    });
1567
  }
1568
  // Au premier ajout d'un champ dans la prévisualisation on ajoute un titre et un message
1569
  if( true === firstClick ) {
1570
    $( '#zone-supp' ).prepend(
3182 idir 1571
      '<h2>Informations propres au projet</h2>' +
1572
      '<div class="message">L\'objectif principal de cet aperçu est de vérifier les contenus et repérer d\'éventuelles erreurs</div>'
3174 idir 1573
    );
1574
  }
1575
  // Parcourir tous les blocs d'infos de champs supplémentaires
3226 idir 1576
  for( var index = $( 'fieldset' ).first().data( 'id' ) ; index <= count ; index++ ) {
3174 idir 1577
    var thisFieldset = $( 'fieldset[data-id="' + index + '"]');
1578
    // Certains indices peuvent correspondre à un champ supprimé
1579
    if( 0 < $( thisFieldset ).length ) {
1580
      // Prévisualisation d'un champ
1581
      $( '#zone-supp .preview-container' ).append(
3241 idir 1582
        '<div class="preview-fields col-sm-12 row" data-id="' + index + '">'+
3174 idir 1583
          onClickPreviewField( thisFieldset , index ) +
1584
        '</div>'
1585
      );
1586
      // Ajout/suppression d'un champ texte "Autre"
1587
      if( $( '.option-other-value' , thisFieldset ).is( ':checked' ) ) {
1588
        onOtherOption( thisFieldset , index);
1589
      }
1590
    }
1591
  }
1592
  // Le titre + message de la section prévisualisation ne sont ajoutés qu'une fois
1593
  firstClick = false;
1594
}
1595
 
3176 idir 1596
// Activation/Desactivation et contenu de la modale Bootstrap
1597
// https://getbootstrap.com/docs/3.3/javascript/#modals
3174 idir 1598
function previewFieldHelpModal() {
1599
  $( '#zone-supp' ).on( 'click' , '.help-button' , function ( event ) {
3226 idir 1600
    var index = $( this ).closest( '.preview-fields' ).data( 'id' ),
3174 idir 1601
        thisFieldset = $( '.new-field[data-id="' + index + '"]' ),
1602
        file = $( '.field-help' , thisFieldset )[0].files[0],
3176 idir 1603
        tmppath = URL.createObjectURL( file );
1604
    // Titre
3174 idir 1605
    $( '#help-modal-label' ).text( 'Aide pour : ' +  $( '.field-name' , thisFieldset ).val() );
3176 idir 1606
    // Contenu
3226 idir 1607
    if( file.type.match( 'image/*' ) ) {
3174 idir 1608
        $( '#print_content' ).append( '<img src="' + tmppath + '" style="max-width:100%">' );
3226 idir 1609
    } else {
1610
      $( '#print_content' ).append( '<p>Erreur : le fichier n\'est pas une image</p>' );
3167 idir 1611
    }
3176 idir 1612
    // Sortie avec la touche escape
3174 idir 1613
    $( '#help-modal' ).modal( { keyboard : true } );
3176 idir 1614
    // Affichage
3241 idir 1615
    $( '#help-modal' ).modal({ show: true });
3176 idir 1616
    // Remplacer l'autofocus qui ne fonctionne plus en HTML5
1617
    // Message dans la doc de bootstrap :
1618
    // Due to how HTML5 defines its semantics,
1619
    // the autofocus HTML attribute has no effect in Bootstrap modals.
1620
    // To achieve the same effect, use some custom JavaScript
3174 idir 1621
    $( '#help-modal' ).on( 'shown.bs.modal' , function () {
1622
      $( '#myInput' ).trigger( 'focus' );
1623
    })
3176 idir 1624
    // Réinitialisation
3174 idir 1625
    $( '#help-modal' ).on( 'hidden.bs.modal' , function () {
1626
      $( '#help-modal-label' ).text();
1627
      $( '#print_content' ).empty();
1628
    })
3167 idir 1629
  });
1630
}
3174 idir 1631
 
3341 idir 1632
function potDeMiel() {
1633
  if( !valeurOk( $( '#basic-widget-form #email' ).val() ) ) {
1634
    $( '#signup_submit' ).prop( 'disabled', false );
1635
  }
1636
  $( '#signup_submit' ).on( 'click dblclick mousedown submit focus keydown keypress keyup touchstart touchend', function() {
1637
    if( valeurOk( $( '#basic-widget-form #email' ).val() ) ) {
1638
      return false;
1639
    }
1640
  });
1641
  $( '#basic-widget-form #email' ).css({ position : 'absolute', left : '-2000px' }).on( 'input blur change', function( event ) {
1642
    event.preventDefault();
1643
    if( valeurOk( $( this ).val() ) ) {
1644
      $( 'form' ).each( function() {
1645
        $( this )[0].reset();
1646
      });
1647
      $( '#signup_submit' ).prop( 'disabled', true );
1648
    }
1649
  });
1650
}
1651
 
1652
/**
1653
* Permet à la fois de vérifier qu'une valeur ou objet existe et n'est pas vide
1654
* et de comparer à une autre valeur :
1655
* Vérifie qu'une variable ou objet n'est pas : vide, null, undefined, NaN
1656
* Si comparer est défini on le compare à valeur en fonction de sensComparaison
1657
* Un booléen est une variable valide : on retourne true
1658
* @param { string || number || object || undefined } valeur
1659
* @param { boolean } sensComparaison : true = rechercher, false = refuser
1660
* @param { string || number || object || undefined || boolean } comparer :valeur à comparer
1661
* @returns {boolean}
1662
*/
1663
function valeurOk( valeur, sensComparaison = true, comparer = undefined ) {
1664
  var retour;
1665
  if ( 'boolean' !== typeof valeur ) {
1666
    switch( typeof valeur ) {
1667
      case 'string' :
1668
        retour = ( '' !== valeur );
1669
        break;
1670
      case 'number' :
1671
        retour = ( NaN !== valeur );
1672
        break;
1673
      case 'object' :
1674
        retour = ( null !== valeur && undefined !== valeur && !$.isEmptyObject( valeur ) );
1675
        if ( undefined !== valeur.length ) {
1676
          retour = ( retour  && 0 < valeur.length );
1677
        }
1678
        break;
1679
      case 'undefined' :
1680
      default :
1681
        retour = false;
1682
    }
1683
    if ( retour && comparer !== undefined ) {
1684
      var resultComparaison = ( comparer === valeur );
1685
      retour = ( sensComparaison ) ? resultComparaison : !resultComparaison ;
1686
    }
1687
    return retour;
1688
  } else {
1689
    // Un booléen est une valeur valable
1690
    return true;
1691
  }
1692
}
1693
 
3174 idir 1694
/***************************
1695
 *  Lancement des scripts  *
1696
 ***************************/
1697
 
1698
// Tableau d'envoi des données
3176 idir 1699
var datasToSubmit = new Array();
3182 idir 1700
// Variable permettant un seul affichage du titre
1701
// de la prévisualisation pour les nouveaux champs
3176 idir 1702
var firstClick = true;
3174 idir 1703
 
1704
jQuery( document ).ready( function() {
3241 idir 1705
  // reset de tous les formulaires
1706
  $( 'form' ).each( function() {
1707
    $( this )[0].reset();
1708
  });
3341 idir 1709
  // Gestion du champ pot de miel
1710
  potDeMiel();
3174 idir 1711
  // Identifiant de champ
1712
  var fieldIndex = 0;
1713
  // Ajout de nouveaux champs
1714
  onClickAddNewFields( fieldIndex );
1715
  // Activation/Desactivation des boutons valider et prévisualiser
3188 idir 1716
  onClickButtonsTagMissingValues();
3174 idir 1717
  // Prévisualisation des champs classiques
3176 idir 1718
  DisplayClassicFields();
3174 idir 1719
  // Affichage des images ou nom des documents importés
1720
  inputFile();
1721
  // Affichage des List-checkbox
1722
  inputListCheckbox();
3226 idir 1723
  // Activer la checkbox de valeur par default uniquement si une valeur est entrée
1724
  onInputListValueLabelEnableDefaultCheckbox();
3185 idir 1725
  // Affichage des Range
3226 idir 1726
  inputRangeDisplayNumber();
3176 idir 1727
  // Modale "aide"
3174 idir 1728
  previewFieldHelpModal();
1729
});