Subversion Repositories eFlore/Applications.moissonnage

Rev

Rev 37 | Rev 43 | Go to most recent revision | Blame | Compare with Previous | Last modification | View Log | RSS feed

var map = null,
optionsCoucheOSM = {
        attribution: 'Map data &copy; <a href="http://openstreetmap.org">OpenStreetMap</a> contributors,'
        + ' <a href="http://creativecommons.org/licenses/by-sa/2.0/">CC-BY-SA</a>',
        maxZoom: 18
},
optionsCoucheGoogle = {
        attribution: 'Map data &copy;'+new Date().getFullYear()+' <a href="http://maps.google.com">Google</a>',
        maxZoom: 18
},
coucheOSM = new L.TileLayer("http://a.tile.openstreetmap.org/{z}/{x}/{y}.png",
        optionsCoucheOSM),
coucheRelief = new L.TileLayer("http://c.tile3.opencyclemap.org/landscape/{z}/{x}/{y}.png",
        optionsCoucheOSM),
coucheSatellite = new L.TileLayer("http://mt1.google.com/vt/lyrs=y@218131653&hl=fr&src=app&x={x}&y={y}&z={z}",
        optionsCoucheGoogle),
optionsCarte = {
        center : new L.LatLng(46, 2),
        zoom : 6,
        minZoom : 3,
        maxBounds : [[-85.051129, -180], [85.051129, 180]],
        layers : [coucheOSM]
},
zoom = 6,
legende = null,
coucheDepartement = null,
infoBulle = null;

var coucheSites = null,
sources = new Object(),
typeSite = 'maille',
overlays = [];

var requeteChargementPoints = null,
timer = null,
ancienneRequete = null,
deplacement = true,
url = '';




$(document).ready(function() {
        initialiserWidget();
});

$(window).resize(function() {
        dimensionnerCarte();
});

function initialiserWidget() {
        initialiserCarte();
        chargerLimitesCommunales();
        initialiserPanneauControle();
        initialiserSources();
        initialiserListeners();
        chargerLocalisations();
}

function initialiserCarte() {
        dimensionnerCarte();
        map = L.map('map', optionsCarte);
        coucheSatellite.addTo(map);
        coucheRelief.addTo(map);
        coucheOSM.addTo(map);
        var echelle = new L.Control.Scale({
                maxWidth : 50,
                metric : true,
                imperial : false,
                updateWhenIdle : true
        });
        map.addControl(echelle);
        zoom = map.getZoom();
}

function dimensionnerCarte() {
        $('#map').height($(window).height());
        $('#map').width($(window).width());
}

function initialiserListeners() {
        map.on('moveend', surChangementVueCarte);
        map.on('zoomend', surChangementVueCarte);
        map.on('popupclose', function(e) {
                masquerInfoBulle();
                programmerRafraichissementCarte();
        });
}

function initialiserPanneauControle() {
        var baseMaps = {
                "Satellite" : coucheSatellite,
                "Relief" : coucheRelief,
                "Plan" : coucheOSM
        };

        var overlayMaps = {};
        for (var index = 0; index < listeSources.length; index ++) {
                sources[listeSources[index]] = estValeurDansTableau(source, listeSources[index]);
                overlayMaps[listeSources[index]] = new L.LayerGroup();
        }
        L.control.layers(baseMaps, overlayMaps).addTo(map);
        coucheOSM.bringToFront();
        map.removeLayer(coucheRelief);
        map.removeLayer(coucheOSM);
        
        // garder par defaut la couche plan google comme selectionnee dans le panel
        var selecteursFonds = $('.leaflet-control-layers-base .leaflet-control-layers-selector');
        selecteursFonds[0].checked = true;
        selecteursFonds[1].checked = false;
        selecteursFonds[2].checked = false;
}

function chargerLimitesCommunales() {
        coucheDepartement = new L.KML(null, {async : true}).addTo(map);
        if (urlsLimitesCommunales != null) {
                coucheDepartement.addKMLFiles(urlsLimitesCommunales);
        }
}

