Subversion Repositories eFlore/Applications.cel

Rev

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

Rev Author Line No. Line
3120 delphine 1
/**
2
 * Constructeur WidgetSaisie par défaut
3
 */
3425 idir 4
function WidgetSaisie( proprietes ) {
5
	if  ( valOk(proprietes) ) {
6
		this.urlWidgets                        = proprietes.urlWidgets;
3532 idir 7
		this.projet                            = proprietes.projet;
8
		this.idProjet                          = proprietes.idProjet;
9
		this.tagsMotsCles                      = proprietes.tagsMotsCles;
3425 idir 10
		this.mode                              = proprietes.mode;
11
		this.langue                            = proprietes.langue;
12
		this.serviceAnnuaireIdUrl              = proprietes.serviceAnnuaireIdUrl;
13
		this.serviceNomCommuneUrl              = proprietes.serviceNomCommuneUrl;
14
		this.serviceNomCommuneUrlAlt           = proprietes.serviceNomCommuneUrlAlt;
15
		this.debug                             = proprietes.debug;
16
		this.html5                             = proprietes.html5;
17
		this.serviceSaisieUrl                  = proprietes.serviceSaisieUrl;
18
		this.serviceObsUrl                     = proprietes.serviceObsUrl;
19
		this.chargementImageIconeUrl           = proprietes.chargementImageIconeUrl;
20
		this.pasDePhotoIconeUrl                = proprietes.pasDePhotoIconeUrl;
21
		this.autocompletionElementsNbre        = proprietes.autocompletionElementsNbre;
22
		this.serviceAutocompletionNomSciUrl    = proprietes.serviceAutocompletionNomSciUrl;
23
		this.serviceAutocompletionNomSciUrlTpl = proprietes.serviceAutocompletionNomSciUrlTpl;
24
		this.dureeMessage                      = proprietes.dureeMessage;
25
		this.obsMaxNbre                        = proprietes.obsMaxNbre;
26
		this.tagImg                            = proprietes.tagImg;
27
		this.tagObs                            = proprietes.tagObs;
28
		this.obsId                             = proprietes.obsId;
29
		this.nomSciReferentiel                 = proprietes.nomSciReferentiel;
30
		this.especeImposee                     = proprietes.especeImposee;
31
		this.infosEspeceImposee                = proprietes.infosEspeceImposee;
32
		this.referentielImpose                 = proprietes.referentielImpose;
33
		this.isTaxonListe                      = proprietes.isTaxonListe;
34
		this.utils                             = utils;
35
		this.msgs                              = utils.msgs;
36
	}
37
	this.urlRacine            = window.location.origin;
38
	this.obsNbre              = 0;
39
	this.nbObsEnCours         = 1;
3260 idir 40
	this.totalObsATransmettre = 0;
3425 idir 41
	this.nbObsTransmises      = 0;
42
	this.observer             = null;
43
	this.isASL                = false;
3120 delphine 44
}
3425 idir 45
WidgetSaisie.prototype = new WidgetsSaisiesCommun();
3120 delphine 46
 
3425 idir 47
var valOk = WidgetSaisie.prototype.valOk;
3120 delphine 48
 
49
/**
50
 * Initialise le formulaire, les validateurs, les listes de complétion...
51
 */
52
WidgetSaisie.prototype.initForm = function() {
3330 idir 53
	const lthis = this;
3120 delphine 54
 
3425 idir 55
	this.initFormConnection();
56
	if ( this.valOk( this.obsId ) ) {
3260 idir 57
		this.chargerInfoObs();
58
	}
59
	if( this.isTaxonListe ) {
3425 idir 60
		this.initFormTaxonListe();
3260 idir 61
	} else {
62
		this.ajouterAutocompletionNoms();
63
	}
64
	// au rafraichissement de la page,
65
	// les input date semblent conserver la valeur entrée précedemment
3425 idir 66
	// c'est voulu après la création d'une obs mais pas quand la page est actualisée
3260 idir 67
	// Déjà tenté: onbeforeunload avec un location.reload(true) n'a pas permis de le faire
68
	$( 'input[type=date]' ).each( function () {
3425 idir 69
		( lthis.valOk( $( this ).data( 'default' ) ) ) ? $( this ).val( $( this ).data( 'default' ) ) : $( this ).val( '' );
3260 idir 70
	});
71
	this.configurerFormValidator();
72
	this.definirReglesFormValidator();
73
 
74
	if( this.especeImposee ) {
3287 idir 75
		$( '#taxon' ).attr( 'disabled', 'disabled' );
76
		$( '#taxon-input-groupe' ).attr( 'title', '' );
77
		// Bricolage cracra pour avoir le nom retenu avec auteur (nom_retenu.libelle ne le mentionne pas)
78
		var infosEspeceImposee = $.parseJSON( this.infosEspeceImposee );
79
			nomRetenuComplet   = infosEspeceImposee.nom_retenu_complet,
80
			debutAnneRefBiblio = nomRetenuComplet.indexOf( ' [' );
81
		if ( -1 !== debutAnneRefBiblio ) {
82
			nomRetenuComplet = nomRetenuComplet.substr( 0, debutAnneRefBiblio );
83
		}
84
		// fin bricolage cracra
85
		var infosAssociee = {
86
			label : infosEspeceImposee.nom_sci_complet,
87
			value : infosEspeceImposee.nom_sci_complet,
88
			nt : infosEspeceImposee.num_taxonomique,
89
			nomSel : infosEspeceImposee.nom_sci,
90
			nomSelComplet : infosEspeceImposee.nom_sci_complet,
91
			numNomSel : infosEspeceImposee.id,
92
			nomRet : nomRetenuComplet,
93
			numNomRet : infosEspeceImposee['nom_retenu.id'],
94
			famille : infosEspeceImposee.famille,
95
			retenu : ( 'false' === infosEspeceImposee.retenu ) ? false : true
96
		};
97
		$( '#taxon' ).data( infosAssociee );
3260 idir 98
	}
3120 delphine 99
};
100
 
