Subversion Repositories eFlore/Applications.cel

Rev

Go to most recent revision | Details | Last modification | View Log | RSS feed

Rev Author Line No. Line
3312 idir 1
function UtilsApa() {
2
	// this.infosUtilisateur = null;
3
	this.langue = $( 'body' ).data( 'lang' );
4
	this.urlRacine = window.location.origin;
5
	// système de traduction minimaliste
6
	this.msgs = {
7
		fr: {
8
			'arbre'                             : 'Arbre',
9
			'dupliquer'                         : 'Dupliquer',
10
			'saisir-plantes'                    : 'Saisir les plantes',
11
			'saisir-lichens'                    : 'Saisir les lichens',
12
			'format-non-supporte'               : 'Le format de fichier n\'est pas supporté, les formats acceptés sont',
13
			'image-deja-chargee'                : 'Cette image a déjà été utilisée',
14
			'date-incomplete'                   : 'Format : jj/mm/aaaa.',
15
			'observations-transmises'           : 'observations transmises',
16
			'supprimer-observation-liste'       : 'Supprimer cette observation de la liste à transmettre',
17
			'milieu'                            : 'Milieu',
18
			'commentaires'                      : 'Commentaires',
19
			'non-lie-au-ref'                    : 'non lié au référentiel',
20
			'obs-le'                            : 'le',
21
			'non-connexion'                     : 'Veuillez entrer votre login et votre mot de passe',
22
			'obs-numero'                        : 'Observation n°',
23
			'erreur'                            : 'Erreur',
24
			'erreur-inconnue'                   : 'Erreur inconnue',
25
			'erreur-image'                      : 'Erreur lors du chargement des images',
26
			'erreur-ajax'                       : 'Erreur Ajax',
27
			'erreur-chargement'                 : 'Erreur lors du chargement de l\'observation',
28
			'erreur-chargement-obs-utilisateur' : 'Erreur lors du chargement des observations de cet utilisateur',
29
			'erreur-formulaire'                 : 'Erreur: impossible de charger le formulaire',
30
			'lieu-obs'                          : 'observé à',
31
			'lieu-dit'                          : 'Lieu-dit',
32
			'station'                           : 'Station',
33
			'date-rue'                          : 'Un releve existe dejà à cette date pour cette rue.',
34
			'rechargement-page'                 : 'Êtes vous sûr de vouloir quiter la page?\nLes observations saisies mais non transmises seront perdues.'
35
		},
36
		en: {
37
			'arbre'                             : 'Tree',
38
			'dupliquer'                         : 'Duplicate',
39
			'saisir-plantes'                    : 'Enter the plants',
40
			'saisir-lichens'                    : 'Enter the lichens',
41
			'format-non-supporte'               : 'The file format is not supported, the accepted formats are',
42
			'image-deja-chargee'                : 'This image has already been used',
43
			'date-incomplete'                   : 'Format: dd/mm/yyyy.',
44
			'observations-transmises'           : 'observations transmitted',
45
			'supprimer-observation-liste'       : 'Delete this observation from the list to be transmitted',
46
			'milieu'                            : 'Environment',
47
			'commentaires'                      : 'Comments',
48
			'non-lie-au-ref'                    : 'unrelated to the referencial ',
49
			'obs-le'                            : 'the',
50
			'non-connexion'                     : 'Please enter your login and password',
51
			'obs-numero'                        : 'Observation number ',
52
			'erreur'                            : 'Error',
53
			'erreur-inconnue'                   : 'Unknown error',
54
			'erreur-image'                      : 'Error loading the images',
55
			'erreur-ajax'                       : 'Ajax Error',
56
			'erreur-chargement'                 : 'Error loading the observation',
57
			'erreur-chargement-obs-utilisateur' : 'Error loading this user\'s observations',
58
			'erreur-formulaire'                 : 'Error: couldn\'t load form',
59
			'lieu-obs'                          : 'observed at',
60
			'lieu-dit'                          : 'Locality',
61
			'station'                           : 'Place',
62
			'date-rue'                          : 'A record already exists on this date for this street',
63
			'rechargement-page'                 : 'Are you sure you want to leave the page?\nAll untransmitted observations will be lost.'
64
		}
65
	};
66
}
67
 