function initialiserSources() {
        overlays = $('.leaflet-control-layers-overlays .leaflet-control-layers-selector');
        $.each(overlays, function (index, input) {
                input.value = listeSources[index];
                input.id = 'overlay' + (index+1);
                var lien = '<a href="' + liensVersSources[index] + '" target="_blank">' + nomListeSources[index] + '</a>';
                $('#overlay' + (index+1) + ' ~ span').html(lien);
                input.checked = sources[listeSources[index]];
                input.onclick = function(event) {
                        changerSource(event.target.value);
                }
        });
}

function changerSource(projetClique) {
        var indexProjetClique;
        for (var index = 0; index < overlays.length; index ++) {
                if (overlays[index].value == projetClique) {
                        indexProjetClique = index;
                }
        }
        masquerInfoBulle();
        sources[projetClique] = overlays[indexProjetClique].checked;
        if (sources[projetClique] == true) {
                programmerRafraichissementCarte(projetClique);
        } else {
                if (requeteEnCours()) {
                        stopperRequeteAjax();
                }
                supprimerFeaturesSource(projetClique);
        }
}

function supprimerFeaturesSource(source) {
        if (coucheSites != null) {
                coucheSites.eachLayer(function(layer) {
                        if (layer.typeSite == 'maille') {
                                retirerStationsEtObservations(layer, source);
                        } else {
                                layer.supprimerSource(source, coucheSites);
                                if (layer._map == 'null') {
                                        couheSites.removeLayer(layer);
                                }
                        }
                });
                if (typeSite == 'maille') {
                        var nombreMailles = calculerNombreMaillesVisibles();
                        if (nombreMailles == 0) {
                                coucheSites.clearLayers();
                                masquerLegende();
                                typeSite = 'point';
                        }
                }
        }
}

function retirerStationsEtObservations(maille, sourceRetrait) {
        var sources = maille.properties.source;
        var nombreStations = 0;
        for (var index = 0; index < sources.length; index ++) {
                var source = sources[index];
                if (source == sourceRetrait) {
                        delete maille.properties.stations[source];
                        delete maille.properties.observations[source];
                } else if (typeof(maille.properties.stations[source]) != 'undefined') {
                        nombreStations += parseInt(maille.properties.stations[source]);
                }
        }
        if (nombreStations == 0) {
                coucheSites.removeLayer(maille);
        } else {
                colorerMaille(maille)
                genererInfobulle(maille);               
        }
}

function calculerNombreMaillesVisibles() {
        var nombreMailles = 0;
        coucheSites.eachLayer(function(layer) {
                if($(layer._path).attr('fill-opacity') != '0') {
                        nombreMailles ++;
                }
        });
        return nombreMailles;
}

function estValeurDansTableau(tableau, valeur) {
        var index;
        for (index = 0; index < tableau.length && tableau[index] != valeur; index ++);
        return (tableau.length > 0 && index != tableau.length);
}

//************************************
// requetes stations

function surChangementVueCarte() {
        programmerRafraichissementCarte();
}

function programmerRafraichissementCarte(source) {
        $('#tooltip').css('display', 'none');
        source = (source == null || source == 'null') ? null : source;
        if (timer != null) {
                window.clearTimeout(timer);
        }
        if (requeteChargementPoints != null) {
                stopperRequeteAjax();
        }
        var nombreSourcesVisibles = 0;
        for (var index = 0; index < overlays.length; index ++) {
                if (overlays[index].checked) {
                        nombreSourcesVisibles ++;
                }
        }
        if (source == null) {
                timer = window.setTimeout("chargerLocalisations()", 100);
        } else {
                timer = window.setTimeout("chargerSource('"+source+"')", 100);
        }
}

function stopperRequeteAjax() {
        requeteChargementPoints.abort();
        requeteChargementPoints = null;
}

