Subversion Repositories eFlore/Applications.moissonnage

Rev

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

// Javascript Document


// ===================================================================================
//  FONCTIONS ADDITIONNELLES POUR GERER LES URLS ET L'OUVERTRURE DE NOUVELLE FENETRE
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 recupererParametreDansUrl(nomParametre, chaineRecherche) {
        var split = chaineRecherche.split('?');
        chaineRecherche = split[split.length-1];
        var valeurParametre = null;
        var listeParametres = chaineRecherche.split("&");
        for (var index = 0; index < listeParametres.length; index ++) {
                var split = listeParametres[index].split("=");
                if (split[0] == nomParametre) {
                        valeurParametre = split[1];
                        break;
                }
        }
        return valeurParametre;
};

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

function ouvrirNouvelleFenetre(element, event) {
        window.open(element.href);
        return arreter(event);
}

function arreter(event) {
        if (event.stopPropagation) {
                event.stopPropagation();
        } else if (window.event) {
                window.event.cancelBubble = true;
        }
        if (event.preventDefault) {
                event.preventDefault();
        }
        event.returnValue = false;
        return false;
}



// =============================================================

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://{s}.tile.openstreetmap.org/{z}/{x}/{y}.png",
        optionsCoucheOSM),
couchePlanGoogle = new L.TileLayer("http://mt1.google.com/vt/lyrs=m&x={x}&y={y}&z={z}",
        optionsCoucheGoogle),