68
 
69
UtilsApa.prototype.chargerForm = function( nomSquelette, apaFormObj ) {
70
	const lthis = this;
71
	var urlSqueletteArbres = this.urlRacine + '/widget:cel:apa?squelette=' + nomSquelette;
72
 
73
	$.ajax({
74
		url: urlSqueletteArbres,
75
		type: 'get',
76
		success: function( squelette ) {
77
			if ( lthis.valOk( squelette ) ) {
78
				apaFormObj.chargerSquelette( squelette, nomSquelette );
79
			}
80
		},
81
		error: function() {
82
			$( '#charger-form' ).html( lthis.msgTraduction( 'erreur-formulaire' ) );
83
		}
84
	});
85
};
86
 
87
UtilsApa.prototype.chargerFormPlantesOuLichens = function( squelette, nomSquelette ) {
88
	if ( this.valOk( $( '#releve-data' ).val() ) ) {
89
		$( '#charger-form' ).html( squelette );
90
		const releveDatas = $.parseJSON( $( '#releve-data' ).val() );
91
		const nbArbres    = releveDatas.length -1;
92
 
93
		for ( var i = 1; i <= nbArbres ; i++ ) {
94
			$( '#choisir-arbre' ).append(
95
				'<option value="' + i + '">'+
96
					this.msgTraduction( 'arbre' ) + ' ' + i +
97
				'</option>'
98
			);
99
		}
100
	}
101
};
102
 
103
/**
104
 * Stocke en Json les valeurs du relevé dans en value d'un input hidden
105
 */
106
UtilsApa.prototype.formaterReleveData = function( releveDatas ) {
107
	var releve  = [],
108
		obs  = releveDatas.obs,
109
		obsE = releveDatas.obsE;
110
 
111
	releve[0] = {
112
		utilisateur        : obs.ce_utilisateur,
113
		date               : obs.date_observation,
114
		rue                : obsE.rue,
115
		'commune-nom'      : obs.zone_geo,
116
		'commune-insee'    : obs.ce_zone_geo,
117
		pays               : obs.pays,
118
		latitude           : obs.latitude,
119
		longitude          : obs.longitude,
120
		altitude           : obs.altitude,
121
		'zone-pietonne'    : obsE['zone-pietonne'],
122
		'pres-lampadaires' : obsE['pres-lampadaires'],
123
		commentaires       : obs.commentaire
124
	};
125
	return releve;
126
};
127
 
128
/**
129
 * Stocke en Json les valeurs d'une obs
130
 */
131
UtilsApa.prototype.formaterArbreData = function( arbresDatas ) {
132
	var retour = {},
133
		obs          = arbresDatas.obs,
134
		obsE         = arbresDatas.obsE,
135
		miniatureImg = [];
136
	if( this.valOk( obs['miniature-img'] ) ) {
137
		miniatureImg = obs['miniature-img'];
138
	} else if ( this.valOk( obsE['miniature-img'] ) ) {
139
		miniatureImg = $.parseJSON( obsE['miniature-img'] );
140
	}
141
 
142
	retour = {
143
		'date_rue_commune'      : obs.date_observation + obsE.rue + obs.zone_geo,
144
		'num-arbre'             : obsE.num_arbre,
145
		'id_observation'        : obs.id_observation,
146
		'taxon'                 : {
147
			'numNomSel' : obs.nom_sel_nn,
148
			'value'     : obs.nom_sel,
149
			'nomRet'    : obs.nom_ret,
150
			'numNomRet' : obs.nom_ret_nn,
151
			'nt'        : obs.nt,
152
			'famille'   : obs.famille,
153
		},
154
		'miniature-img'         : miniatureImg,
155
		'referentiel'           : obs.nom_referentiel,
156
		'certitude'             : obs.certitude,
3322 idir 157
		'rue-arbres'            : obsE['rue-arbres'],
3312 idir 158
		'latitude-arbres'       : obsE['latitude-arbres'],
159
		'longitude-arbres'      : obsE['longitude-arbres'],
160
		'altitude-arbres'       : obsE['altitude-arbres'],
161
		'circonference'         : obsE.circonference,
162
		'surface-pied'          : obsE['surface-pied'],
163
		'equipement-pied-arbre' : obsE['equipement-pied-arbre'],
164
		'tassement'             : obsE.tassement,
165
		'dejections'            : obsE.dejections,
166
		'face-ombre'            : obsE['face-ombre'],
167
		'com-arbres'            : obsE['com-arbres']
168
	};
169
	return retour;
170
};
171
 