101
/**
102
 * Initialise les écouteurs d'événements
103
 */
104
WidgetSaisie.prototype.initEvts = function() {
3330 idir 105
	const lthis = this;
106
 
3260 idir 107
	// identité
3425 idir 108
	this.initEvtsConnection();
109
	// on location, initialisation de la géoloc
110
	this.initEvtsGeoloc();
3260 idir 111
	// Sur téléchargement image
3425 idir 112
	this.initEvtsFichier();
3330 idir 113
 
3260 idir 114
	$( '#referentiel' ).on( 'change', this.surChangementReferentiel.bind( this ) );
3425 idir 115
	// Création / Suppression / Transmission des obs
116
	// Défilement des miniatures dans le résumé obs
117
	this.initEvtsObs();
118
	// Alertes et aides
119
	this.initEvtsAlertes();
120
	// message avant de quitter le formulaire
121
	this.confirmerSortie();
3120 delphine 122
};
123
 
3287 idir 124
// Identité Observateur par courriel
125
WidgetSaisie.prototype.requeterIdentiteCourriel = function() {
3330 idir 126
	const lthis = this;
127
 
3260 idir 128
	var courriel = $( '#courriel' ).val();
129
	var urlAnnuaire = this.serviceAnnuaireIdUrl + courriel;
3330 idir 130
 
3425 idir 131
	if ( this.valOk( courriel ) ) {
3260 idir 132
		$.ajax({
133
			url : urlAnnuaire,
134
			type : 'GET',
135
			success : function( data, textStatus, jqXHR ) {
136
				if ( lthis.debug ) {
137
					console.log( 'SUCCESS: ' + textStatus );
138
				}
3425 idir 139
				if ( lthis.valOk( data ) && lthis.valOk( data[courriel] ) ) {
3260 idir 140
					var infos = data[courriel];
141
					lthis.surSuccesCompletionCourriel( infos, courriel );
142
				} else {
143
					lthis.surErreurCompletionCourriel();
144
				}
145
			},
146
			error : function( jqXHR, textStatus, errorThrown ) {
147
				if ( lthis.debug ) {
148
					console.log( 'ERREUR: '+ textStatus );
149
				}
150
				lthis.surErreurCompletionCourriel();
151
			},
152
			complete : function( jqXHR, textStatus ) {
153
				if ( lthis.debug ) {
154
					console.log( 'COMPLETE: '+ textStatus );
155
				}
156
			}
157
		});
158
	}
3120 delphine 159
};
160
 
3274 idir 161
// se déclanche quand on choisit "Observation sans inscription" mais que le mail entré est incrit à Tela
3260 idir 162
WidgetSaisie.prototype.surSuccesCompletionCourriel = function( infos, courriel ) {
3274 idir 163
	if ( $( '#utilisateur-connecte' ).hasClass( 'hidden' ) ) {// si quelque chose a foiré après actualisation
3425 idir 164
		if ( !this.valOk( $( '#warning-identite' ) ) ) {
3275 idir 165
			$( '#zone-courriel' ).before( '<p id="warning-identite" class="warning"><i class="fas fa-exclamation-triangle"></i> ' + this.msgTraduction( 'courriel-connu' ) + '</p>' );
166
		}
3425 idir 167
		$( '#inscription, #zone-prenom-nom, #zone-courriel-confirmation' ).addClass( 'hidden' );
3274 idir 168
		$( '#prenom, #nom, #courriel_confirmation' ).attr( 'disabled', 'disabled' );
169
		$( '.nav.control-group' ).addClass( 'error' );
170
	}
3120 delphine 171
};
172
 
