Subversion Repositories eFlore/Applications.moissonnage

Rev

Rev 43 | Details | Compare with Previous | Last modification | View Log | RSS feed

Rev Author Line No. Line
48 mathias 1
var map = null,
2
optionsCoucheOSM = {
3
	attribution: 'Map data &copy; <a href="http://openstreetmap.org">OpenStreetMap</a> contributors,'
4
	+ ' <a href="http://creativecommons.org/licenses/by-sa/2.0/">CC-BY-SA</a>',
5
	maxZoom: 18
6
},
7
optionsCoucheGoogle = {
8
	attribution: 'Map data &copy;'+new Date().getFullYear()+' <a href="http://maps.google.com">Google</a>',
9
	maxZoom: 18
10
},
11
coucheOSM = new L.TileLayer("http://a.tile.openstreetmap.org/{z}/{x}/{y}.png",
12
	optionsCoucheOSM),
13
coucheRelief = new L.TileLayer("http://c.tile3.opencyclemap.org/landscape/{z}/{x}/{y}.png",
14
	optionsCoucheOSM),
15
coucheSatellite = new L.TileLayer("http://mt1.google.com/vt/lyrs=y@218131653&hl=fr&src=app&x={x}&y={y}&z={z}",
16
	optionsCoucheGoogle),
17
optionsCarte = {
18
	center : new L.LatLng(46, 2),
19
	zoom : 6,
20
	minZoom : 3,
21
	maxBounds : [[-85.051129, -180], [85.051129, 180]],
22
	layers : [coucheOSM]
23
},
24
zoom = 6,
25
legende = null,
26
coucheDepartement = null,
27
infoBulle = null;
28
 
29
var coucheSites = null,
30
sources = new Object(),
31
typeSite = 'maille',
32
overlays = [];
33
 
34
var requeteChargementPoints = null,
35
timer = null,
36
ancienneRequete = null,
37
deplacement = true,
38
url = '';
39
 
40
 
41
 
42
 
43
$(document).ready(function() {
44
	initialiserWidget();
45
});
46
 
47
$(window).resize(function() {
48
	dimensionnerCarte();
49
});
50
 
51
function initialiserWidget() {
52
	initialiserCarte();
53
	chargerLimitesCommunales();
54
	initialiserPanneauControle();
55
	initialiserSources();
56
	initialiserListeners();
57
	chargerLocalisations();
58
}
59
 
60
function initialiserCarte() {
61
	dimensionnerCarte();
62
	map = L.map('map', optionsCarte);
63
	coucheSatellite.addTo(map);
64
	coucheRelief.addTo(map);
65
	coucheOSM.addTo(map);
66
	var echelle = new L.Control.Scale({
67
		maxWidth : 50,
68
		metric : true,
69
		imperial : false,
70
		updateWhenIdle : true
71
	});
72
	map.addControl(echelle);
73
	zoom = map.getZoom();
74
}
75
 
76
function dimensionnerCarte() {
77
	$('#map').height($(window).height());
78
	$('#map').width($(window).width());
79
}
80
 
81
function initialiserListeners() {
82
	map.on('moveend', surChangementVueCarte);
83
	map.on('zoomend', surChangementVueCarte);
84
	map.on('popupclose', function(e) {
85
		masquerInfoBulle();
86
		programmerRafraichissementCarte();
87
	});
88
}
89
 
90
function initialiserPanneauControle() {
91
	var baseMaps = {
92
		"Satellite" : coucheSatellite,
93
		"Relief" : coucheRelief,
94
		"Plan" : coucheOSM
95
	};
96
 
97
	var overlayMaps = {};
98
	for (var index = 0; index < listeSources.length; index ++) {
99
		sources[listeSources[index]] = estValeurDansTableau(source, listeSources[index]);
100
		overlayMaps[listeSources[index]] = new L.LayerGroup();
101
	}
102
	L.control.layers(baseMaps, overlayMaps).addTo(map);
103
	coucheOSM.bringToFront();
104
	map.removeLayer(coucheRelief);
105
	map.removeLayer(coucheOSM);
106
 
107
	// garder par defaut la couche plan google comme selectionnee dans le panel
108
	var selecteursFonds = $('.leaflet-control-layers-base .leaflet-control-layers-selector');
109
	selecteursFonds[0].checked = true;
110
	selecteursFonds[1].checked = false;
111
	selecteursFonds[2].checked = false;
112
}
113
 
114
function chargerLimitesCommunales() {
115
	coucheDepartement = new L.KML(null, {async : true}).addTo(map);
116
	if (urlsLimitesCommunales != null) {
117
		coucheDepartement.addKMLFiles(urlsLimitesCommunales);
118
	}
119
}
120
 