function chargerLocalisations() {
        if (requeteEnCours()) {
                requeteChargementPoints.abort();
        }
        afficherMessageChargement('stations');
        if (!(ancienneRequete != null && ancienneRequete[1] == map.getZoom()
                && map.getBounds().intersects(ancienneRequete[0]))) {   
                supprimerFeatures();
                deplacement = false;
        }
        var bboxRequete = calculerBboxRequete();
        var parametres = {
                "bbox" : bboxRequete,
                "zoom" : map.getZoom(),
                "source" : recupererSourcesActivees(),
                "num_taxon" : numTaxon,
                "nn" : nn,
                "referentiel" : referentiel,
                "dept" : dept,
                "auteur" : auteur,
                "date_debut" : dateDebut,
                "date_fin" : dateFin,
                "nb_jours" : nbJours
        };
        if (deplacement == true) {
                parametres.format = typeSite;
        }
        ancienneRequete = [map.getBounds(), map.getZoom()];
        url = urlBase + "stations?" + convertirEnParametresUrl(parametres);
        fonctionCallback = traiterDonneesStations;
        executerAJAX();
}

function supprimerFeatures() {
        if (coucheSites != null) {
                coucheSites.clearLayers();
                coucheSites = null;
        }
}

function recupererSourcesActivees(sourceAIgnorer) {
        sourceAIgnorer = typeof(sourceAIgnorer) == 'undefined' ? '' : sourceAIgnorer;
        var sourcesActivees = [];
        for (var index = 0; index < overlays.length; index ++) {
                if (overlays[index].checked == true && overlays[index].value != sourceAIgnorer) {
                        sourcesActivees.push(overlays[index].value);
                }
        }
        return sourcesActivees.join(',');
}

function chargerSource(sourceAjout) {
        if (requeteEnCours()) {
                requeteChargementPoints.abort();
        }
        afficherMessageChargement('stations');
        var bboxRequete = determinerCoordonneesBordure();
        var parametres = {
                "bbox" : bboxRequete,
                "zoom" : map.getZoom(),
                "format" : typeSite,
                "source" : sourceAjout,
                "num_taxon" : numTaxon,
                "nn" : nn,
                "referentiel" : referentiel,
                "dept" : dept,
                "auteur" : auteur,
                "date_debut" : dateDebut,
                "date_fin" : dateFin,
                "nb_jours" : nbJours
        };
        ancienneRequete = [map.getBounds(), map.getZoom()];
        url = urlBase + "stations?" + convertirEnParametresUrl(parametres);
        fonctionCallback = traiterRetourChargementSource;
        executerAJAX();
}

function calculerBboxRequete() {
        var bordure = map.getBounds();
        var bboxRequete = "";
        if (ancienneRequete != null && ancienneRequete[1] == map.getZoom()
                && bordure.intersects(ancienneRequete[0])) {
                bboxRequete = calculerIntersectionRectangle(ancienneRequete[0], bordure);
        } else {
                bboxRequete = determinerCoordonneesBordure();
        }
        return bboxRequete;
}

function calculerIntersectionRectangle(rectangle1, rectangle2) {
        var bbox1 = [rectangle2.getSouthWest().lng.toFixed(6), rectangle2.getSouthWest().lat.toFixed(6),
            rectangle2.getNorthEast().lng.toFixed(6), rectangle2.getNorthEast().lat.toFixed(6)];
        var bbox2 = [rectangle2.getSouthWest().lng.toFixed(6), rectangle2.getSouthWest().lat.toFixed(6),
            rectangle2.getNorthEast().lng.toFixed(6), rectangle2.getNorthEast().lat.toFixed(6)];
        
        if (rectangle2.getSouthWest().lng >= rectangle1.getSouthWest().lng
                && rectangle2.getSouthWest().lng <= rectangle1.getNorthEast().lng) {
                bbox2[0] = bbox1[2] = rectangle1.getNorthEast().lng.toFixed(6);
                if (rectangle2.getSouthWest().lat >= rectangle1.getSouthWest().lat
                        && rectangle2.getSouthWest().lat <= rectangle1.getNorthEast().lat) {
                        bbox1[1] = rectangle1.getNorthEast().lat.toFixed(6);
                } else {
                        bbox1[3] = rectangle1.getSouthWest().lat.toFixed(6);
                }
        } else {
                bbox2[0] = bbox1[2] = rectangle1.getSouthWest().lng.toFixed(6);
                if (rectangle2.getSouthWest().lat >= rectangle1.getSouthWest().lat
                        && rectangle2.getSouthWest().lat <= rectangle1.getNorthEast().lat) {
                        bbox2[1] = rectangle1.getNorthEast().lat.toFixed(6);
                } else {
                        bbox2[3] = rectangle1.getSouthWest().lat.toFixed(6);
                }
        }
        return bbox1.join(',')+'|'+bbox2.join(',');
}