3274 idir 173
// se déclanche quand on choisit "Observation sans inscription" et qu'effectivement le mail n'est pas connu de Tela
3260 idir 174
WidgetSaisie.prototype.surErreurCompletionCourriel = function() {
175
	$( '#creation-compte, #zone-prenom-nom, #zone-courriel-confirmation' ).removeClass( 'hidden' );
3275 idir 176
	$( '#warning-identite' ).remove();
3274 idir 177
	$( '.nav.control-group' ).removeClass( 'error' );
3425 idir 178
	$( '#prenom, #nom, #courriel_confirmation' ).val( '' ).removeAttr( 'disabled' );
3120 delphine 179
};
180
 
3208 idir 181
WidgetSaisie.prototype.testerLancementRequeteIdentite = function( event ) {
3425 idir 182
	if ( this.valOk( event.which, true, 13 ) ) {
3287 idir 183
		this.requeterIdentiteCourriel();
3260 idir 184
		event.preventDefault();
185
		event.stopPropagation();
186
	}
3120 delphine 187
};
188
 
3425 idir 189
WidgetSaisie.prototype.reduireVoletIdentite = function() {
190
	if ( $( '#form-observateur' ).valid() && $( '#courriel' ).valid() && $( '#courriel_confirmation' ).valid() ) {
191
		$( '#bouton-connexion, #creation-compte' ).addClass( 'hidden' );
192
		$( '#bienvenue').removeClass( 'hidden' );
193
		$( '#inscription, #zone-courriel' ).addClass( 'hidden' );
194
		if ( lthis.valOk( $( '#nom' ).val() ) && lthis.valOk( $( '#prenom' ).val() ) ) {
195
			$( '#zone-prenom-nom' ).addClass( 'hidden' );
196
			$( '#bienvenue-prenom' ).text( ' ' + $( '#prenom' ).val() );
197
			$( '#bienvenue-nom' ).text( ' ' + $( '#nom' ).val() );
198
		} else {
199
			$( '#zone-prenom-nom' ).removeClass( 'hidden' );
200
			$( '#bienvenue-prenom,#bienvenue-nom' ).text( '' );
201
		}
202
	} else {
203
		$( '#bouton-connexion, #creation-compte' ).removeClass( 'hidden' );
204
		$( '#bienvenue').addClass( 'hidden' );
205
	}
206
};
207
 
208
 
3260 idir 209
WidgetSaisie.prototype.formaterNom = function() {
3425 idir 210
	$( '#nom' ).val( $( '#nom' ).val().toUpperCase() );
3120 delphine 211
};
212
 
3260 idir 213
WidgetSaisie.prototype.formaterPrenom = function() {
3330 idir 214
	var prenom     = new Array(),
3425 idir 215
		mots       = $( '#prenom' ).val().split( ' ' ),
3330 idir 216
		motsLength = mots.length;
3120 delphine 217
 
3260 idir 218
	for ( var i = 0; i < motsLength; i++ ) {
219
		var mot = mots[i];
220
		if ( 0 <= mot.indexOf( '-' ) ) {
221
			var prenomCompose = new Array(),
3330 idir 222
				motsComposes = mot.split( '-' )
223
				motsComposesLength = motsComposes.length;
3260 idir 224
			for ( var j = 0; j < motsComposesLength; j++ ) {
3330 idir 225
				var motSimple    = motsComposes[j],
226
					motMajuscule = motSimple.charAt(0).toUpperCase() + motSimple.slice(1);
3208 idir 227
 
3260 idir 228
				prenomCompose.push( motMajuscule );
229
			}
230
			prenom.push( prenomCompose.join( '-' ) );
231
		} else {
232
			var motMajuscule = mot.charAt(0).toUpperCase() + mot.slice(1);
233
			prenom.push( motMajuscule );
234
		}
235
	}
3425 idir 236
	$( '#prenom' ).val( prenom.join( ' ' ) );
3120 delphine 237
};
238
 
3260 idir 239
WidgetSaisie.prototype.bloquerCopierCollerCourriel = function() {
240
	this.afficherPanneau( '#dialogue-bloquer-copier-coller' );
241
	return false;
3208 idir 242
};
243
 
3260 idir 244
// Préchargement des infos-obs ************************************************/
245
WidgetSaisie.prototype.chargerInfoObs = function() {
3330 idir 246
	const lthis = this;
247
 
3260 idir 248
	var urlObs = this.serviceObsUrl + '/' + this.obsId;
3330 idir 249
 
3260 idir 250
	$.ajax({
251
		url: urlObs,
252
		type: 'GET',
253
		success: function( data, textStatus, jqXHR ) {
3425 idir 254
			if ( lthis.valOk( data ) ) {
3260 idir 255
				lthis.prechargerForm( data );
256
			} else {
257
				lthis.surErreurChargementInfosObs.bind( lthis );
258
			}
259
		},
260
		error: function( jqXHR, textStatus, errorThrown ) {
261
			lthis.surErreurChargementInfosObs();
262
		}
263
	});
3120 delphine 264
};
265
 