121
function initialiserSources() {
122
	overlays = $('.leaflet-control-layers-overlays .leaflet-control-layers-selector');
123
	$.each(overlays, function (index, input) {
124
		input.value = listeSources[index];
125
		input.id = 'overlay' + (index+1);
126
		var lien = '<a href="' + liensVersSources[index] + '" target="_blank">' + nomListeSources[index] + '</a>';
127
		$('#overlay' + (index+1) + ' ~ span').html(lien);
128
		input.checked = sources[listeSources[index]];
129
		input.onclick = function(event) {
130
			changerSource(event.target.value);
131
		}
132
	});
133
}
134
 
135
function changerSource(projetClique) {
136
	var indexProjetClique;
137
	for (var index = 0; index < overlays.length; index ++) {
138
		if (overlays[index].value == projetClique) {
139
			indexProjetClique = index;
140
		}
141
	}
142
	masquerInfoBulle();
143
	sources[projetClique] = overlays[indexProjetClique].checked;
144
	if (sources[projetClique] == true) {
145
		programmerRafraichissementCarte(projetClique);
146
	} else {
147
		if (requeteEnCours()) {
148
			stopperRequeteAjax();
149
		}
150
		supprimerFeaturesSource(projetClique);
151
	}
152
}
153
 
154
function supprimerFeaturesSource(source) {
155
	if (coucheSites != null) {
156
		coucheSites.eachLayer(function(layer) {
157
			if (layer.typeSite == 'maille') {
158
				retirerStationsEtObservations(layer, source);
159
			} else {
160
				layer.supprimerSource(source, coucheSites);
161
				if (layer._map == 'null') {
162
					couheSites.removeLayer(layer);
163
				}
164
			}
165
		});
166
		if (typeSite == 'maille') {
167
			var nombreMailles = calculerNombreMaillesVisibles();
168
			if (nombreMailles == 0) {
169
				coucheSites.clearLayers();
170
				masquerLegende();
171
				typeSite = 'point';
172
			}
173
		}
174
	}
175
}
176
 
177
function retirerStationsEtObservations(maille, sourceRetrait) {
178
	var sources = maille.properties.source;
179
	var nombreStations = 0;
180
	for (var index = 0; index < sources.length; index ++) {
181
		var source = sources[index];
182
		if (source == sourceRetrait) {
183
			delete maille.properties.stations[source];
184
			delete maille.properties.observations[source];
185
		} else if (typeof(maille.properties.stations[source]) != 'undefined') {
186
			nombreStations += parseInt(maille.properties.stations[source]);
187
		}
188
	}
189
	if (nombreStations == 0) {
190
		coucheSites.removeLayer(maille);
191
	} else {
192
		colorerMaille(maille)
193
		genererInfobulle(maille);
194
	}
195
}
196
 
197
function calculerNombreMaillesVisibles() {
198
	var nombreMailles = 0;
199
	coucheSites.eachLayer(function(layer) {
200
		if($(layer._path).attr('fill-opacity') != '0') {
201
			nombreMailles ++;
202
		}
203
	});
204
	return nombreMailles;
205
}
206
 
207
function estValeurDansTableau(tableau, valeur) {
208
	var index;
209
	for (index = 0; index < tableau.length && tableau[index] != valeur; index ++);
210
	return (tableau.length > 0 && index != tableau.length);
211
}
212
 
213
//************************************
214
// requetes stations
215
 
216
function surChangementVueCarte() {
217
	programmerRafraichissementCarte();
218
}
219
 
220
function programmerRafraichissementCarte(source) {
221
	$('#tooltip').css('display', 'none');
222
	source = (source == null || source == 'null') ? null : source;
223
	if (timer != null) {
224
		window.clearTimeout(timer);
225
	}
226
	if (requeteChargementPoints != null) {
227
		stopperRequeteAjax();
228
	}
229
	var nombreSourcesVisibles = 0;
230
	for (var index = 0; index < overlays.length; index ++) {
231
		if (overlays[index].checked) {
232
			nombreSourcesVisibles ++;
233
		}
234
	}
235
	if (source == null) {
236
		timer = window.setTimeout("chargerLocalisations()", 100);
237
	} else {
238
		timer = window.setTimeout("chargerSource('"+source+"')", 100);
239
	}
240
}
241
 
242
function stopperRequeteAjax() {
243
	requeteChargementPoints.abort();
244
	requeteChargementPoints = null;
245
}
246
 