function determinerCoordonneesBordure() {
        var ouest = map.getBounds().getSouthWest().lng.toFixed(6),
                sud = Math.max(map.getBounds().getSouthWest().lat, -85.051129).toFixed(6),
                est = map.getBounds().getNorthEast().lng.toFixed(6),
                nord = Math.min(map.getBounds().getNorthEast().lat, 85.051129).toFixed(6);
        // appliquer les limites possibles de la projection actuellement utilisee aux coordonnees
        // longitudes ouest et est de la bbox (permettra d'eviter de renvoyer des messages d'erreur)
        if (ouest < -180) {
                ouest += 360;
        } else if (ouest > 180) {
                ouest -= 360;
        }
        if (est < -180) {
                est += 360;
        } else if (est > 180) {
                est -= 360;
        }
        return [ouest, sud, est, nord].join(',');
}

function afficherMessageChargement(element) {
        if ($("#zone-chargement").css('display') == 'none') {
                var divTmplElement = 'tpl-chargement-' + element;
                $("#zone-chargement").append($("#" + divTmplElement).text());
                $("#zone-chargement").css('display', 'block');
        }
}

function masquerMessageChargement() {
        $("#zone-chargement").css('display', 'none');
        $("#zone-chargement").children().remove();
}

function executerAJAX() {
        if (requeteEnCours()) {
                requeteChargementPoints.abort();
        }
        requeteChargementPoints = $.getJSON(url).complete(function() {
                fonctionCallback();
        });
}

function requeteEnCours() {
        return (requeteChargementPoints != null && requeteChargementPoints.readyState != 4);
}

function estStatutRequeteOK() {
        return ((requeteChargementPoints.status == 200 || requeteChargementPoints.status == 304)
                || requeteChargementPoints.status == 0);
}

function convertirEnParametresUrl(objet) {
        var parametresUrl = '';
        for (attribut in objet) {
                if (typeof(objet[attribut]) == 'function' || typeof(objet[attribut]) == 'undefined' ||
                        objet[attribut] == null || objet[attribut] == '*' || objet[attribut] == 0)
                        continue;
                parametresUrl += (parametresUrl == '' ? '' : '&') + attribut + "=" + objet[attribut];
        }
        return parametresUrl;
};

function traiterDonneesStations() {
        masquerMessageChargement();
        masquerLegende();
        if (deplacement == true) {
                supprimerFeaturesHorsBbox();
        }
        deplacement = true;
        var texte = requeteChargementPoints.responseText;
        if (!estStatutRequeteOK()) {
                alert(texte);
        } else {
                var donneesJSON = eval("(function(){return " + texte + ";})()");
                if (donneesJSON != null && donneesJSON.features.length > 0) {
                        ajouterStationsSurCarte(donneesJSON);
                }
        }
}

function traiterRetourChargementSource() {
        masquerMessageChargement();
        var texte = requeteChargementPoints.responseText;
        if (!estStatutRequeteOK()) {
                alert(texte);
        } else {
                var donneesJSON = eval("(function(){return " + texte + ";})()");
                if (donneesJSON != null && donneesJSON.features.length > 0) {
                        var formatRetourDifferent = donneesJSON.stats.formeDonnees != typeSite;
                        ajouterStationsSurCarte(donneesJSON);
                        if (formatRetourDifferent) {
                                var sourceAIgnorer = donneesJSON.stats.source[0];
                                var sourcesARecharger = recupererSourcesActivees(sourceAIgnorer);
                                if (sourcesARecharger.length > 0) {
                                        rechargerSources(sourcesARecharger);
                                }
                        }
                }
        }
}