172
UtilsApa.prototype.fournirDate = function( dateObs ) {
173
	if ( /^[0-9]{2}\/[0-9]{2}\/[0-9]{4}$/.test( dateObs ) ) {
174
		return dateObs;
175
	} else if ( /^[0-9]{4}-[0-9]{2}-[0-9]{2}$/.test( dateObs ) ) {
176
		var dateArray = dateObs.split( '-' );
177
		return dateArray[2] + '/' + dateArray[1] + '/' + dateArray[0]
178
	} else {
179
		console.log( 'erreur date : ' + dateObs )
180
	}
181
};
182
 
183
/**
184
 * Si la langue est définie dans this.langue, et si des messages sont définis
185
 * dans this.msgs, tente de trouver le message dont la clé est [cle] dans la
186
 * langue en cours. S'il n'est pas trouvé, retourne la version française (par
187
 * défaut); si celle-ci n'exite pas, retourne "N/A".
188
 */
189
UtilsApa.prototype.msgTraduction = function( cle ) {
190
	var msg = 'N/A';
191
 
192
	if ( this.msgs ) {
193
		if ( this.langue in this.msgs && cle in this.msgs[this.langue] ) {
194
			msg = this.msgs[this.langue][cle];
195
		} else if ( cle in this.msgs['fr'] ) {
196
			msg = this.msgs['fr'][cle];
197
		}
198
	}
199
	return msg;
200
};
201
 
202
/**
203
* Permet à la fois de vérifier qu'une valeur ou objet existe et n'est pas vide
204
* et de comparer à une autre valeur :
205
* Vérifie qu'une variable ou objet n'est pas : vide, null, undefined, NaN
206
* Si comparer est défini on le compare à valeur en fonction de sensComparaison
207
* Un booléen est une variable valide : on retourne true
208
* @param { string || number || object || undefined } valeur
209
* @param { boolean } sensComparaison : true = rechercher, false = refuser
210
* @param { string || number || object || undefined || boolean } comparer :valeur à comparer
211
* @returns {boolean}
212
*/
213
UtilsApa.prototype.valOk = function( valeur, sensComparaison = true, comparer = undefined ) {
214
	var retour = true;
215
	if ( 'boolean' !== typeof valeur ) {
216
		switch( typeof valeur ) {
217
			case 'string' :
218
				retour = ( '' !== valeur );
219
			 break;
220
			case 'number' :
221
					retour = ( NaN !== valeur );
222
				break;
223
			case 'object' :
224
					retour = ( null !== valeur && undefined !== valeur && !$.isEmptyObject( valeur ) );
225
					if (  null !== valeur && undefined !== valeur.length ) {
226
						retour = ( retour  && 0 < valeur.length );
227
					}
228
				break;
229
			case 'undefined' :
230
			default :
231
				retour = false;
232
		}
233
		if ( retour && comparer !== undefined ) {
234
			var resultComparaison = ( comparer === valeur );
235
			retour = ( sensComparaison ) ? resultComparaison : !resultComparaison ;
236
		}
237
 
238
		return retour;
239
	} else {
240
		// Un booléen est une valeur valable
241
		return true;
242
	}
243
}
244
 
245
// Lib hors objet
246
 
247
/*************************************
248
 *  Fonctions de Style et Affichage  *
249
 *      des éléments "spéciaux"      *
250
 *************************************/
251
 
252
// Logique d'affichage pour le input type=file
253
function inputFile() {
254
  // Initialisation des variables
255
  var $fileInput  = $( '.input-file' ),
256
      $button     = $( '.label-file' );
257
  // Action lorsque la "barre d'espace" ou "Entrée" est pressée
258
  $( '#charger-form' ).on( 'keydown', '.label-file', function( event ) {
259
    if ( event.keyCode == 13 || event.keyCode == 32 ) {
260
      $( '#' + $( this ).attr( 'for' ) + '.input-file' ).click();
261
    }
262
  });
263
}
264
 