247
function chargerLocalisations() {
248
	if (requeteEnCours()) {
249
		requeteChargementPoints.abort();
250
	}
251
	afficherMessageChargement('stations');
252
	if (!(ancienneRequete != null && ancienneRequete[1] == map.getZoom()
253
		&& map.getBounds().intersects(ancienneRequete[0]))) {
254
		supprimerFeatures();
255
		deplacement = false;
256
	}
257
	var bboxRequete = calculerBboxRequete();
258
	var parametres = {
259
		"bbox" : bboxRequete,
260
		"zoom" : map.getZoom(),
261
		"source" : recupererSourcesActivees(),
262
		"num_taxon" : numTaxon,
263
		"nn" : nn,
264
		"referentiel" : referentiel,
265
		"dept" : dept,
266
		"auteur" : auteur,
267
		"date_debut" : dateDebut,
268
		"date_fin" : dateFin,
269
		"nb_jours" : nbJours
270
	};
271
	if (deplacement == true) {
272
		parametres.format = typeSite;
273
	}
274
	ancienneRequete = [map.getBounds(), map.getZoom()];
275
	url = urlBase + "stations?" + convertirEnParametresUrl(parametres);
276
	fonctionCallback = traiterDonneesStations;
277
	executerAJAX();
278
}
279
 
280
function supprimerFeatures() {
281
	if (coucheSites != null) {
282
		coucheSites.clearLayers();
283
		coucheSites = null;
284
	}
285
}
286
 
287
function recupererSourcesActivees(sourceAIgnorer) {
288
	sourceAIgnorer = typeof(sourceAIgnorer) == 'undefined' ? '' : sourceAIgnorer;
289
	var sourcesActivees = [];
290
	for (var index = 0; index < overlays.length; index ++) {
291
		if (overlays[index].checked == true && overlays[index].value != sourceAIgnorer) {
292
			sourcesActivees.push(overlays[index].value);
293
		}
294
	}
295
	return sourcesActivees.join(',');
296
}
297
 
298
function chargerSource(sourceAjout) {
299
	if (requeteEnCours()) {
300
		requeteChargementPoints.abort();
301
	}
302
	afficherMessageChargement('stations');
303
	var bboxRequete = determinerCoordonneesBordure();
304
	var parametres = {
305
		"bbox" : bboxRequete,
306
		"zoom" : map.getZoom(),
307
		"format" : typeSite,
308
		"source" : sourceAjout,
309
		"num_taxon" : numTaxon,
310
		"nn" : nn,
311
		"referentiel" : referentiel,
312
		"dept" : dept,
313
		"auteur" : auteur,
314
		"date_debut" : dateDebut,
315
		"date_fin" : dateFin,
316
		"nb_jours" : nbJours
317
	};
318
	ancienneRequete = [map.getBounds(), map.getZoom()];
319
	url = urlBase + "stations?" + convertirEnParametresUrl(parametres);
320
	fonctionCallback = traiterRetourChargementSource;
321
	executerAJAX();
322
}
323
 
324
function calculerBboxRequete() {
325
	var bordure = map.getBounds();
326
	var bboxRequete = "";
327
	if (ancienneRequete != null && ancienneRequete[1] == map.getZoom()
328
		&& bordure.intersects(ancienneRequete[0])) {
329
		bboxRequete = calculerIntersectionRectangle(ancienneRequete[0], bordure);
330
	} else {
331
		bboxRequete = determinerCoordonneesBordure();
332
	}
333
	return bboxRequete;
334
}
335
 
336
function calculerIntersectionRectangle(rectangle1, rectangle2) {
337
	var bbox1 = [rectangle2.getSouthWest().lng.toFixed(6), rectangle2.getSouthWest().lat.toFixed(6),
338
	    rectangle2.getNorthEast().lng.toFixed(6), rectangle2.getNorthEast().lat.toFixed(6)];
339
	var bbox2 = [rectangle2.getSouthWest().lng.toFixed(6), rectangle2.getSouthWest().lat.toFixed(6),
340
	    rectangle2.getNorthEast().lng.toFixed(6), rectangle2.getNorthEast().lat.toFixed(6)];
341
 
342
	if (rectangle2.getSouthWest().lng >= rectangle1.getSouthWest().lng
343
	 	&& rectangle2.getSouthWest().lng <= rectangle1.getNorthEast().lng) {
344
		bbox2[0] = bbox1[2] = rectangle1.getNorthEast().lng.toFixed(6);
345
		if (rectangle2.getSouthWest().lat >= rectangle1.getSouthWest().lat
346
			&& rectangle2.getSouthWest().lat <= rectangle1.getNorthEast().lat) {
347
			bbox1[1] = rectangle1.getNorthEast().lat.toFixed(6);
348
		} else {
349
			bbox1[3] = rectangle1.getSouthWest().lat.toFixed(6);
350
		}
351
	} else {
352
		bbox2[0] = bbox1[2] = rectangle1.getSouthWest().lng.toFixed(6);
353
		if (rectangle2.getSouthWest().lat >= rectangle1.getSouthWest().lat
354
			&& rectangle2.getSouthWest().lat <= rectangle1.getNorthEast().lat) {
355
			bbox2[1] = rectangle1.getNorthEast().lat.toFixed(6);
356
		} else {
357
			bbox2[3] = rectangle1.getSouthWest().lat.toFixed(6);
358
		}
359
	}
360
	return bbox1.join(',')+'|'+bbox2.join(',');
361
}
362
 
