Subversion Repositories eFlore/Applications.cel

Rev

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