265
// Style et affichage des list-checkboxes
266
function inputListCheckbox() {
267
  // On écoute le click sur une list-checkbox ('.selectBox')
268
  // à tout moment de son insertion dans le dom
269
  // _ S'assurer de bien viser la bonne list-checkbox
270
  // _ Au click sur un autre champ remballer la list-checkbox
271
  $( document ).click( function( event ) {
272
    var target = event.target;
273
 
274
    if ( !$( target ).is( '.overSelect' ) && 0 === $( target ).closest( '.checkboxes' ).length ) {
275
      $( '.checkboxes' ).each( function () {
276
        $( this ).addClass( 'hidden' );
277
      });
278
      $( '.selectBox select.focus', '#zone-appli' ).each( function() {
279
        $( this ).removeClass( 'focus' );
280
      });
281
    }
282
  });
283
  $( '#zone-appli' ).on( 'click' , '.selectBox' , function() {
284
    // afficher/cacher le volet des checkboxes et focus
285
    $( this ).next().toggleClass( 'hidden' );
286
    $( this ).find( 'select' ).toggleClass( 'focus' );
287
 
288
    // Cacher le volet des autres checkboxes et retirer leur focus
289
    var $checkboxes = $( this ).next(),
290
        count = $( '.checkboxes' ).length;
291
 
292
    for ( var i = 0; i < count; i++ ) {
293
      if ( $( '.checkboxes' )[i] !== $checkboxes[0] && !$checkboxes.hasClass( 'hidden' ) ) {
294
        var $otherListCheckboxes = $( '.checkboxes' )[i];
295
        if ( !$otherListCheckboxes.classList.contains( 'hidden' ) ) {
296
          $otherListCheckboxes.classList.add( 'hidden' );
297
        }
298
        if( $otherListCheckboxes.previousElementSibling.firstElementChild.classList.contains( 'focus' ) ) {
299
          $otherListCheckboxes.previousElementSibling.firstElementChild.classList.remove( 'focus' );
300
        }
301
      }
302
    }
303
  });
304
}
305
 
306
// Style et affichage des input type="range"
307
function inputRangeDisplayNumber() {
308
  $( 'input[type="range"]','#charger-form' ).each( function() {
309
    $( this ).siblings( '.range-live-value' ).text( $( this ).val() );
310
  });
311
  $( '#top' ).on( 'input' , 'input[type="range"]' , function () {
312
    $( this ).siblings( '.range-live-value' ).text( $( this ).val() );
313
  });
314
  $( '#top' ).on( 'click', '#ajouter-obs', function() {
315
    $( '.range-live-value' ).each( function() {
316
      var $this = $( this );
317
      $this.text( '' );
318
    });
319
  });
320
}
321
 
322
// Activation/Desactivation et contenu de la modale Bootstrap
323
// https://getbootstrap.com/docs/3.3/javascript/#modals
324
function newFieldsHelpModal() {
325
  $( '#zone-appli' ).on( 'click' , '.help-button' , function ( event ) {
326
    var thisFieldKey = $( this ).data( 'key' ),
327
        fileMimeType = $( this ).data( 'mime-type' );
328
 
329
    // Titre
330
    $( '#help-modal-label' ).text( 'Aide pour : ' +  $( this ).data( 'name' ) );
331
    if( fileMimeType.match( 'image' ) ) {
332
      var extention = fileMimeType.replace( /(?:imag)?e\/?/g , '' );
333
      // var extention = 'jpg';
334
      $( '#print_content' ).append( '<img src="' + CHEMIN_FICHIERS + thisFieldKey + '.' + extention + '" style="max-width:100%" alt="' + thisFieldKey + '" />' );
335
    }
336
    // Sortie avec la touche escape
337
    $( '#help-modal' ).modal( { keyboard : true } );
338
    // Affichage
339
    $( '#help-modal' ).modal({ show: true });
340
    // Remplacer l'autofocus qui ne fonctionne plus en HTML5
341
    // Message dans la doc de bootstrap :
342
    // Due to how HTML5 defines its semantics,
343
    // the autofocus HTML attribute has no effect in Bootstrap modals.
344
    // To achieve the same effect, use some custom JavaScript
345
    $( '#help-modal' ).on( 'shown.bs.modal' , function () {
346
      $( '#myInput' ).trigger( 'focus' );
347
    })
348
    // Réinitialisation
349
    $( '#help-modal' ).on( 'hidden.bs.modal' , function () {
350
      $( '#help-modal-label' ).text();
351
      $( '#print_content' ).empty();
352
    })
353
  });
354
}
355
 