function supprimerFeaturesHorsBbox() {
        var bordure = map.getBounds();
        var layersRestants = 0;
        if (coucheSites != null) {
                coucheSites.eachLayer(function(layer) {
                        if (typeof(layer._latlng) != 'undefined') {
                                if (bordure.contains(layer.getLatLng())) {
                                        layersRestants ++;
                                } else {
                                        coucheSites.supprimerPoint(layer);
                                }
                        } else {
                                if (bordure.intersects(layer.getBounds())) {
                                        layersRestants ++;
                                } else {
                                        coucheSites.removeLayer(layer);
                                }
                        }
                });
        }
        if (layersRestants == 0) {
                coucheSites = null;
        }
}

function rechargerSources(sourcesARecharger) {
        var listeSourcesASupprimer = sourcesARecharger.split(',');
        for (var index = 0; index < listeSourcesASupprimer.length; index ++) {
                supprimerFeaturesSource(listeSourcesASupprimer[index]);
        }
        chargerSource(sourcesARecharger);
}

function ajouterStationsSurCarte(donnees) {
        typeSite = donnees.stats.formeDonnees;
        if (coucheSites == null) {
                coucheSites = (typeSite == 'maille') ? new L.FeatureGroup() : new L.ClusterGroup();
                map.addLayer(coucheSites);
        }
        for (var index = 0; index < donnees.features.length; index ++) {
                var feature = donnees.features[index];
                if (typeSite == 'maille') {
                        traiterMaille(feature);
                } else {
                        ajouterPoint(feature);
                }
        }
        if (donnees.features.length > 0) {
                afficherLegende();
        }
        if (typeSite == 'maille') {
                genererInfobulleMailles();
        } else {
                coucheSites.afficherClusters();
        }
}

// =========================================
// Gestion des mailles

function traiterMaille(feature) {
        var coordonnees = [];
        for (var i = 0; i < feature.geometry.coordinates.length; i++) {
                var sommet = new L.LatLng(feature.geometry.coordinates[i][0], feature.geometry.coordinates[i][1]);
                coordonnees.push(sommet);
        }
        var maille = rechercherMailleExistante(coordonnees);
        if (maille) {
                mettreAJourMaille(maille, feature);
        } else {
                maille = ajouterMaille(feature, coordonnees);
        }
        colorerMaille(maille);
}

function rechercherMailleExistante(coordonnees) {
        var mailleTrouvee = null;
        coucheSites.eachLayer(function(layer) {
                if ('typeSite' in layer && layer.typeSite == 'maille') {
                        if (sontMaillesIdentiques(coordonnees, layer._latlngs)) {
                                mailleTrouvee = layer;
                                return;
                        }
                }
        });
        return mailleTrouvee;
}

function sontMaillesIdentiques(coordonnees1, coordonnees2) {
        return (
                coordonnees1[0].lat == coordonnees2[0].lat &&
                coordonnees1[0].lng == coordonnees2[0].lng &&
                coordonnees1[2].lat == coordonnees2[2].lat &&
                coordonnees1[2].lng == coordonnees2[2].lng
        );
}

function ajouterMaille(feature, coordonnees) {
        var maille = new L.Polygon(coordonnees);
        var optionsMaille = {
                color: '#FFFFFF',
                opacity : 0.7,
                weight: 1,
                fillOpacity : 0.6
        };
        maille.setStyle(optionsMaille);
        maille.typeSite = 'maille';
        maille.properties = feature.properties;
        coucheSites.addLayer(maille);
        return maille;
}

function mettreAJourMaille(maille, feature) {
        var sources = feature.properties.source;
        for (var index = 0; index < sources.length; index ++) {
                var source = sources[index];
                maille.properties.stations[source] = parseInt(feature.properties.stations[source]);
                maille.properties.observations[source] = parseInt(feature.properties.observations[source]);
                maille.properties.source.push(source);
        }
}

function colorerMaille(maille) {
        var nombreStations = 0;
        var sources = maille.properties.source;
        for (var index = 0; index < sources.length; index ++) {
                var source = sources[index];
                if (typeof(maille.properties.stations[source]) != 'undefined') {
                        nombreStations += parseInt(maille.properties.stations[source]);
                }
        }
        if (nombreStations > 0) {
                maille.on('click', surClicMaille);
                maille.setStyle({fillColor : genererCouleur(nombreStations), fillOpacity: 0.45, opacity: 0.7});
        } else {
                maille.setStyle({fillOpacity: 0, opacity: 0});
                maille.off('click');
        }
}