363
function determinerCoordonneesBordure() {
364
	var ouest = map.getBounds().getSouthWest().lng.toFixed(6),
365
		sud = Math.max(map.getBounds().getSouthWest().lat, -85.051129).toFixed(6),
366
		est = map.getBounds().getNorthEast().lng.toFixed(6),
367
		nord = Math.min(map.getBounds().getNorthEast().lat, 85.051129).toFixed(6);
368
	// appliquer les limites possibles de la projection actuellement utilisee aux coordonnees
369
	// longitudes ouest et est de la bbox (permettra d'eviter de renvoyer des messages d'erreur)
370
	if (ouest < -180) {
371
		ouest += 360;
372
	} else if (ouest > 180) {
373
		ouest -= 360;
374
	}
375
	if (est < -180) {
376
		est += 360;
377
	} else if (est > 180) {
378
		est -= 360;
379
	}
380
	return [ouest, sud, est, nord].join(',');
381
}
382
 
383
function afficherMessageChargement(element) {
384
	if ($("#zone-chargement").css('display') == 'none') {
385
		var divTmplElement = 'tpl-chargement-' + element;
386
		$("#zone-chargement").append($("#" + divTmplElement).text());
387
		$("#zone-chargement").css('display', 'block');
388
	}
389
}
390
 
391
function masquerMessageChargement() {
392
	$("#zone-chargement").css('display', 'none');
393
	$("#zone-chargement").children().remove();
394
}
395
 
396
function executerAJAX() {
397
	if (requeteEnCours()) {
398
		requeteChargementPoints.abort();
399
	}
400
	requeteChargementPoints = $.getJSON(url).complete(function() {
401
		fonctionCallback();
402
	});
403
}
404
 
405
function requeteEnCours() {
406
	return (requeteChargementPoints != null && requeteChargementPoints.readyState != 4);
407
}
408
 
409
function estStatutRequeteOK() {
410
	return ((requeteChargementPoints.status == 200 || requeteChargementPoints.status == 304)
411
		|| requeteChargementPoints.status == 0);
412
}
413
 
414
function convertirEnParametresUrl(objet) {
415
	var parametresUrl = '';
416
	for (attribut in objet) {
417
		if (typeof(objet[attribut]) == 'function' || typeof(objet[attribut]) == 'undefined' ||
418
			objet[attribut] == null || objet[attribut] == '*' || objet[attribut] == 0)
419
			continue;
420
		parametresUrl += (parametresUrl == '' ? '' : '&') + attribut + "=" + objet[attribut];
421
	}
422
	return parametresUrl;
423
};
424
 
425
function traiterDonneesStations() {
426
	masquerMessageChargement();
427
	masquerLegende();
428
	if (deplacement == true) {
429
		supprimerFeaturesHorsBbox();
430
	}
431
	deplacement = true;
432
	var texte = requeteChargementPoints.responseText;
433
	if (!estStatutRequeteOK()) {
434
		alert(texte);
435
	} else {
436
		var donneesJSON = eval("(function(){return " + texte + ";})()");
437
		if (donneesJSON != null && donneesJSON.features.length > 0) {
438
			ajouterStationsSurCarte(donneesJSON);
439
		}
440
	}
441
}
442
 
443
function traiterRetourChargementSource() {
444
	masquerMessageChargement();
445
	var texte = requeteChargementPoints.responseText;
446
	if (!estStatutRequeteOK()) {
447
		alert(texte);
448
	} else {
449
		var donneesJSON = eval("(function(){return " + texte + ";})()");
450
		if (donneesJSON != null && donneesJSON.features.length > 0) {
451
			var formatRetourDifferent = donneesJSON.stats.formeDonnees != typeSite;
452
			ajouterStationsSurCarte(donneesJSON);
453
			if (formatRetourDifferent) {
454
				var sourceAIgnorer = donneesJSON.stats.source[0];
455
				var sourcesARecharger = recupererSourcesActivees(sourceAIgnorer);
456
				if (sourcesARecharger.length > 0) {
457
					rechargerSources(sourcesARecharger);
458
				}
459
			}
460
		}
461
	}
462
}
463
 