3260 idir 266
// @TODO faire mieux que ça !
267
WidgetSaisie.prototype.surErreurChargementInfosObs = function() {
3425 idir 268
	this.activerModale( this.msgTraduction( 'erreur-chargement' ) );
3260 idir 269
};
3208 idir 270
 
3260 idir 271
WidgetSaisie.prototype.prechargerForm = function( data ) {
272
	$( '#milieu' ).val( data.milieu );
3425 idir 273
	$( '#commune-nom' ).text( data.zoneGeo );
274
	if( data.hasOwnProperty( 'codeZoneGeo' ) ) {
275
	  // TODO: trouver un moyen qui fonctionne lorsqu'on aura d'autres référentiels que INSEE
276
	  $( '#commune-insee' ).text( data.codeZoneGeo.replace( 'INSEE-C:', '' ) );
3260 idir 277
	}
3120 delphine 278
 
3425 idir 279
	if( data.hasOwnProperty( 'latitude' ) && data.hasOwnProperty( 'longitude' ) ) {
280
		// $cartoRemplacee = $( '#tb-geolocation' ),
281
		// suffixe = '',
282
		// layer = 'osm',
283
		// zoomInit = 18
284
		var typeLocalisation = $( '#top' ).data( 'type-loc' ),
285
			donnesResetCarto = {
286
			latitude         : data.latitude,
287
			longitude        : data.longitude,
288
			typeLocalisation : typeLocalisation
289
		};
290
		this.transfererCarto( donnesResetCarto );
3260 idir 291
	}
3120 delphine 292
};
293
 
3425 idir 294
// Ajouter Obs ****************************************************************/
295
/**
296
 * Retourne un Array contenant les valeurs des champs étendus
297
 */
298
WidgetSaisie.prototype.getObsChpSpecifiques = function() {
3330 idir 299
	const lthis = this;
3208 idir 300
 
3425 idir 301
	var champs    = new Array(),
302
		$thisForm = $( '#form-supp' ),
303
		elements  =
304
			'input[type=text]:not(.collect-other),'+
305
			'input[type=checkbox]:checked,'+
306
			'input[type=radio]:checked,'+
307
			'input[type=email],'+
308
			'input[type=number],'+
309
			'input[type=range],'+
310
			'input[type=date],'+
311
			'textarea,'+
312
			'.select',
313
		retour    = new Array();
3330 idir 314
 
3425 idir 315
	$( elements, $thisForm ).each( function() {
316
		if ( lthis.valOk( $( this ).val() ) && ( lthis.valOk( $( this ).attr( 'name' ) ) || lthis.valOk( $( this ).data( 'name' ) ) ) ) {
317
			var valeur = $( this ).val(),
318
				cle    = ( lthis.valOk( $( this ).attr( 'name' ) ) ) ? $( this ).attr( 'name' ) : $( this ).data( 'name' );
319
			if ( cle in champs ) {
320
				champs[cle] += ';' + valeur;
321
			} else {
322
				champs[cle] = valeur;
3260 idir 323
			}
3425 idir 324
		}
3260 idir 325
	});
3425 idir 326
	for ( var key in champs ) {
327
		retour.push({ 'cle' : key , 'valeur' : champs[key] });
3260 idir 328
	}
3425 idir 329
	if ( this.valOk( $( '#coord-lineaire' ).val() ) ) {
330
		retour.push({ 'cle' : 'coordonnees-rue-ou-lineaire' , 'valeur' : $( '#coord-lineaire' ).val() });
3260 idir 331
	}
3425 idir 332
	return retour;
3260 idir 333
};
3240 idir 334
 
3425 idir 335
WidgetSaisie.prototype.reinitialiserForm = function() {
336
	this.supprimerMiniatures();
337
	if( !this.especeImposee ) {
338
		$( '#taxon' ).val( '' );
339
		$( '#taxon' ).data( 'numNomSel', '' )
340
			.data( 'nomRet','' )
341
			.data( 'numNomRet', '' )
342
			.data( 'nt', '' )
343
			.data( 'famille', '' );
344
		if( this.isTaxonListe ) {
345
			$( '#taxon-liste' ).find( 'option' ).each( function() {
346
				if ( $( this ).hasClass( 'choisir' ) ) {
3260 idir 347
					$( this ).attr( 'selected', true );
348
				} else {
349
					$( this ).attr( 'selected', false );
350
				}
351
			});
3425 idir 352
			$( '#taxon-input-groupe' ).addClass( 'hidden' );
353
			$('#taxon-autre').val('');
3260 idir 354
		}
355
	}
3425 idir 356
	if ( this.valOk( $( '#form-supp' ) ) ) {
357
		$( '#form-supp' ).validate().resetForm();
358
	}
3208 idir 359
};
360
 