function genererCouleur(nombrePoints) {
        var couleur = {'bleu': 231, 'vert': 224, 'rouge': 64},
                seuils = [1, 10, 50 ,100, 500, 1000, 2500],
                pas = 26,
                position = 0;
        for (var index = 1; index < seuils.length-1 && nombrePoints >= seuils[index]; index ++) {
                position ++;
        }
        couleur.vert -= position*pas;
        return 'rgb('+couleur.bleu+','+couleur.vert+','+couleur.rouge+')';
}

function surClicMaille(event) {
        map.fitBounds(event.layer.getBounds());
}

function afficherLegende() {
        if (legende == null) {
                legende = new L.Control({position : 'bottomright'});
                legende.onAdd = function(map) {
                        var contenuHtml = '';
                        if (typeSite == 'maille') {
                                contenuHtml = construireContenuHtmlLegendeMailles();
                        } else {
                                contenuHtml = construireContenuHtmlLegendePoints(); 
                        }
                        return contenuHtml;
                };
                map.addControl(legende);
        }
}

function construireContenuHtmlLegendeMailles() {
        var div = L.DomUtil.create('div', 'info');
        div.innerHTML = '<h4>' + titreLegende + '</h4>';
        var seuils = [1, 10, 50 ,100, 500, 1000, 2500];
        var labels = [];
        for (var i = 0; i < seuils.length; i ++) {
                div.innerHTML += 
                        '<div class="legend">'+
                                '<span class="couleur-maille" style="background:' + genererCouleur(seuils[i] + 1) + '">'+
                                '</span>'+seuils[i]+ (i + 1 < seuils.length ? '&ndash;' + seuils[i + 1] : '+')+
                        '</div>';
        }
        return div;
}

function masquerLegende() {
        if (legende != null) {
                map.removeControl(legende);
                legende = null;
        }
}

function genererInfobulleMailles() {
        coucheSites.eachLayer(function(layer) {
                if (layer.typeSite == 'maille') {
                        genererInfobulle(layer);
                }
        });
}

function genererInfobulle(maille) {
        var sources = maille.properties.source;
        var textes = new Array();
        for (var index = 0; index < sources.length; index ++) {
                var source = sources[index];
                if (typeof(maille.properties.stations[source]) != 'undefined') {
                        textes.push(source+" : "+maille.properties.stations[source]+" stations, "
                                +maille.properties.observations[source]+" observations");
                }
        }
        var contenu = textes.join('<br />');
        maille.on('mouseover', function() {
                afficherTooltip(contenu, map.latLngToContainerPoint(maille.getBounds().getSouthWest()));
        });
        maille.on('mouseout', function() {
                $("#tooltip").css('display', 'none');
        });
}

function afficherTooltip(texte, point) { 
        $("#tooltip").html(texte);
        if ($("#tooltip").css('display') == 'none') {
                var x = point.x - 15;
                var y = point.y + (typeSite == 'maille' ? 1 : 10);
                $("#tooltip").css('display', 'block');
                $("#tooltip").css('left', x + 'px');
                $("#tooltip").css('top', y + 'px');
        }
}




// ====================================================================
// Gestion des points

function ajouterPoint(feature) {
        var iconePoint = new L.Icon({ iconUrl : pointImageUrl,   iconSize : [16, 16] }),
                iconeCommune   = new L.Icon({ iconUrl : communeImageUrl, iconSize : [24, 32] }),
                icone = (feature.properties.typeSite == 'STATION') ? iconePoint : iconeCommune,
                point = new L.LatLng(feature.geometry.coordinates[0], feature.geometry.coordinates[1]);
        var marker = new L.Cluster(point, {
                icon  : icone,
                titre : feature.properties.nom
        });
        marker.typeSite = feature.properties.typeSite.toLowerCase();
        marker.source = feature.properties.source;
        marker.on('click', surClicMarqueur);
        marker.on('mouseover', function() {
                afficherTooltip(marker.options.titre, map.latLngToContainerPoint(marker.getLatLng()));
        });
        marker.on('mouseout', function() {
                $("#tooltip").css('display', 'none');
        });
        coucheSites.ajouterPoint(marker);
}