coucheSatelliteGoogle = new L.TileLayer("http://mt1.google.com/vt/lyrs=y&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 = new L.FeatureGroup(),
points = new Array(),
coucheSites = new L.FeatureGroup(),
sources = new Object(),
formeDonnees = '',
popupMaille = null;
overlays = [];

var requeteChargementPoints = null,
        chargementMaillesEnCours = false,
doitRafraichirCarte = true,
chargementCommunesEnCours = false,
timer = null,
url = '';




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

function initialiserWidget() {
        initialiserCarte();
        dimensionnerOverlay();
        initialiserPanneauControle();
        initialiserSources();
        initialiserListeners();
        chargerLimitesCommunales();
        chargerMaillesVides();
        programmerRafraichissementCarte();
}

$(window).resize(function() {
        dimensionnerCarte();
        if (infoBulle != null) {
                redimensionnerPopup();
        }
});

function dimensionnerOverlay() {
        var taille = '1.6';
        var tailleMaxIcones = 20;
        var padding_icones = 8;
        $("#zone-titre h1").css('font-size', (taille)+'em');
        $("#zone-titre").css('padding', padding_icones+"px "+padding_icones+"px "+Math.round(padding_icones/4)+"px");   
        $('#zone-titre').height(tailleMaxIcones*2);
        var left = ($(window).width()-$('#zone-titre').width())/2;
        $('#zone-titre').css('left',left);
}


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

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

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

function initialiserPanneauControle() {
        var baseMaps = {
                "OpenStreetMap" : coucheOSM,
                "Plan" : couchePlanGoogle,
                "Satellite" : coucheSatelliteGoogle
        };

        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();
        couchePlanGoogle.bringToBack();
        coucheSatelliteGoogle.bringToBack();
        
        // 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 determinerSourcesSelectionnees() {
        var sourcesSelectionnees = new Array();
        for (source in sources) {
                if (sources[source] == true) {
                        sourcesSelectionnees.push(source);
                }
        }
        return sourcesSelectionnees;
}

function surChangementVueSurCarte() {
        if (doitRafraichirCarte == false) {
                doitRafraichirCarte = true;
        } else {
                supprimerTousLayers();
                zoom = map.getZoom();
                chargerMaillesVides();
        }
}

function chargerMaillesVides() {
        chargementMaillesEnCours = true;
        if (timer != null) {
        window.clearTimeout(timer);
    }   
        if (requeteChargementPoints != null) {
                stopperRequeteAjax();
        }
        timer = window.setTimeout(function() {
                var coordonneesBordure = calculerCoordonneesBordure();
                var parametres = {
                                "source" : "floradata",
                                "bbox" : coordonneesBordure,
                                "zoom" : map.getZoom()
                        };
                        url = urlBase + "mailles?" + convertirEnParametresUrl(parametres);
                        fonctionCallback = traiterDonneesStations;
                        executerAJAX();
        }, 400);
}

function programmerRafraichissementCarte(source) {
        source = (source == null || source == 'null') ? null : source;
        if (!chargementMaillesEnCours) {
                if (timer != null) {
                        window.clearTimeout(timer);
                }
                if (requeteChargementPoints != null) {
                        if (source == null) {
                                stopperRequeteAjax();
                        }
                }
                timer = window.setTimeout("rafraichirDonnnees('"+source+"')", 250);
    } else {
        window.setTimeout("programmerRafraichissementCarte('"+source+"')", 400);
    }
}

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

function rafraichirDonnnees(source) {
        source = (source == null || source == 'null') ? null : source;
        if (coucheDepartement == null || coucheDepartement.getStatus() == KML_READY) {
                if (source != null) {
                        chargerLocalisations(source);
                } else {
                        supprimerLocalisations();
                        for (source in sources) {
                                if (sources[source] == true) {
                                        chargerLocalisations(source);
                                }
                        }
                }
        } else {
                window.setTimeout("rafraichirDonnnees('"+source+"')", 800);
        }
}

function supprimerTousLayers() {
        coucheSites.clearLayers();
        points = [];
        formeDonnees = '';
}

function supprimerLocalisations(source) {
        source = (typeof(source) == 'undefined') ? null : source;
        if (source != null) {
                var sourceUrl = recupererParametreDansUrl('source', url);
                if (requeteChargementPoints != null && sourceUrl == source && source != null) {
                        stopperRequeteAjax();
                }
                coucheSites.eachLayer(function(layer) {
                        supprimerLayer(layer, source);
                });
                if (source != null) {
                        supprimerPointsListe(source);
                }
                var sourcesSelectionnees = determinerSourcesSelectionnees();
                if (sourcesSelectionnees.length == 1 && determinerNombreMarqueurs(sourcesSelectionnees[0]) > 0) {
                        transformerMaillesEnPoints(sourcesSelectionnees[0]);
                }
                var sontPointsAffiches = (points.length>0 && determinerNombreMailles(false)==0);
                formeDonnees = sontPointsAffiches ? 'point' : 'maille';
        }
}

function estLayerUtilisePourSource(layer, source) {
        return (
                (layer.typeSite == 'MAILLE' && typeof(layer.nombrePoints[source]) != 'undefined') ||
                (layer.typeSite != 'MAILLE' && layer.source == source)
        );
}

function supprimerLayer(layer, source) {
        if (estLayerUtilisePourSource(layer, source)) {
                if (layer.typeSite == 'MAILLE') {
                        supprimerSourceDansMaille(layer, source);
                } else {
                        coucheSites.removeLayer(layer);
                }
        }
}


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 {
                supprimerLocalisations(projetClique);
        }
}

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();
}