3330 idir 361
// Géolocalisation *************************************************************/
362
/**
363
 * Fonction handler de l'évenement location du module tb-geoloc
364
 */
365
WidgetSaisie.prototype.locationHandler = function( location ) {
366
	var locDatas = location.originalEvent.detail;
367
 
3425 idir 368
	if ( this.valOk( locDatas ) ) {
3330 idir 369
		console.log( locDatas );
3545 idir 370
		var geometry      = JSON.stringify( locDatas.geometry );
3425 idir 371
		var altitude      = ( this.valOk( locDatas.elevation ) ) ? locDatas.elevation : '';
372
		var pays          = ( this.valOk( locDatas.osmCountryCode ) ) ? locDatas.osmCountryCode.toUpperCase() : 'FR';
3330 idir 373
		var latitude      = '';
374
		var longitude     = '';
375
		var coordLineaire = '';
376
		var nomCommune    = '';
377
		var communeInsee  = '';
378
 
3425 idir 379
		if ( this.valOk( locDatas.geometry.coordinates ) ) {
3330 idir 380
			if ( 'Point' === locDatas.geometry.type ) {
3425 idir 381
				if ( this.valOk( locDatas.geometry.coordinates[0] ) ) {
3330 idir 382
					longitude = locDatas.geometry.coordinates[0];
383
				}
3425 idir 384
				if ( this.valOk( locDatas.geometry.coordinates[1] ) ) {
3330 idir 385
					latitude = locDatas.geometry.coordinates[1];
386
				}
387
			} else if ( 'LineString' === locDatas.geometry.type ) {// on a besoin que d'un point de la rue
388
				coordLineaire = JSON.stringify( locDatas.geometry.coordinates );
3425 idir 389
				if ( this.valOk( locDatas.geometry.coordinates[0][0] ) ) {
3330 idir 390
					longitude = locDatas.geometry.coordinates[0][0];
391
				}
3425 idir 392
				if ( this.valOk( locDatas.geometry.coordinates[0][1] ) ){
3330 idir 393
					latitude = locDatas.geometry.coordinates[0][1];
394
				}
395
			}
396
		}
3425 idir 397
		if ( this.valOk( locDatas.inseeData ) ) {
3330 idir 398
			nomCommune = locDatas.inseeData.nom;
3425 idir 399
			communeInsee = ( this.valOk( locDatas.inseeData.code ) ) ? locDatas.inseeData.code : '';
400
		} else if ( this.valOk( locDatas.locality ) ) {
3330 idir 401
			nomCommune = locDatas.locality;
3425 idir 402
		} else if ( this.valOk( locDatas.locality ) ) {
3330 idir 403
			nomCommune = locDatas.osmCounty;
404
		}
3532 idir 405
		$( '#geometry' ).val( geometry );
3330 idir 406
		$( '#coord-lineaire' ).val( coordLineaire );
407
		$( '#latitude' ).val( latitude );
408
		$( '#longitude' ).val( longitude );
409
		$( '#commune-nom' ).val( nomCommune );
410
		$( '#commune-insee' ).val( communeInsee );
411
		$( '#altitude' ).val( altitude );
412
		$( '#pays' ).val( pays );
3425 idir 413
		if ( this.valOk( $( '#latitude' ).val() ) && this.valOk( $( '#longitude' ).val() ) ) {
3330 idir 414
			$( '#geoloc' ).closest( '.control-group' ).removeClass( 'error' );
415
		} else {
416
			$( '#geoloc' ).closest( '.control-group' ).addClass( 'error' );
417
		}
418
	} else {
419
		console.log( 'Error location' );
420
	}
421
}
422
 