464
function supprimerFeaturesHorsBbox() {
465
	var bordure = map.getBounds();
466
	var layersRestants = 0;
467
	if (coucheSites != null) {
468
		coucheSites.eachLayer(function(layer) {
469
			if (typeof(layer._latlng) != 'undefined') {
470
				if (bordure.contains(layer.getLatLng())) {
471
					layersRestants ++;
472
				} else {
473
					coucheSites.supprimerPoint(layer);
474
				}
475
			} else {
476
				if (bordure.intersects(layer.getBounds())) {
477
					layersRestants ++;
478
				} else {
479
					coucheSites.removeLayer(layer);
480
				}
481
			}
482
		});
483
	}
484
	if (layersRestants == 0) {
485
		coucheSites = null;
486
	}
487
}
488
 
489
function rechargerSources(sourcesARecharger) {
490
	var listeSourcesASupprimer = sourcesARecharger.split(',');
491
	for (var index = 0; index < listeSourcesASupprimer.length; index ++) {
492
		supprimerFeaturesSource(listeSourcesASupprimer[index]);
493
	}
494
	chargerSource(sourcesARecharger);
495
}
496
 
497
function ajouterStationsSurCarte(donnees) {
498
	typeSite = donnees.stats.formeDonnees;
499
	if (coucheSites == null) {
500
		coucheSites = (typeSite == 'maille') ? new L.FeatureGroup() : new L.ClusterGroup();
501
		map.addLayer(coucheSites);
502
	}
503
	for (var index = 0; index < donnees.features.length; index ++) {
504
		var feature = donnees.features[index];
505
		if (typeSite == 'maille') {
506
			traiterMaille(feature);
507
		} else {
508
			ajouterPoint(feature);
509
		}
510
	}
511
	if (donnees.features.length > 0) {
512
		afficherLegende();
513
	}
514
	if (typeSite == 'maille') {
515
		genererInfobulleMailles();
516
	} else {
517
		coucheSites.afficherClusters();
518
	}
519
}
520
 
521
// =========================================
522
// Gestion des mailles
523
 
524
function traiterMaille(feature) {
525
	var coordonnees = [];
526
	for (var i = 0; i < feature.geometry.coordinates.length; i++) {
527
		var sommet = new L.LatLng(feature.geometry.coordinates[i][0], feature.geometry.coordinates[i][1]);
528
		coordonnees.push(sommet);
529
	}
530
	var maille = rechercherMailleExistante(coordonnees);
531
	if (maille) {
532
		mettreAJourMaille(maille, feature);
533
	} else {
534
		maille = ajouterMaille(feature, coordonnees);
535
	}
536
	colorerMaille(maille);
537
}
538
 
539
function rechercherMailleExistante(coordonnees) {
540
	var mailleTrouvee = null;
541
	coucheSites.eachLayer(function(layer) {
542
		if ('typeSite' in layer && layer.typeSite == 'maille') {
543
			if (sontMaillesIdentiques(coordonnees, layer._latlngs)) {
544
				mailleTrouvee = layer;
545
				return;
546
			}
547
		}
548
	});
549
	return mailleTrouvee;
550
}
551
 
552
function sontMaillesIdentiques(coordonnees1, coordonnees2) {
553
	return (
554
		coordonnees1[0].lat == coordonnees2[0].lat &&
555
		coordonnees1[0].lng == coordonnees2[0].lng &&
556
		coordonnees1[2].lat == coordonnees2[2].lat &&
557
		coordonnees1[2].lng == coordonnees2[2].lng
558
	);
559
}
560
 
561
function ajouterMaille(feature, coordonnees) {
562
	var maille = new L.Polygon(coordonnees);
563
	var optionsMaille = {
564
		color: '#FFFFFF',
565
		opacity : 0.7,
566
		weight: 1,
567
		fillOpacity : 0.6
568
	};
569
	maille.setStyle(optionsMaille);
570
	maille.typeSite = 'maille';
571
	maille.properties = feature.properties;
572
	coucheSites.addLayer(maille);
573
	return maille;
574
}
575
 
576
function mettreAJourMaille(maille, feature) {
577
	var sources = feature.properties.source;
578
	for (var index = 0; index < sources.length; index ++) {
579
		var source = sources[index];
580
		maille.properties.stations[source] = parseInt(feature.properties.stations[source]);
581
		maille.properties.observations[source] = parseInt(feature.properties.observations[source]);
582
		maille.properties.source.push(source);
583
	}
584
}
585
 
586
function colorerMaille(maille) {
587
	var nombreStations = 0;
588
	var sources = maille.properties.source;
589
	for (var index = 0; index < sources.length; index ++) {
590
		var source = sources[index];
591
		if (typeof(maille.properties.stations[source]) != 'undefined') {
592
			nombreStations += parseInt(maille.properties.stations[source]);
593
		}
594
	}
595
	if (nombreStations > 0) {
596
		maille.on('click', surClicMaille);
597
		maille.setStyle({fillColor : genererCouleur(nombreStations), fillOpacity: 0.45, opacity: 0.7});
598
	} else {
599
		maille.setStyle({fillOpacity: 0, opacity: 0});
600
		maille.off('click');
601
	}
602
}
603
 