// execution d'une requete AJAX
function executerAJAX() {
        if (requeteEnCours()) {
                masquerMessageChargement();
                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 chargerLocalisations(source) {
        if (requeteEnCours()) {
                window.setTimeout("chargerLocalisations('"+source+"')", 400);
        } else {
                afficherMessageChargement('stations');
                // generer l'URL du script a interroger sur le serveur
                var coordonneesBordure = calculerCoordonneesBordure();
                var parametres = {
                        "source" : source,
                        "num_taxon" : numTaxon,
                        "referentiel" : referentiel,
                        "dept" : dept,
                        "nn" : nn,
                        "auteur" : auteur,
                        "date_debut" : dateDebut,
                        "date_fin" : dateFin,
                        "bbox" : coordonneesBordure,
                        "nb_jours" : nbJours,
                        "zoom" : map.getZoom()
                };
                url = urlBase + "stations?" + convertirEnParametresUrl(parametres);
                fonctionCallback = traiterDonneesStations;
                executerAJAX();
        }
}

function calculerCoordonneesBordure() {
        var bordure = map.getBounds();
        var ouest = bordure.getSouthWest().lng.toFixed(6),
                sud = Math.max(bordure.getSouthWest().lat, -85.051129).toFixed(6),
                est = bordure.getNorthEast().lng.toFixed(6),
                nord = Math.min(bordure.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 traiterDonneesStations() {
        masquerMessageChargement();
        var texte = requeteChargementPoints.responseText;
        if (!estStatutRequeteOK()) {
                alert(texte);
        } else {
                var donneesJSON = eval("(function(){return " + texte + ";})()");
                if (donneesJSON != null && typeof(donneesJSON.features) != 'undefined') {
                        ajouterStationsSurCarte(donneesJSON);
                }
        }
}

function ajouterStationsSurCarte(data) {
        if (doitTransformerEnMaille(data.stats)) {
                if (points.length > 0 && data.stats.source != '') {
                        combinerMaillesEtPoints();
                }
                formeDonnees = 'maille';
        } else {
                formeDonnees = data.stats.formeDonnees;
        }
        var sourceDonnees = data.stats.source;
        for (var index = 0; index < data.features.length; index ++) {
                ajouterStation(data.features[index]);
        }
        if (formeDonnees == 'maille' && data.stats.sites > 0) {
                afficherLegende();
                regenererInfobulleMailles();
        } else {
                masquerLegende();
        }
        if (chargementMaillesEnCours) {
                chargementMaillesEnCours = false;
                programmerRafraichissementCarte();
        }
}

function ajouterStation(feature) {
        if (feature.properties.typeSite == 'MAILLE') {
                traiterMaille(feature);
        } else {
                ajouterPoint(feature);
        }
}

function doitTransformerEnMaille(statsFeatures) {
        var condition1 = (formeDonnees == 'point' && statsFeatures.formeDonnees =='maille');
        var condition2 = (formeDonnees == 'maille' && statsFeatures.formeDonnees =='point'
                && determinerNombreMailles(false) > 0);
        var condition3 = (statsFeatures.formeDonnees == 'point' && map.getZoom() <= ZOOM_MAXIMUM_MAILLAGE
                && (points.length+statsFeatures.sites) > SEUIL_MAILLAGE);
        return (condition1 || condition2 || condition3);
}



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

var optionsMaille = {
        color: '#FFFFFF',
        opacity : 0.7,
        weight: 1,
        fillOpacity : 0.6
};

function determinerNombreMailles(prendToutesMailles) {
        var nombreMailles = 0;
        coucheSites.eachLayer(function(layer) {
                if ('typeSite' in layer && layer.typeSite == 'MAILLE') {
                        var nombrePoints = 0;
                        for (var source in layer.nombrePoints) {
                                nombrePoints = layer.nombrePoints[source];
                        }
                        if (prendToutesMailles || nombrePoints>0) {
                                nombreMailles ++;
                        }
                }
        });
        return nombreMailles;
}

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 if (feature.properties.nombrePoints > 0) {
                ajouterMaille(feature);
        }
}

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) {
        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 = new L.Polygon(coordonnees);
        maille.setStyle(optionsMaille);
        maille.typeSite = feature.properties.typeSite;
        maille.nombrePoints = new Object();
        var nombreAAjouter = feature.properties.nombrePoints == null ? 0 : parseInt(feature.properties.nombrePoints);
        maille.nombrePoints[feature.properties.source] = nombreAAjouter;
        coucheSites.addLayer(maille);
        colorerMaille(maille);
}

function mettreAJourMaille(maille, feature) {
        var nombreAAjouter = feature.properties.nombrePoints == null ? 0 : parseInt(feature.properties.nombrePoints);
        /*if (typeof(maille.nombrePoints[feature.properties.source]) == 'undefined') {
                maille.nombrePoints[feature.properties.source] = nombreAAjouter;
        } else {
                maille.nombrePoints[feature.properties.source] += nombreAAjouter;
        }*/
        maille.nombrePoints[feature.properties.source] = nombreAAjouter;
        colorerMaille(maille);
}

function regenererInfobulleMailles() {
        $('.leaflet-clickable').addClass('tooltip');
        coucheSites.eachLayer(function(layer) {
                if (layer.typeSite == 'MAILLE') {
                        genererInfobulle(layer);
                }
        });
}

function colorerMaille(maille) {
        var nombrePoints = 0;
        for (sourceMaille in maille.nombrePoints) {
                nombrePoints += maille.nombrePoints[sourceMaille];
        }
        if (nombrePoints > 0) {
                maille.on('click', surClicMaille);
                maille.setStyle({fillColor : genererCouleur(nombrePoints), fillOpacity: 0.45, opacity: 0.7});
        } else {
                maille.setStyle({fillOpacity: 0, opacity: 0});
                maille.off('click', surClicMaille);
        }
}

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

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 afficherLegende() {
        if (legende == null) {
                legende = new L.Control({position : 'bottomright'});
                legende.onAdd = function(map) {
                        return construireContenuHtmlLegende();
                };
                map.addControl(legende);
        }
}

function construireContenuHtmlLegende() {
        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 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 supprimerSourceDansMaille(maille, sourceSuppression) {
        if (typeof(maille.nombrePoints[sourceSuppression]) != 'undefined') {
                maille.nombrePoints[sourceSuppression] = 0;
                colorerMaille(maille);
                genererInfobulle(maille);
        }
}

function genererInfobulle(maille) {
        var nombrePoints = 0,
                nombreSources = 0;
                contenuTexte = '';
        for (sourceMaille in maille.nombrePoints) {
                nombrePoints = maille.nombrePoints[sourceMaille];
                if (nombrePoints > 0) {
                        contenuTexte += (contenuTexte.length==0 ?'' : '\n')+
                                sourceMaille+' : '+maille.nombrePoints[sourceMaille];
                }
                nombreSources ++;
        }
        if (nombreSources > 0) {
                $(maille._path).addClass('tooltip');
                $(maille._path).attr('title',contenuTexte);
        }
}




// ====================================================================
// Gestion des marqueurs

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]),
                marker = new L.Marker(point, {
                        icon  : icone,
                        title : feature.properties.nom
                })
        marker.typeSite = feature.properties.typeSite;
        marker.source = feature.properties.source;
        marker.on('click', surClicMarqueur);
        points.push(marker);
        if (formeDonnees != 'maille') {
                coucheSites.addLayer(marker);
        } else {
                ajouterPointDansMaille(marker);
        }
}