356
// Activation/Desactivation et contenu de la modale Bootstrap
357
// https://getbootstrap.com/docs/3.3/javascript/#modals
358
function projetHelpModale() {
359
  $( '#top' ).on ( 'click', '#info-button', function ( event ) {
360
    var fileMimeType = $( this ).data( 'mime-info' );
361
 
362
    // Titre
363
    $( '#help-modal-label' ).text( 'Aide du projet : ' +  $( '#titre-projet' ).text() );
364
    if( fileMimeType.match( 'image' ) ) {
365
      var extention = fileMimeType.replace( /(?:imag)?e\/?/g , '' );
366
      $( '#print_content' ).append( '<img src="' + CHEMIN_FICHIERS + 'info.' + extention + '" style="max-width:100%" alt="info projet" />' );
367
    }
368
    // Sortie avec la touche escape
369
    $( '#help-modal' ).modal( { keyboard : true } );
370
    // Affichage
371
    $( '#help-modal' ).modal({ show: true });
372
    // Remplacer l'autofocus qui ne fonctionne plus en HTML5
373
    // Message dans la doc de bootstrap :
374
    // Due to how HTML5 defines its semantics,
375
    // the autofocus HTML attribute has no effect in Bootstrap modals.
376
    // To achieve the same effect, use some custom JavaScript
377
    $( '#help-modal' ).on( 'shown.bs.modal' , function () {
378
      $( '#myInput' ).trigger( 'focus' );
379
    })
380
    // Réinitialisation
381
    $( '#help-modal' ).on( 'hidden.bs.modal' , function () {
382
      $( '#help-modal-label' ).text();
383
      $( '#print_content' ).empty();
384
    });
385
 
386
  });
387
}
388
 
389
// Faire apparaitre un champ text "Autre"
390
function onOtherOption() {
391
  const PREFIX = 'collect-other-';
392
 
393
  // Ajouter un champ texte pour "Autre"
394
  function optionAdd( otherId, $target, element, dataName ) {
395
    $target.after(
396
      '<div class="control-group">'+
397
        '<label'+
398
          ' for="' + otherId + '"'+
399
          ' class="' + otherId + '"'+
400
        '>'+
401
          'Autre option :'+
402
        '</label>'+
403
        '<input'+
404
          ' type="text"'+
405
          ' id="' + otherId + '"'+
406
          ' name="' + otherId + '"'+
407
          ' class="collect-other form-control"'+
408
          ' data-name="' + dataName + '"'+
409
          ' data-element="' + element + '"'+
410
        '>'+
411
      '</div>'
412
    );
413
    $( '#' + otherId ).focus();
414
  }
415
 
416
  // Supprimer un champ texte pour "Autre"
417
  function optionRemove( otherId ) {
418
    $( '.' + otherId + ', #' + otherId ).remove();
419
  }
420
 
421
  $( '.other', '#form-arbre' ).each( function() {
422
    if( $( this ).hasClass( 'is-select' ) ) {
423
      var dataName = $( this ).data( 'name' ),
424
          otherId  = PREFIX + dataName;
425
 
426
      // Insertion du champ "Autre" après les boutons
427
      optionAdd( otherId, $( this ).parent( '.add-field-select' ), 'select', dataName );
428
    } else if ( $( this ).is( ':checked' ) ) {
429
      var dataName = $( this ).data( 'name' ),
430
          otherId  = PREFIX + dataName,
431
          element = $( this ).data( 'element' );
432
      // Insertion du champ "Autre" après les boutons
433
      optionAdd( otherId, $( this ).parent( 'label' ), element, dataName );
434
    }
435
  });
436
 
437
  $( '#charger-form' ).on( 'change', '.select', function () {
438
    var dataName = $( this ).data( 'name' ),
439
        otherId  = PREFIX + dataName;
440
 
441
    if( 'other' === $( this ).val() ) {
442
        // Insertion du champ "Autre" après les boutons
443
        optionAdd( otherId, $( this ).parent( '.add-field-select' ), 'select', dataName );
444
      } else {
445
        // Suppression du champ autre
446
        optionRemove( otherId );
447
        $( this ).find( '.other' ).val( 'other' );
448
      }
449
  });
450
 
451
  $( '#charger-form' ).on( 'change', 'input[type=radio]', function () {
452
    var dataName = $( this ).data( 'name' ),
453
        otherId  = PREFIX + dataName;
454
 
455
    if( 'other' === $( this ).val() ) {
456
      // Insertion du champ "Autre" après les boutons
457
      optionAdd( otherId, $( this ).parent( 'label' ), 'radio', dataName );
458
    } else {
459
      // Suppression du champ autre
460
      optionRemove( otherId );
461
      $( this ).closest( '.radio' ).find( '.other' ).val( 'other' );
462
    }
463
  });
464
 
465
  $( '#charger-form' ).on( 'click', '.list-checkbox .other,.checkbox .other', function () {
466
    var dataName = $( this ).data( 'name' ),
467
        otherId  = PREFIX + dataName,
468
        element = $( this ).data( 'element' );
469
 
470
    if( $( this ).is( ':checked' ) ) {
471
        // Insertion du champ "Autre" après les boutons
472
        optionAdd( otherId, $( this ).parent( 'label' ), element, dataName );
473
      } else {
474
        // Suppression du champ autre
475
        optionRemove( otherId );
476
        $( this ).val( 'other' );
477
      }
478
  });
479
}
480
 