3260 idir 423
// Form Validator *************************************************************/
424
WidgetSaisie.prototype.chpEtendusValidation = function() {
3330 idir 425
	const lthis = this;
426
 
3260 idir 427
	var $thisForm = $( '#form-supp' ),
3330 idir 428
		elements  =
429
			'.checkbox,'+
430
			'.radio,'+
431
			'.checkboxes,'+
432
			'.select,'+
433
			'textarea,'+
434
			'input[type=text]:not(.collect-other),'+
435
			'input[type=email],'+
436
			'input[type=number],'+
437
			'input[type=range],'+
438
			'input[type=date]',
439
		speFields = ['checkbox','radio','checkboxes','select'],
440
		spefieldsCount = speFields.length,
441
		chpSuppValidation = {
442
			rules : {},
443
			messages : {},
444
			minmax : []
445
		},
446
		errors = {},
447
		namesListFields = [],
448
		picked = '';
3208 idir 449
 
3260 idir 450
	$( elements, $thisForm ).each( function() {
451
		for( var fieldsClass = 0; spefieldsCount > fieldsClass; fieldsClass++ ) {
3425 idir 452
			if ( lthis.valOk( $( this ).attr( 'required' ) ) && $( this ).hasClass( speFields[fieldsClass] ) && !lthis.valOk( chpSuppValidation.rules[ dataName ] ) ) {
3330 idir 453
 
3260 idir 454
				var dataName = $( this ).data( 'name' );
3240 idir 455
 
3260 idir 456
				namesListFields.push( dataName );
457
				chpSuppValidation.rules[ dataName ] = { required : true };
3425 idir 458
				if ( lthis.valOk( $( '.other', $( this ) ) ) ) {
3260 idir 459
					picked = ( 'select' === speFields[fieldsClass] ) ? ':selected' : ':checked';
460
					chpSuppValidation.rules[ 'collect-other-' + dataName.replace( '[]', '' ) ] = {
461
						required : '#other-' + dataName.replace( '[]', '' ) + picked,
462
						minlength: 1
463
					};
464
					chpSuppValidation.messages[ 'collect-other-' + dataName.replace( '[]', '' ) ] = false;
465
				}
466
				chpSuppValidation.rules[ dataName ]['listFields'] = true;
467
				chpSuppValidation.messages[ dataName ] = 'Ce champ est requis :\nVeuillez choisir une option, ou entrer une valeur autre valide.';
468
				errors[dataName] = '.' + speFields[fieldsClass];
469
			}
470
		}
3425 idir 471
		if ( lthis.valOk( $( this ).attr( 'name' ) ) && lthis.valOk ( $( this ).attr( 'required' ) ) && 0 > $.inArray( $( this ).attr( 'name' ) , namesListFields ) ) {
3260 idir 472
			chpSuppValidation.rules[ $( this ).attr( 'name' ) ] = { required : true, minlength: 1 };
473
			if(
3425 idir 474
				( lthis.valOk( $( this ).attr( 'type' ), true, 'number' ) || lthis.valOk( $( this ).attr( 'type' ), true, 'range' ) ) &&
475
				( lthis.valOk( $( this )[0].min ) || lthis.valOk( $( this )[0].max ) )
3330 idir 476
			) {
3260 idir 477
				chpSuppValidation.rules[ $( this ).attr('name') ]['minMaxOk'] = true;
478
				chpSuppValidation.messages[ $( this ).attr('name') ] = lthis.validerMinMax( $( this )[0] ).message;
479
			}
480
		}
481
	});
3425 idir 482
	if ( this.valOk( chpSuppValidation.rules ) ) {
3260 idir 483
		$.each( chpSuppValidation.rules, function( key ) {
3425 idir 484
			if ( !lthis.valOk( chpSuppValidation.messages[key] ) ) {
3260 idir 485
				chpSuppValidation.messages[key] = 'Ce champ est requis :\nVeuillez entrer une valeur valide.';
486
			}
487
		});
488
		if ( 0 < Object.keys( errors ).length ) {
489
			chpSuppValidation['errors'] = errors;
490
		}
491
	}
492
	return chpSuppValidation;
3208 idir 493
};
494
 
3260 idir 495
WidgetSaisie.prototype.validerMinMax = function( element ) {
496
	var mMCond      = new Boolean(),
3330 idir 497
		minCond     = parseFloat( element.value ) >= parseFloat( element.min ),
498
		maxCond     = parseFloat( element.value ) <= parseFloat( element.max ),
499
		messageMnMx = 'La valeur entrée doit être',
500
		returnMnMx  = { cond : true , message : '' };
3208 idir 501
 
3260 idir 502
	if(
3425 idir 503
		( this.valOk( element.type, true, 'number' ) || this.valOk( element.type, true, 'range' ) ) &&
504
		( this.valOk( element.min ) || this.valOk( element.max ) )
3330 idir 505
	) {
3260 idir 506
		if ( element.min && element.max ) {
507
			messageMnMx += ' comprise entre ' + element.min + ' et ' + element.max;
508
			mnMxCond     = ( minCond && maxCond );
509
		} else if ( element.min ) {
510
			messageMnMx += ' supérieure à ' + element.min;
511
			mnMxCond     = minCond;
512
		} else {
513
			messageMnMx += ' inférieure à ' + element.max;
514
			mnMxCond     = maxCond;
515
		}
516
		returnMnMx.cond    = mnMxCond;
517
		returnMnMx.message = messageMnMx;
518
	}
519
	return returnMnMx;
3208 idir 520
 
521
};
522
 