function ajouterPointDansMaille(point) {
        var maille = null;
        coucheSites.eachLayer(function(layer) {
                if (layer.typeSite == 'MAILLE' && layer.getBounds().contains(point.getLatLng())) {
                        maille = layer;
                        return;
                }
        });
        if (typeof(maille.nombrePoints[point.source]) == 'undefined') {
                maille.nombrePoints[point.source] = 1;
        } else {
                maille.nombrePoints[point.source] += 1;
        }
        colorerMaille(maille);
}

function combinerMaillesEtPoints() {
        enleverMarqueursCarte();
        coucheSites.eachLayer(function(layer) {
                if (layer.typeSite == 'MAILLE') {
                        var nombrePoints = compterNombrePointsDansMaille(layer);
                        ajouterNombrePointsDansMaille(layer, nombrePoints);
                }
        });
}

function determinerNombreMarqueurs(source) {
        var nombrePoints = 0;
        for (var index = 0; index < points.length; index ++) {
                if (points[index].source == source) {
                        nombrePoints += 1;
                }
        }
        return nombrePoints;
}

function enleverMarqueursCarte() {
        coucheSites.eachLayer(function(layer) {
                if (layer.typeSite != 'MAILLE') {
                        coucheSites.removeLayer(layer);
                }
        });
}

function compterNombrePointsDansMaille(maille) {
        var nombrePoints = {};
        for (var index = 0; index < points.length; index ++) {
                if (maille.getBounds().contains(points[index].getLatLng())) {
                        var source = points[index].source;
                        if (typeof(nombrePoints[source]) == 'undefined') {
                                nombrePoints[source] = 1;
                        } else {
                                nombrePoints[source] += 1;
                        }
                }
        }
        return nombrePoints;
}

function ajouterNombrePointsDansMaille(maille, nombrePoints) {
        for (sourceDonnees in nombrePoints) {
                if (typeof(maille.nombrePoints[sourceDonnees]) == 'undefined') {
                        maille.nombrePoints[sourceDonnees] = nombrePoints[sourceDonnees];
                } else {
                        maille.nombrePoints[sourceDonnees] += nombrePoints[sourceDonnees];
                }
        }
        colorerMaille(maille);
}