604
function genererCouleur(nombrePoints) {
605
	var couleur = {'bleu': 231, 'vert': 224, 'rouge': 64},
606
		seuils = [1, 10, 50 ,100, 500, 1000, 2500],
607
		pas = 26,
608
		position = 0;
609
	for (var index = 1; index < seuils.length-1 && nombrePoints >= seuils[index]; index ++) {
610
		position ++;
611
	}
612
	couleur.vert -= position*pas;
613
	return 'rgb('+couleur.bleu+','+couleur.vert+','+couleur.rouge+')';
614
}
615
 
616
function surClicMaille(event) {
617
	map.fitBounds(event.layer.getBounds());
618
}
619
 
620
function afficherLegende() {
621
	if (legende == null) {
622
		legende = new L.Control({position : 'bottomright'});
623
		legende.onAdd = function(map) {
624
			var contenuHtml = '';
625
			if (typeSite == 'maille') {
626
				contenuHtml = construireContenuHtmlLegendeMailles();
627
			} else {
628
				contenuHtml = construireContenuHtmlLegendePoints();
629
			}
630
			return contenuHtml;
631
		};
632
		map.addControl(legende);
633
	}
634
}
635
 
636
function construireContenuHtmlLegendeMailles() {
637
	var div = L.DomUtil.create('div', 'info');
638
	div.innerHTML = '<h4>' + titreLegende + '</h4>';
639
	var seuils = [1, 10, 50 ,100, 500, 1000, 2500];
640
	var labels = [];
641
	for (var i = 0; i < seuils.length; i ++) {
642
		div.innerHTML +=
643
			'<div class="legend">'+
644
				'<span class="couleur-maille" style="background:' + genererCouleur(seuils[i] + 1) + '">'+
645
				'</span>'+seuils[i]+ (i + 1 < seuils.length ? '&ndash;' + seuils[i + 1] : '+')+
646
			'</div>';
647
	}
648
	return div;
649
}
650
 
651
function masquerLegende() {
652
	if (legende != null) {
653
		map.removeControl(legende);
654
		legende = null;
655
	}
656
}
657
 
658
function genererInfobulleMailles() {
659
	coucheSites.eachLayer(function(layer) {
660
		if (layer.typeSite == 'maille') {
661
			genererInfobulle(layer);
662
		}
663
	});
664
}
665
 
666
function genererInfobulle(maille) {
667
	var sources = maille.properties.source;
668
	var textes = new Array();
669
	for (var index = 0; index < sources.length; index ++) {
670
		var source = sources[index];
671
		if (typeof(maille.properties.stations[source]) != 'undefined') {
672
			textes.push(source+" : "+maille.properties.stations[source]+" stations, "
673
				+maille.properties.observations[source]+" observations");
674
		}
675
	}
676
	var contenu = textes.join('<br />');
677
	maille.on('mouseover', function() {
678
		afficherTooltip(contenu, map.latLngToContainerPoint(maille.getBounds().getSouthWest()));
679
	});
680
	maille.on('mouseout', function() {
681
		$("#tooltip").css('display', 'none');
682
	});
683
}
684
 
685
function afficherTooltip(texte, point) {
686
	$("#tooltip").html(texte);
687
	if ($("#tooltip").css('display') == 'none') {
688
		var x = point.x - 15;
689
		var y = point.y + (typeSite == 'maille' ? 1 : 10);
690
		$("#tooltip").css('display', 'block');
691
		$("#tooltip").css('left', x + 'px');
692
		$("#tooltip").css('top', y + 'px');
693
	}
694
}
695
 
696
 
697
 
698
 
699
// ====================================================================
700
// Gestion des points
701
 
702
function ajouterPoint(feature) {
703
	var iconePoint = new L.Icon({ iconUrl : pointImageUrl,   iconSize : [16, 16] }),
704
		iconeCommune   = new L.Icon({ iconUrl : communeImageUrl, iconSize : [24, 32] }),
705
		icone = (feature.properties.typeSite == 'STATION') ? iconePoint : iconeCommune,
706
		point = new L.LatLng(feature.geometry.coordinates[0], feature.geometry.coordinates[1]);
707
	var marker = new L.Cluster(point, {
708
		icon  : icone,
709
		titre : feature.properties.nom
710
	});
711
	marker.typeSite = feature.properties.typeSite.toLowerCase();
712
	marker.source = feature.properties.source;
713
	marker.on('click', surClicMarqueur);
714
	marker.on('mouseover', function() {
715
		afficherTooltip(marker.options.titre, map.latLngToContainerPoint(marker.getLatLng()));
716
	});
717
	marker.on('mouseout', function() {
718
		$("#tooltip").css('display', 'none');
719
	});
720
	coucheSites.ajouterPoint(marker);
721
}
722
 