function construireContenuHtmlLegendePoints() {
        var div = L.DomUtil.create('div', 'info');
        div.innerHTML =
        '<h4>Stations</h4>'+
        '<div class="legend"><table>'+
                '<tr>'+
                        '<td class="image-station"><img src="'+communeImageUrl+'" width="24" height="32" /></td>'+
                        '<td class="label-station">Commune</td>'+
                '</tr>'+
                '<tr>'+
                        '<td class="image-station"><img src="'+pointImageUrl+'" /></td>'+
                        '<td class="label-station">Lieu précis</td>'+
                '</tr>'+
                '<tr>'+
                        '<td class="image-station"><img src="'+clusterImageUrl+'" width="20" height="20" /></td>'+
                        '<td class="label-station">Groupe de stations proches</td>'+
                '</tr>'+
        '</table></div>';
        return div;
}


function surClicMarqueur(event) {
        var nombreMarkers = event.target.recupererMarkers().length;
        if (nombreMarkers == 1 || map.getZoom() == map.getMaxZoom()) {
                recupererObservations(event.target);
        } else {
                map.setView(event.target.getLatLng(), Math.min(map.getZoom()+2, map.getMaxZoom()));
        }
}

function recupererObservations(cluster) {
        pointClique = cluster;
        var latlng = cluster.getLatLng();
        afficherMessageChargement('observations');
        var parametres = {
                "source" : recupererSourcesCluster(cluster),
                "stations" : construireListeStationsCluster(cluster),
                "num_taxon" : numTaxon,
                "nn" : nn,
                "referentiel" : referentiel,
                "auteur" : auteur,
                "date_debut" : dateDebut,
                "date_fin" : dateFin,
                "nb_jours" : nbJours
        };
        url = urlBase + "observations?" + convertirEnParametresUrl(parametres);
        fonctionCallback = traiterDonneesObservations;
        executerAJAX();
}

function recupererSourcesCluster(cluster) {
        var markers = cluster.recupererMarkers();
        var sourcesCluster = [];
        for (var index = 0; index < markers.length; index ++) {
                if (sourcesCluster.indexOf(markers[index].source) == -1) {
                        sourcesCluster.push(markers[index].source);
                }
        }
        return sourcesCluster.join(',');
}

function construireListeStationsCluster(cluster) {
        var markers = cluster.recupererMarkers();
        var listePoints = [];
        for (var index = 0; index < markers.length; index ++) {
                var latlng = markers[index].getLatLng();
                listePoints.push(markers[index].source+":"+markers[index].typeSite+":"+latlng.lng+","+latlng.lat);
        }
        return listePoints.join('|');
}

function traiterDonneesObservations() {
        masquerMessageChargement();
        var texte = requeteChargementPoints.responseText;
        if (!estStatutRequeteOK()) {
                alert(texte);
        } else {
                obsJSON = eval("(function(){return " + texte + ";})()");
                if (obsJSON != null) {
                        viderListeObservations();
                        if (obsJSON.total > 0) {
                                doitRafraichirCarte = false;
                                map.setView(new L.LatLng(pointClique.getLatLng().lat, pointClique.getLatLng().lng), map.getZoom());
                                afficherInfoBulle();
                        } else if (infoBulle != null)  {
                                masquerInfoBulle();
                        }
                }
        }
}




// ====================================================================
// Gestion de l'infobulle

var obsJSON = null,
        pointClique = null,
        obsStation = [],
        pagineur = {'limite':100, 'start':0, 'total':0, 'stationId':null, 'format':'tableau'};

function afficherInfoBulle() {
        var latitude = pointClique.getLatLng().lat;
        var longitude = pointClique.getLatLng().lng;
        infoBulle = new L.Popup({maxWidth : definirLargeurInfoBulle(), maxHeight : 380});
        infoBulle.setLatLng(new L.LatLng(latitude, longitude));
        infoBulle.setContent($("#tpl-obs").html());
        infoBulle.openOn(map);
        remplirContenuPopup();
        $('#info-bulle').css('width', '99%');
        $('#observations').css('height', '250px');
        $('#observations').css('overflow', 'auto');
        $('.leaflet-popup-scrolled').css('overflow', 'visible');
}