function supprimerPointsListe(sourceDonnees) {
        var index = 0;
        while (index < points.length) {
                if (points[index].source == sourceDonnees) {
                        points.splice(index, 1);
                } else {
                        index ++;
                }
        }
}

function transformerMaillesEnPoints(sourceDonnees) {
        coucheSites.eachLayer(function(layer) {
                if (layer.typeSite == 'MAILLE' && typeof(layer.nombrePoints[sourceDonnees]) != 'undefined') {
                        supprimerSourceDansMaille(layer, sourceDonnees);
                }
        });
        for (var index = 0; index < points.length; index ++) {
                coucheSites.addLayer(points[index]);
        }
}

function surClicMarqueur(event) {
        var latitude = event.target.getLatLng().lat;
        var longitude = event.target.getLatLng().lng;
        pointClique = event.target;
        afficherMessageChargement('observations');
        var parametres = {
                "source" : pointClique.source,
                "num_taxon" : numTaxon,
                "referentiel" : referentiel,
                "auteur" : auteur,
                "nn" : nn,
                "type_site" : pointClique.typeSite,
                "date_debut" : dateDebut,
                "date_fin" : dateFin,
                "longitude" : longitude,
                "latitude" : latitude,
                "nb_jours" : nbJours
        };
        url = urlBase + "observations?" + convertirEnParametresUrl(parametres);
        fonctionCallback = traiterDonneesObservations;
        executerAJAX();
}

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();
                        }
                }
        }
}

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




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

var obsJSON = null,
        pointClique = null,
        obsStation = [],
        typeAffichage = "";

function afficherInfoBulle() {
        var latitude = pointClique.getLatLng().lat;
        var longitude = pointClique.getLatLng().lng;
        infoBulle = new L.Popup({maxWidth : definirLargeurInfoBulle(), maxHeight : 350});
        infoBulle.setLatLng(new L.LatLng(latitude, longitude));
        infoBulle.setContent($("#tpl-obs").html());
        infoBulle.openOn(map);  
        remplirContenuPopup();
}

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',  definirLargeurInfoBulle());
}

function remplirContenuPopup() {
        ajouterTableauTriable("#obs-tableau");
        ajouterTitre();
        afficherOnglets();
        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' : '')
                + ' pour ' + (pointClique.options.type=='STATION' ? 'la station : ' : 'la commune : ')
                + pointClique.options.title;
        $('#obs-station-titre').text(texteStationTitre);
}

function selectionnerOnglet() {
        $("#obs-vue-" + typeAffichage).css("display", "block");
        $('#obs-tableau-lignes').empty();
        $('#obs-liste-lignes').empty();
        if (typeAffichage=='liste') {
                $("#obs-vue-tableau").css("display", "none");
        } else {
                $("#obs-vue-liste").css("display", "none");
        }
}

function ajouterObservationsDansHTML() {
        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]);
                }
        }
        var obsPage = [];
        for (var index = 0; index < obsStation.length; index ++) {
                obsPage.push(obsStation[index]);
        }
        $("#tpl-obs-"+typeAffichage).tmpl(obsPage).appendTo("#obs-"+typeAffichage+"-lignes");
}

function afficherOnglets() {
        var $tabs = $('#obs').tabs();
        $('#obs').bind('tabsselect', function(event, ui) {
                if (ui.panel.id == 'obs-vue-tableau') {
                        surClicAffichageTableau();
                } else if (ui.panel.id == 'obs-vue-liste') {
                        surClicAffichageListe();
                }
        });
        if (obsJSON.total > 4) {
                surClicAffichageTableau();
        } else {
                $tabs.tabs('select', "#obs-vue-liste");
        }
}

function surClicAffichageTableau() {
        typeAffichage = 'tableau';
        selectionnerOnglet();
        ajouterObservationsDansHTML();
        mettreAJourTableauTriable("#obs-tableau");
}

function surClicAffichageListe() {
        typeAffichage = 'liste';
        selectionnerOnglet();
        ajouterObservationsDansHTML();
}

function ajouterTableauTriable(element) {
        $.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' 
        });
        $(element).tablesorter({ 
        headers: { 
                        1: { 
                sorter:'date_cel' 
                } 
        }
        });
}

function mettreAJourTableauTriable(element) {
        $(element).trigger('update');
}

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