3260 idir 523
WidgetSaisie.prototype.definirReglesFormValidator = function() {
3330 idir 524
	const lthis = this;
3425 idir 525
 
3330 idir 526
	var formSuppValidation = this.chpEtendusValidation();
3208 idir 527
 
3260 idir 528
	$( '#form-supp' ).validate({
529
		onclick : function( element ) {
530
			if (
531
				(
3425 idir 532
					lthis.valOk( element.type, true, 'checkbox' ) ||
533
					lthis.valOk( element.type, true, 'radio' )
3260 idir 534
				) &&
535
				(
3425 idir 536
					!lthis.valOk( $( '.' + $( element ).attr( 'name' ).replace( '[]', '' ) + ':checked' ) ) ||
537
					lthis.valOk( $( '.' + $( element ).attr( 'name' ).replace( '[]', '' ) + ':not(.other):checked' ) ) ||
538
					!lthis.valOk( $( '#other-' + $( element ).attr( 'name' ).replace( '[]', '' ) ) ) ||
3260 idir 539
					$( '#other-' + $( element ).attr( 'name' ).replace( '[]', '' ) ).is( ':checked' ) ||
540
					(
541
						$( '#other-' + $( element ).attr( 'name' ).replace( '[]', '' ) ).is( ':checked' ) &&
542
						$( element ).closest( '.control-group' ).hasClass('error')
543
					)
544
				)
545
			) {
546
				$( element ).valid();
547
				if ( $( element ).valid() ) {
548
					$( element ).closest( '.control-group' ).removeClass( 'error' );
549
					$( element ).next( $( 'span.error' ) ).remove();
550
				} else {
551
					$( element ).closest( '.control-group' ).addClass( 'error' );
552
				}
553
			}
554
			return false;
555
		},
556
		rules : formSuppValidation.rules,
557
		messages : formSuppValidation.messages,
558
		errorPlacement : function( error , element ) {
559
			if ( 0 < Object.keys( formSuppValidation.errors ).length ) {
560
				var errorsKeys = Object.keys( formSuppValidation.errors ),
3330 idir 561
					thisKey = '',
562
					errorsFlag = true;
3260 idir 563
				for ( i = 0 ; i < errorsKeys.length ; i++ ) {
564
					thisKey = errorsKeys[i];
565
					if( $( element ).attr( 'name' ) === thisKey ) {
566
						$( formSuppValidation.errors[thisKey] ).append( error );
567
						errorsFlag = false;
568
					}
569
				}
570
				if ( errorsFlag ) {
571
					error.insertAfter( element );
572
				}
573
			} else {
574
				error.insertAfter( element );
575
			}
576
		}
577
	});
578
	$( '#form-supp .select' ).change( function() {
579
		$( this ).valid();
580
	});
581
	$( 'input[type=date]' ).on( 'input', function() {
582
		$( this ).valid();
583
	});
3272 idir 584
	// Validation Taxon si pas de miniature
3270 idir 585
	$( '#taxon' ).on( 'change', function() {
3425 idir 586
		var images = lthis.valOk( $( '#miniatures .miniature' ) );
587
		lthis.validerTaxonImage( lthis.valOk( $( this ).val() ), images );
3270 idir 588
	});
3272 idir 589
	// Validation miniatures avec MutationObserver
3270 idir 590
	this.surPresenceAbsenceMiniature();
3260 idir 591
	$( '#form-observation' ).validate({
592
		rules : {
593
			date_releve : {
594
				required : true,
595
				'dateCel' : true
596
			},
597
			latitude : {
3273 idir 598
				required : true,
3274 idir 599
				minlength : 1,
600
				range : [-90, 90]
3260 idir 601
			},
602
			longitude : {
3273 idir 603
				required : true,
3274 idir 604
				minlength : 1,
605
				range : [-180, 180]
3260 idir 606
			}
607
		}
608
	});
609
	$( '#form-observateur' ).validate({
610
		rules : {
611
			courriel : {
612
				required : true,
613
				email : true,
614
				'userEmailOk' : true
615
			},
616
			courriel_confirmation : {
617
				required : true,
618
				equalTo : '#courriel'
619
			}
620
		}
621
	});
3425 idir 622
	$( '#connexion,#inscription,#bouton-anonyme' ).on( 'click', function( event ) {
3274 idir 623
		$( '.nav.control-group' ).removeClass( 'error' );
624
	});
3208 idir 625
};
626
 
3270 idir 627
WidgetSaisie.prototype.validerTaxonImage = function( taxon = false, images = false ) {
628
	var taxonOuImage = ( images || taxon );
629
	if ( images || taxon ) {
630
		this.masquerPanneau( '#dialogue-taxon-or-image' );
631
		$( '#bloc-taxon' ).removeClass( 'error' )
632
			.find( 'span.error' ).hide();
633
		$( '#fichier' ).parent( 'label.label-file' ).removeClass( 'error' );
634
		$( '#photos-conteneur').removeClass( 'error' ).find( 'span.error' ).hide();
635
	} else {
636
		this.afficherPanneau( '#dialogue-taxon-or-image' );
637
		$( '#bloc-taxon' ).addClass( 'error' )
638
			.find( 'span.error' ).show();
639
		$( '#fichier' ).parent( 'label.label-file' ).addClass( 'error' );
640
		$( '#photos-conteneur').addClass( 'error' ).find( 'span.error' ).show();
641
	}
642
	return ( images || taxon );
643
};
644
 