723
function construireContenuHtmlLegendePoints() {
724
	var div = L.DomUtil.create('div', 'info');
725
	div.innerHTML =
726
	'<h4>Stations</h4>'+
727
	'<div class="legend"><table>'+
728
		'<tr>'+
729
			'<td class="image-station"><img src="'+communeImageUrl+'" width="24" height="32" /></td>'+
730
			'<td class="label-station">Commune</td>'+
731
		'</tr>'+
732
		'<tr>'+
733
			'<td class="image-station"><img src="'+pointImageUrl+'" /></td>'+
734
			'<td class="label-station">Lieu précis</td>'+
735
		'</tr>'+
736
		'<tr>'+
737
			'<td class="image-station"><img src="'+clusterImageUrl+'" width="20" height="20" /></td>'+
738
			'<td class="label-station">Groupe de stations proches</td>'+
739
		'</tr>'+
740
	'</table></div>';
741
	return div;
742
}
743
 
744
 
745
function surClicMarqueur(event) {
746
	var nombreMarkers = event.target.recupererMarkers().length;
747
	if (nombreMarkers == 1 || map.getZoom() == map.getMaxZoom()) {
748
		recupererObservations(event.target);
749
	} else {
750
		map.setView(event.target.getLatLng(), Math.min(map.getZoom()+2, map.getMaxZoom()));
751
	}
752
}
753
 
754
function recupererObservations(cluster) {
755
	pointClique = cluster;
756
	var latlng = cluster.getLatLng();
757
	afficherMessageChargement('observations');
758
	var parametres = {
759
		"source" : recupererSourcesCluster(cluster),
760
		"stations" : construireListeStationsCluster(cluster),
761
		"num_taxon" : numTaxon,
762
		"nn" : nn,
763
		"referentiel" : referentiel,
764
		"auteur" : auteur,
765
		"date_debut" : dateDebut,
766
		"date_fin" : dateFin,
767
		"nb_jours" : nbJours
768
	};
769
	url = urlBase + "observations?" + convertirEnParametresUrl(parametres);
770
	fonctionCallback = traiterDonneesObservations;
771
	executerAJAX();
772
}
773
 
774
function recupererSourcesCluster(cluster) {
775
	var markers = cluster.recupererMarkers();
776
	var sourcesCluster = [];
777
	for (var index = 0; index < markers.length; index ++) {
778
		if (sourcesCluster.indexOf(markers[index].source) == -1) {
779
			sourcesCluster.push(markers[index].source);
780
		}
781
	}
782
	return sourcesCluster.join(',');
783
}
784
 
785
function construireListeStationsCluster(cluster) {
786
	var markers = cluster.recupererMarkers();
787
	var listePoints = [];
788
	for (var index = 0; index < markers.length; index ++) {
789
		var latlng = markers[index].getLatLng();
790
		listePoints.push(markers[index].source+":"+markers[index].typeSite+":"+latlng.lng+","+latlng.lat);
791
	}
792
	return listePoints.join('|');
793
}
794
 
795
function traiterDonneesObservations() {
796
	masquerMessageChargement();
797
	var texte = requeteChargementPoints.responseText;
798
	if (!estStatutRequeteOK()) {
799
		alert(texte);
800
	} else {
801
		obsJSON = eval("(function(){return " + texte + ";})()");
802
		if (obsJSON != null) {
803
			viderListeObservations();
804
			if (obsJSON.total > 0) {
805
				doitRafraichirCarte = false;
806
				map.setView(new L.LatLng(pointClique.getLatLng().lat, pointClique.getLatLng().lng), map.getZoom());
807
				afficherInfoBulle();
808
			} else if (infoBulle != null)  {
809
				masquerInfoBulle();
810
			}
811
		}
812
	}
813
}
814
 
815
 
816
 
817
 
818
// ====================================================================
819
// Gestion de l'infobulle
820
 
821
var obsJSON = null,
822
	pointClique = null,
823
	obsStation = [],
824
	pagineur = {'limite':100, 'start':0, 'total':0, 'stationId':null, 'format':'tableau'};
825
 
826
function afficherInfoBulle() {
827
	var latitude = pointClique.getLatLng().lat;
828
	var longitude = pointClique.getLatLng().lng;
829
	infoBulle = new L.Popup({maxWidth : definirLargeurInfoBulle(), maxHeight : 380});
830
	infoBulle.setLatLng(new L.LatLng(latitude, longitude));
831
	infoBulle.setContent($("#tpl-obs").html());
832
	infoBulle.openOn(map);
833
	remplirContenuPopup();
834
	$('#info-bulle').css('width', '99%');
835
	$('#observations').css('height', '250px');
836
	$('#observations').css('overflow', 'auto');
837
	$('.leaflet-popup-scrolled').css('overflow', 'visible');
838
}
839
 