function viderListeObservations() {
        obsStation = new Array();
}

function definirLargeurInfoBulle() {
        var largeurViewPort = $(window).width();
        var lageurInfoBulle = null;
        if (largeurViewPort < 800) {
                largeurInfoBulle = 400;
        } else if (largeurViewPort >= 800 && largeurViewPort < 1200) {
                largeurInfoBulle = 500;
        } else if (largeurViewPort >= 1200) {
                largeurInfoBulle = 600;
        }
        return largeurInfoBulle;
}

function redimensionnerPopup() {
        $('.leaflet-popup-content*').css('width', definirLargeurInfoBulle());
        $('#info-bulle').css('width', '99%');
}

function remplirContenuPopup() {
        ajouterTableauTriable("#obs-tableau");
        ajouterTitre();
        afficherTableau();
        afficherTexteStationId();
}

function masquerInfoBulle() {
        if (infoBulle != null && map.hasLayer(infoBulle)) {
                map.removeLayer(infoBulle);
        }
        infoBulle = null;
}

function ajouterTitre() {
        var texteStationTitre = obsJSON.total + ' observation' + (obsJSON.total > 1 ? 's' : '')
                + ' sur ' + (pointClique.typeSite=='station' ? 'la station : ' : 'la commune : ')
                + pointClique.options.title;
        $('#obs-station-titre').text(texteStationTitre);
}

function afficherTableau() {
        construireListeObservations();
        afficherPagination();
        afficherObservationsDansHTML();
}

function construireListeObservations() {
        if (obsStation.length==0) {
                // premiere execution de la fonction : faire une copie des objets JSON decrivant les observations 
                for (var index = 0; index < obsJSON.observations.length; index ++) {
                        obsStation.push(obsJSON.observations[index]);
                }
        }
        pagineur.total = obsStation.length;
}

function afficherPagination() {
        $(".navigation").pagination(pagineur.total, {
                items_per_page:pagineur.limite,
                callback:afficherObservationsDansHTML,
                next_text:'Suivant',
                prev_text:'Précédent',
                prev_show_always:false,
                num_edge_entries:1,
                num_display_entries:4,
                load_first_page:true
        });
}

function afficherObservationsDansHTML(indexPage) {
        $("#obs-tableau-lignes").empty();
        if (typeof(indexPage) == 'undefined') {
                indexPage = 0;
        }
        var depart = indexPage * pagineur.limite;
        var obsPage = [];
        for (var index = depart; index < depart + pagineur.limite; index ++) {
                obsPage.push(obsStation[index]);
        }
        $("#tpl-obs-tableau").tmpl(obsPage).appendTo("#obs-tableau-lignes");
        mettreAJourTableauTriable();
}

function ajouterTableauTriable() {
        $.tablesorter.addParser({ 
                id: 'date_cel', 
                is: function(s) { 
                        // doit retourner false si le parseur n'est pas autodétecté
                        return /^\s*\d{2}[\/-]\d{2}[\/-]\d{4}\s*$/.test(s);
                }, 
                format: function(date) { 
                        // Transformation date jj/mm/aaaa en aaaa/mm/jj
                        date = date.replace(/^\s*(\d{2})[\/-](\d{2})[\/-](\d{4})\s*$/, "$3-$2-$1");
                        // Remplace la date par un nombre de millisecondes pour trier numériquement
                        return $.tablesorter.formatFloat(new Date(date).getTime());
                }, 
                type: 'numeric' 
        });
        $("#obs-tableau").tablesorter({ 
        headers: { 
                        1: { 
                sorter:'date_cel'
                } 
        }
        });
}

function mettreAJourTableauTriable() {
        $("#obs-tableau").trigger('update');
}

function afficherTexteStationId() {
        var latitude = pointClique.getLatLng().lat.toFixed(5);
        var longitude = pointClique.getLatLng().lng.toFixed(5);
        var texteStationId = pointClique.typeSite.toUpperCase() + ':'
                + latitude + '|' + longitude + ', SOURCE:' + pointClique.source;
        $('#obs-station-id').text(texteStationId);
}