645
WidgetSaisie.prototype.surPresenceAbsenceMiniature = function() {
3330 idir 646
	const lthis = this;
3271 idir 647
 
3272 idir 648
	// voir : https://developer.mozilla.org/en-US/docs/Web/API/MutationObserver/disconnect
3270 idir 649
	// Selectionne le noeud dont les mutations seront observées
650
	var targetNode = document.getElementById( 'miniatures' );
651
	// Fonction callback à éxécuter quand une mutation est observée
652
	var callback = function( mutationsList ) {
3287 idir 653
		for( var mutation of mutationsList ) {
3425 idir 654
			var taxon = lthis.valOk( $( '#taxon' ).val() );
3330 idir 655
 
3287 idir 656
			images = ( 0 < mutation.target.childElementCount );
657
			lthis.validerTaxonImage( taxon, images );
658
		}
3270 idir 659
	};
660
	// Créé une instance de l'observateur lié à la fonction de callback
3271 idir 661
	this.observer = new MutationObserver( callback );
3270 idir 662
	// Commence à observer le noeud cible pour les mutations précédemment configurées
3271 idir 663
	this.observer.observe( targetNode, { childList: true } );
3270 idir 664
};
665
 
3425 idir 666
WidgetSaisie.prototype.validerForm = function() {
667
	const lthis = this;
668
 
669
	var observateur  = ( $( '#form-observateur' ).valid() && $( '#courriel' ).valid() && $( '#courriel_confirmation' ).valid() );
3270 idir 670
	var obs          = $( '#form-observation' ).valid();
3425 idir 671
	var geoloc       = ( this.valOk( $( '#latitude' ).val() ) && this.valOk( $( '#longitude' ).val() ) ) ;
672
	var images       = this.valOk( $( '#miniatures .miniature' ) );
673
	var taxon        = this.valOk( $( '#taxon' ).val() );
3270 idir 674
	// validation et panneau taxon/images
3287 idir 675
	var taxonOuImage = this.validerTaxonImage( taxon, images );
3270 idir 676
	var chpsSupp     = new Boolean();
3425 idir 677
	if ( this.valOk( $( '#form-supp' ) ) ) {
3260 idir 678
		chpsSupp = ( function () {
679
			var otherFlag = $( '#form-supp' ).valid();
3425 idir 680
			if( lthis.valOk( $( '.other', $( '#form-supp' ) ) ) ) {
3260 idir 681
				$( '.other', $( '#form-supp' ) ).each( function() {
682
					var picked = ( $( this ).data( 'element' ) !== 'select' ) ? ':checked' : ':selected';
3425 idir 683
						if ( $( this ).is( picked ) && lthis.valOk( $( this ).val(), true, 'other' ) ) {
3260 idir 684
							otherFlag = false;
685
						}
686
				});
687
			}
688
			return otherFlag;
689
		})();
690
	} else {
691
		chpsSupp = true;
692
	}
3270 idir 693
	// panneau geoloc
3274 idir 694
	if ( geoloc ) {
695
		this.masquerPanneau( '#dialogue-geoloc-ko' );
696
		$( '#geoloc-datas' ).closest( '.control-group' ).removeClass( 'error' );
697
	} else{
698
		this.afficherPanneau( '#dialogue-geoloc-ko' );
699
		$( '#geoloc-datas' ).closest( '.control-group' ).addClass( 'error' );
700
	}
3270 idir 701
	// panneau observateur
3274 idir 702
	if ( observateur ) {
703
		this.masquerPanneau( '#dialogue-utilisateur-non-identifie' );
704
		$( '.nav.control-group' ).removeClass( 'error' );
705
	} else {
706
		this.afficherPanneau( '#dialogue-utilisateur-non-identifie' );
707
		$( '.nav.control-group' ).addClass( 'error' );
708
	}
709
	return ( observateur && obs && geoloc && taxonOuImage && chpsSupp );
3208 idir 710
};
711
 
3260 idir 712
// Referentiel ****************************************************************/
713
// N'est pas utilisé en cas de taxon-liste
714
WidgetSaisie.prototype.surChangementReferentiel = function() {
715
	this.nomSciReferentiel = $( '#referentiel' ).val();
716
	//réinitialise taxon.val
717
	$( '#taxon' ).val( '' );
3263 idir 718
	$( '#taxon' ).data( 'numNomSel', '' );
3208 idir 719
};