840
function viderListeObservations() {
841
	obsStation = new Array();
842
}
843
 
844
function definirLargeurInfoBulle() {
845
	var largeurViewPort = $(window).width();
846
	var lageurInfoBulle = null;
847
	if (largeurViewPort < 800) {
848
		largeurInfoBulle = 400;
849
	} else if (largeurViewPort >= 800 && largeurViewPort < 1200) {
850
		largeurInfoBulle = 500;
851
	} else if (largeurViewPort >= 1200) {
852
		largeurInfoBulle = 600;
853
	}
854
	return largeurInfoBulle;
855
}
856
 
857
function redimensionnerPopup() {
858
	$('.leaflet-popup-content*').css('width', definirLargeurInfoBulle());
859
	$('#info-bulle').css('width', '99%');
860
}
861
 
862
function remplirContenuPopup() {
863
	ajouterTableauTriable("#obs-tableau");
864
	ajouterTitre();
865
	afficherTableau();
866
	afficherTexteStationId();
867
}
868
 
869
function masquerInfoBulle() {
870
	if (infoBulle != null && map.hasLayer(infoBulle)) {
871
		map.removeLayer(infoBulle);
872
	}
873
	infoBulle = null;
874
}
875
 
876
function ajouterTitre() {
877
	var texteStationTitre = obsJSON.total + ' observation' + (obsJSON.total > 1 ? 's' : '')
878
		+ ' sur ' + (pointClique.typeSite=='station' ? 'la station : ' : 'la commune : ')
879
		+ pointClique.options.title;
880
	$('#obs-station-titre').text(texteStationTitre);
881
}
882
 
883
function afficherTableau() {
884
	construireListeObservations();
885
	afficherPagination();
886
	afficherObservationsDansHTML();
887
}
888
 
889
function construireListeObservations() {
890
	if (obsStation.length==0) {
891
		// premiere execution de la fonction : faire une copie des objets JSON decrivant les observations
892
		for (var index = 0; index < obsJSON.observations.length; index ++) {
893
			obsStation.push(obsJSON.observations[index]);
894
		}
895
	}
896
	pagineur.total = obsStation.length;
897
}
898
 
899
function afficherPagination() {
900
	$(".navigation").pagination(pagineur.total, {
901
		items_per_page:pagineur.limite,
902
		callback:afficherObservationsDansHTML,
903
		next_text:'Suivant',
904
		prev_text:'Précédent',
905
		prev_show_always:false,
906
		num_edge_entries:1,
907
		num_display_entries:4,
908
		load_first_page:true
909
	});
910
}
911
 
912
function afficherObservationsDansHTML(indexPage) {
913
	$("#obs-tableau-lignes").empty();
914
	if (typeof(indexPage) == 'undefined') {
915
		indexPage = 0;
916
	}
917
	var depart = indexPage * pagineur.limite;
918
	var obsPage = [];
919
	for (var index = depart; index < depart + pagineur.limite; index ++) {
920
		obsPage.push(obsStation[index]);
921
	}
922
	$("#tpl-obs-tableau").tmpl(obsPage).appendTo("#obs-tableau-lignes");
923
	mettreAJourTableauTriable();
924
}
925
 
926
function ajouterTableauTriable() {
927
	$.tablesorter.addParser({
928
		id: 'date_cel',
929
		is: function(s) {
930
			// doit retourner false si le parseur n'est pas autodétecté
931
			return /^\s*\d{2}[\/-]\d{2}[\/-]\d{4}\s*$/.test(s);
932
		},
933
		format: function(date) {
934
			// Transformation date jj/mm/aaaa en aaaa/mm/jj
935
			date = date.replace(/^\s*(\d{2})[\/-](\d{2})[\/-](\d{4})\s*$/, "$3-$2-$1");
936
			// Remplace la date par un nombre de millisecondes pour trier numériquement
937
			return $.tablesorter.formatFloat(new Date(date).getTime());
938
		},
939
		type: 'numeric'
940
	});
941
	$("#obs-tableau").tablesorter({
942
        headers: {
943
			1: {
944
            	sorter:'date_cel'
945
        	}
946
    	}
947
	});
948
}
949
 
950
function mettreAJourTableauTriable() {
951
	$("#obs-tableau").trigger('update');
952
}
953
 
954
function afficherTexteStationId() {
955
	var latitude = pointClique.getLatLng().lat.toFixed(5);
956
	var longitude = pointClique.getLatLng().lng.toFixed(5);
957
	var texteStationId = pointClique.typeSite.toUpperCase() + ':'
958
		+ latitude + '|' + longitude + ', SOURCE:' + pointClique.source;
959
	$('#obs-station-id').text(texteStationId);
960
}