481
function collectOtherOption() {
482
  $( '#charger-form' ).on( 'change', '.collect-other', function () {
483
    var otherIdSuffix = $( this ).data( 'name' ).replace( '[]', '' );
484
    var element = $( this ).data( 'element' );
485
 
486
    if ( '' === $( this ).val() ){
487
      if ( 'select' === element ) {
488
        $( '#' + otherIdSuffix ).find( '.other' ).prop( 'selected', false ).val( 'other' );
489
      } else {
490
        $( '#other-' + otherIdSuffix ).prop( 'checked', false ).val( 'other' );
491
      }
492
      $( 'label.collect-other-' + otherIdSuffix ).remove();
493
      $( this ).remove();
494
    } else {
495
      if ( 'select' === element ) {
496
        $( '#' +  otherIdSuffix ).find( '.other' ).val( $( this ).val() );
497
        $( '#' +  otherIdSuffix ).val( $( this ).val() );
498
        $( '#' +  otherIdSuffix + ' option').not( '.other' ).prop( 'selected', false );
499
        $( '#' +  otherIdSuffix ).find( '.other' ).prop( 'selected', true );
500
      } else {
501
        if ( 'radio' === element ) {
502
          $( 'input[name=' + otherIdSuffix + ']' ).not( '#other-' + otherIdSuffix ).prop( 'checked', false );
503
        }
504
        $( '#other-' + otherIdSuffix ).val( $( this ).val() );
505
        $( '#other-' + otherIdSuffix ).prop( 'checked', true );
506
      }
507
    }
508
  });
509
}
510
 
511
/***************************
512
 *  Lancement des scripts  *
513
 ***************************/
514
const CHEMIN_FICHIERS = $( '#zone-appli' ).data('url-fichiers');
515
 
516
jQuery( document ).ready( function() {
517
  // Modale "aide" du projet
518
  projetHelpModale();
519
  // Affichage input file
520
  inputFile();
521
  // Affichage des List-checkbox
522
  inputListCheckbox();
523
  // Affichage des Range
524
  inputRangeDisplayNumber()
525
  // Modale "aide"
526
  newFieldsHelpModal();
527
  // Ajout/suppression d'un champ texte "Autre"
528
  onOtherOption();
529
  // Récupérer les données entrées dans "Autre"
530
  collectOtherOption();
531
});