Subversion Repositories eFlore/Applications.cel

Rev

Rev 2408 | Blame | Last modification | View Log | RSS feed

//+---------------------------------------------------------------------------------------------------------+
// GÉNÉRAL
$(document).ready(function() {
        if (DEBUG == false) {
                $(window).on('beforeunload', function(event) {
                        return 'Êtes vous sûr de vouloir quiter la page?\nLes observations saisies mais non transmises seront perdues.';
                });
        }
});
//+----------------------------------------------------------------------------------------------------------+
// FONCTIONS GÉNÉRIQUES
/**
 * Stope l'évènement courrant quand on clique sur un lien.
 * Utile pour Chrome, Safari...
 * @param evenement
 * @return
 */
function arreter(evenement) {
        if (evenement.stopPropagation) {
                evenement.stopPropagation();
        }
        if (evenement.preventDefault) {
                evenement.preventDefault();
        }
        return false;
}

function extraireEnteteDebug(jqXHR) {
        var msgDebug = '';
        if (jqXHR.getResponseHeader('X-DebugJrest-Data') != '') {
                var debugInfos = jQuery.parseJSON(jqXHR.getResponseHeader('X-DebugJrest-Data'));
                if (debugInfos != null) {
                        $.each(debugInfos, function (cle, valeur) {
                                msgDebug += valeur + "\n";
                        });
                }
        }
        return msgDebug;
}

function afficherPanneau(selecteur) {
        $(selecteur).fadeIn('slow').delay(DUREE_MESSAGE).fadeOut('slow');
}

//+----------------------------------------------------------------------------------------------------------+
// PRÉCHARGEMENT DU FORMULAIRE
var latLngDebPre = {lat: null, lng: null},
        latLngFinPre = {lat: null, lng: null},
        okPourChargementCarte = 2;

$(document).ready(function() {
        if (OBS_ID != '') {
                chargerInfoObs();
        }
});

function chargerInfoObs() {
        var urlObs = SERVICE_OBS_URL + '/' + OBS_ID;
        $.ajax({
                url: urlObs,
                type: 'GET',
                success: function(data, textStatus, jqXHR) {
                        if (data != undefined) {
                                prechargerForm(data);
                        } else {
                                surErreurChargementInfosObs();
                        }
                },
                error: function(jqXHR, textStatus, errorThrown) {
                        surErreurChargementInfosObs();
                }
        });
}

function prechargerForm(infos) {
        $('input[name="station"]').val(infos.station);

        //console.log(infos.extension);
        if (infos.extension) {
                var ext = infos.extension;
                if (ext.latitudeDebutRue && ext.longitudeDebutRue && ext.latitudeFinRue && ext.longitudeFinRue) {
                        okPourChargementCarte--;
                        latLngDebPre.lat = parseFloat(ext.latitudeDebutRue.valeur);
                        latLngDebPre.lng = parseFloat(ext.longitudeDebutRue.valeur);
                        latLngFinPre.lat = parseFloat(ext.latitudeFinRue.valeur);
                        latLngFinPre.lng = parseFloat(ext.longitudeFinRue.valeur);
                        prechargerRue();
                }

                var chpsARemplir = ['adresse', 'typoUrbaine', 'revetementSol', 'presenceZoneVegetalise', 'hauteurBatimentAvoisinant',
                        'intensiteGestion', 'periodiciteTraitementPhyto', 'dateArretTraitementPhyto', 'itineraireGestion'];
                $.each(infos.extension, function(nomDuChp, value) {
                        if (chpsARemplir.indexOf(nomDuChp) >= 0) {
                                if ($('[name="' + nomDuChp + '"]').hasClass('slider')) {
                                        $('select[name="' + nomDuChp + '"] option[value="' + value.valeur + '"]')
                                                .attr('selected', 'selected');
                                        var selectedIndexOptions = $('select[name="' + nomDuChp + '"]').prop('selectedIndex') + 1;
                                        $('[name="' + nomDuChp + '"]').parent().find('.horizontal-slider').slider('value', selectedIndexOptions);

                                        if (nomDuChp == 'periodiciteTraitementPhyto') {
                                                $('[name="periodiciteTraitementPhyto"]').trigger('change');
                                        }
                                } else {
                                        $('[name="' + nomDuChp + '"]').val(value.valeur);
                                }
                        }
                });
        }
}

function prechargerRue() {
        //console.log('okPourChargementCarte : '+okPourChargementCarte);
        if (okPourChargementCarte == 0) {
                latLngDeb = new google.maps.LatLng(latLngDebPre.lat, latLngDebPre.lng);
                markerDeb = undefined;
                initialiserMarkerDeb();
                deplacerMarkerDeb(latLngDeb);
                premierDeplacement = false;
                markerFin = undefined;
                latLngFin = new google.maps.LatLng(latLngFinPre.lat, latLngFinPre.lng);
                initialiserMarkerFin();
                deplacerMakerFin(latLngFin)
                surDeplacementMarkerFin();
                map.setZoom(16);
        }
}

//+----------------------------------------------------------------------------------------------------------+
//FORM IDENTITE : gestion de l'observateur

$(document).ready(function() {
        requeterIdentite();// Sur rechargement de la page

        // Interaction sur le formulaire observateur
        $('#prenom').on('change', formaterPrenom);
        $('#nom').on('change', formaterNom);
        $('#courriel').on('blur', requeterIdentite);
        $('#courriel').on('keyup', testerLancementRequeteIdentite);
        $('#courriel_confirmation').on('paste', bloquerCopierCollerCourriel);
});

function testerLancementRequeteIdentite(event) {
        if (event.which == 13) {
                requeterIdentite();
                event.preventDefault();
                event.stopPropagation();
        }
}

function requeterIdentite() {
        var courriel = $('#courriel').val();
        if (courriel) {
                var urlAnnuaire = SERVICE_ANNUAIRE_ID_URL + courriel;
                $.ajax({
                        url: urlAnnuaire,
                        type: 'GET',
                        success: function(data, textStatus, jqXHR) {
                                if (data != undefined && data[courriel] != undefined) {
                                        var infos = data[courriel];
                                        $('#id_utilisateur').val(infos.id);
                                        $('#prenom').val(infos.prenom);
                                        $('#nom').val(infos.nom);
                                        $('#courriel_confirmation').val(courriel);
                                        $('#prenom, #nom, #courriel_confirmation').attr('disabled', 'disabled');
                                        $('#structure').focus();
                                } else {
                                        surErreurCompletionCourriel();
                                }
                        },
                        error: function(jqXHR, textStatus, errorThrown) {
                                surErreurCompletionCourriel();
                        },
                        complete: function(jqXHR, textStatus) {
                                $('#zone-courriel-confirmation, #zone-prenom-nom').removeClass('hidden');
                        }
                });
        }
}

function surErreurCompletionCourriel() {
        $('#prenom, #nom, #courriel_confirmation').removeAttr('disabled');
        afficherPanneau('#dialogue-courriel-introuvable');
}

function formaterNom() {
        $(this).val($(this).val().toUpperCase());
}

function formaterPrenom() {
        var prenom = new Array(),
                mots = $(this).val().split(' ');
        for (var i = 0; i < mots.length; i++) {
                var mot = mots[i];
                if (mot.indexOf('-') >= 0) {
                        var prenomCompose = new Array(),
                                motsComposes = mot.split('-');
                        for (var j = 0; j < motsComposes.length; j++) {
                                var motSimple = motsComposes[j],
                                        motMajuscule = motSimple.charAt(0).toUpperCase() + motSimple.slice(1);
                                prenomCompose.push(motMajuscule);
                        }
                        prenom.push(prenomCompose.join('-'));
                } else {
                        var motMajuscule = mot.charAt(0).toUpperCase() + mot.slice(1);
                        prenom.push(motMajuscule);
                }
        }
        $(this).val(prenom.join(' '));
}

function bloquerCopierCollerCourriel() {
        afficherPanneau('#dialogue-bloquer-copier-coller');
        return false;
}

//+----------------------------------------------------------------------------------------------------------+
// GOOGLE MAP

var map,
        geocoder,
        markerDeb,
        latLngDeb,
        markerFin,
        latLngFin,
        ligneRue,
        premierDeplacement = true;

$(document).ready(function() {
        initialiserGoogleMap();
        afficherEtapeGeolocalisation(1);

        // Autocompletion du champ adresse
        $('#carte-recherche').on('focus', function() {
                $(this).select();
        });
        $('#carte-recherche').on('mouseup', function(event) {// Pour Safari...
                event.preventDefault();
        });

        $('#carte-recherche').keypress(function(e) {
                if (e.which == 13) {
                        e.preventDefault();
                }
        });

        $('#carte-recherche').autocomplete({
                //Cette partie utilise geocoder pour extraire des valeurs d'adresse
                source: function(request, response) {

                        geocoder.geocode( {'address': request.term+', France', 'region' : 'fr' }, function(results, status) {
                                if (status == google.maps.GeocoderStatus.OK) {
                                        response($.map(results, function(item) {
                                                var retour = {
                                                        label: item.formatted_address,
                                                        value: item.formatted_address,
                                                        latitude: item.geometry.location.lat(),
                                                        longitude: item.geometry.location.lng()
                                                };
                                                return retour;
                                        }));
                                } else {
                                        afficherErreurGoogleMap(status);
                                }
                        });
                },
                // Cette partie est executee a la selection d'une adresse
                select: function(event, ui) {
                        var nouvellePosition = new google.maps.LatLng(ui.item.latitude, ui.item.longitude);
                        initialiserMarkerDeb();
                        deplacerMarkerDeb(nouvellePosition);
                        map.setZoom(16);
                        afficherEtapeGeolocalisation(2);
                }
        });

        $('#geolocaliser').on('click', geolocaliser);
});

function initialiserGoogleMap(){
        latLngDeb = new google.maps.LatLng(46.30871, 2.54395);// Centre de la France
        var options = {
                        zoom: 5,
                        center: latLngDeb,
                        mapTypeId: google.maps.MapTypeId.HYBRID,
                        mapTypeControlOptions: {
                                mapTypeIds: ['OSM',
                                        google.maps.MapTypeId.ROADMAP,
                                        google.maps.MapTypeId.HYBRID,
                                        google.maps.MapTypeId.SATELLITE,
                                        google.maps.MapTypeId.TERRAIN]}
                };

        // Ajout de la couche OSM à la carte
        osmMapType = new google.maps.ImageMapType({
                getTileUrl: function(coord, zoom) {
                        return 'http://tile.openstreetmap.org/' + zoom + '/' + coord.x + '/' + coord.y + '.png';
                },
                tileSize: new google.maps.Size(256, 256),
                isPng: true,
                alt: 'OpenStreetMap',
                name: 'OSM',
                maxZoom: 19
        });

        // Création de la carte Google
        map = new google.maps.Map(document.getElementById('map-canvas'), options); //affiche la google map dans la div map_canvas
        map.mapTypes.set('OSM', osmMapType);

        // Ajout de l'évènment sur click dans Carte
        google.maps.event.addListener(map, 'click', surClickDansCarte);

        // Lorsque la carte est chargée, on vérifie si on peut précharger des données
        google.maps.event.addListenerOnce(map, 'idle', function(){
                if (OBS_ID == '') {
                        // Initialisation du marker de début de rue
                        initialiserMarkerDeb();
                        // Tentative de geocalisation si aucune obs à précharger
                        if (OBS_ID == '') {
                                tenterGeolocalisation();
                        }
                } else {
                        okPourChargementCarte--;
                        prechargerRue();
                }
        });

        // Création du Geocoder
        geocoder = new google.maps.Geocoder();
}

function initialiserMarkerDeb() {
        premierDeplacement = true;
        if (markerDeb == undefined) {
                // Marqueur de début de Rue
                markerDeb = new google.maps.Marker({
                        map: map,
                        draggable: true,
                        title: 'Début de la portion de rue étudiée',
                        icon: GOOGLE_MAP_MARQUEUR_DEBUT_URL,
                        position: latLngDeb
                });
                google.maps.event.addListener(markerDeb, 'dragend', surDeplacementMarkerDeb);
        }

        latLngFin = latLngDeb;
        if (markerFin != undefined) {
                markerFin.setMap(null);
        }
        latLngCentre = latLngDeb;
        if (ligneRue != undefined) {
                ligneRue.setMap(null);
        }
}

function surDeplacementMarkerDeb() {
        deplacerMarkerDeb(markerDeb.getPosition());
}

function deplacerMarkerDeb(nouvellePosition) {
        latLngDeb = nouvellePosition;
        markerDeb.setPosition(latLngDeb);
        map.setCenter(latLngDeb);
        mettreAJourStationPosition(latLngDeb);
        trouverCommune(latLngDeb);

        if (premierDeplacement) {
                initialiserMarkerDeb();
                premierDeplacement = false;
        } else {
                var nouvellePositionFin = new google.maps.LatLng(latLngDeb.lat(), latLngDeb.lng() + 0.0010);
                initialiserMarkerFin();
                deplacerMakerFin(nouvellePositionFin)
                afficherEtapeGeolocalisation(3);
        }
}

function initialiserMarkerFin() {
        if (markerFin == undefined) {
                markerFin = new google.maps.Marker({
                        map: map,
                        draggable: true,
                        title: 'Fin de la portion de rue étudiée',
                        icon: GOOGLE_MAP_MARQUEUR_FIN_URL,
                        position: latLngFin
                });
                google.maps.event.addListener(markerFin, 'dragend', surDeplacementMarkerFin);
        } else {
                markerFin.setMap(null);
        }
}

function deplacerMakerFin(nouvellePosition) {
        latLngFin = nouvellePosition;
        markerFin.setMap(map);
        markerFin.setPosition(latLngFin);
        dessinerLigneRue(latLngDeb, latLngFin);
}

function surDeplacementMarkerFin() {
        dessinerLigneRue(markerDeb.getPosition(), markerFin.getPosition());
        afficherCentreRue();
        afficherEtapeGeolocalisation(4);
}

function dessinerLigneRue(pointDebut, pointFin) {
        if (ligneRue != undefined) {
                ligneRue.setMap(null);
        }

        ligneRue = new google.maps.Polyline({
                path: [pointDebut, pointFin],
                strokeColor: "#FF0000",
                strokeOpacity: 1.0,
                strokeWeight: 2
        });

        ligneRue.setMap(map);
}

function afficherCentreRue() {
        latLngDeb = markerDeb.getPosition();
        latLngFin = markerFin.getPosition();
        latLngCentre = new google.maps.LatLng((latLngFin.lat() + latLngDeb.lat())/2, (latLngFin.lng() + latLngDeb.lng())/2);
        mettreAJourStationPosition(latLngCentre);
}

function mettreAJourStationPosition(latLng) {
        var lat = latLng.lat().toFixed(5),
                lng = latLng.lng().toFixed(5);
        remplirChampLatitude(lat);
        remplirChampLongitude(lng);
}

function remplirChampLatitude(latDecimale) {
        var lat = Math.round(latDecimale * 100000) / 100000;
        $('#latitude').val(lat);
}

function remplirChampLongitude(lngDecimale) {
        var lng = Math.round(lngDecimale * 100000) / 100000;
        $('#longitude').val(lng);
}

function trouverCommune(pos) {
        $(function() {
                var url_service = SERVICE_NOM_COMMUNE_URL,
                        urlNomCommuneFormatee = url_service.replace('{lat}', pos.lat()).replace('{lon}', pos.lng());
                $.ajax({
                        url: urlNomCommuneFormatee,
                        type: 'GET',
                        dataType: 'jsonp',
                        beforeSend: function() {
                                $('.commune-info').empty();
                                $('#dialogue-erreur .alert-txt').empty();
                        },
                        success: function(data, textStatus, jqXHR) {
                                $('.commune-info').empty();
                                $('#commune-nom').append(data.nom);
                                $('#commune-code-insee').append(data.codeINSEE);
                                $('#marqueur-commune').data('commune', {'nom' : data.nom, 'codeInsee' : data.codeINSEE});
                        },
                        statusCode: {
                                500: function(jqXHR, textStatus, errorThrown) {
                                        if (DEBUG) {
                                                $('#dialogue-erreur .alert-txt').append('<p id="msg">Un problème est survenu lors de l\'appel au service fournissante le nom des communes.</p>');
                                                reponse = jQuery.parseJSON(jqXHR.responseText);
                                                var erreurMsg = "";
                                                if (reponse != null) {
                                                        $.each(reponse, function (cle, valeur) {
                                                                erreurMsg += valeur + '<br />';
                                                        });
                                                }

                                                $('#dialogue-erreur .alert-txt').append(
                                                        '<p class="msg-erreur">Erreur 500 : '+errorThrown+'<br />'+erreurMsg+'</p>');
                                        }
                                }
                        },
                        error: function(jqXHR, textStatus, errorThrown) {
                                if (DEBUG) {
                                        $('#dialogue-erreur .alert-txt').append(
                                                '<p class="msg">Une erreur Ajax est survenue lors de la transmission de vos observations.</p>');
                                        reponse = jQuery.parseJSON(jqXHR.responseText);
                                        var erreurMsg = '';
                                        if (reponse != null) {
                                                $.each(reponse, function (cle, valeur) {
                                                        erreurMsg += valeur + '<br />';
                                                });
                                        }

                                        $('#dialogue-erreur .alert-txt').append(
                                                '<p class="msg-erreur">Erreur Ajax : '+errorThrown+' (type : '+textStatus+') <br />'+erreurMsg+'</p>');
                                }
                        },
                        complete: function(jqXHR, textStatus) {
                                var debugMsg = extraireEnteteDebug(jqXHR);
                                if (debugMsg != '') {
                                        if (DEBUG) {
                                                $("#dialogue-erreur .alert-txt").append('<pre class="msg-debug msg">Débogage : '+debugMsg+'</pre>');
                                        }
                                }
                                if ($("#dialogue-erreur .msg").length > 0) {
                                        $("#dialogue-erreur").show();
                                }
                        }
                });
        });
}

function afficherEtapeGeolocalisation(numEtape) {
        $('.liste_indication_geolocalisation').children().hide();
        $('.liste_indication_geolocalisation :nth-child('+numEtape+')').show();
}

function afficherErreurGoogleMap(status) {
        if (DEBUG) {
                $('#dialogue-google-map .contenu').empty().append(
                        '<pre class="msg-erreur">'+
                        "Le service de Géocodage de Google Map a échoué à cause de l'erreur : "+status+
                        '</pre>');
                afficherPanneau('#dialogue-google-map');
        }
}

function geolocaliser(event) {
        var latitude = $('#latitude').val(),
                longitude = $('#longitude').val(),
                nouvellePosition = new google.maps.LatLng(latitude, longitude);
        initialiserMarkerDeb();
        deplacerMarkerDeb(nouvellePosition);
        afficherEtapeGeolocalisation(2);
        map.setZoom(16);
        arreter(event);
}

function tenterGeolocalisation() {
        if (navigator.geolocation) {
                navigator.geolocation.getCurrentPosition(function(position) {
                        var latitude = position.coords.latitude,
                                longitude = position.coords.longitude,
                                nouvellePosition = new google.maps.LatLng(latitude, longitude);
                        initialiserMarkerDeb();
                        deplacerMarkerDeb(nouvellePosition);
                        map.setZoom(16);
                });
        }
}

function surClickDansCarte(event) {
        deplacerMarkerDeb(event.latLng);
}


//+---------------------------------------------------------------------------------------------------------+
//AUTO-COMPLÉTION Noms Scientifiques

function ajouterAutocompletionNoms() {
        $('#taxon').autocomplete({
                source: function(requete, add){
                        // la variable de requête doit être vidée car sinon le parametre "term" est ajouté

                        var url = getUrlAutocompletionNomsSci();
                        $.getJSON(url, function(data) {
                                var suggestions = traiterRetourNomsSci(data);
                                add(suggestions);
                        });
                },
                html: true
        });

        $('#taxon').bind('autocompleteselect', function(event, ui) {
                $('#taxon').data(ui.item);
                if (ui.item.retenu == true) {
                        $('#taxon').addClass('ns-retenu');
                } else {
                        $('#taxon').removeClass('ns-retenu');
                }
        });
}

function getUrlAutocompletionNomsSci() {
        var mots = $('#taxon').val(),
                url = SERVICE_AUTOCOMPLETION_NOM_SCI_URL_TPL.replace('{referentiel}',NOM_SCI_REFERENTIEL);
        url = url.replace('{masque}', mots);
        return url;
}

function traiterRetourNomsSci(data) {
        var suggestions = [];
        if (data.resultat != undefined) {
                $.each(data.resultat, function(i, val) {
                        val.nn = i;
                        var nom = {label: '', value: '', nt: '', nomSel: '', nomSelComplet: '', numNomSel: '',
                                nomRet: '', numNomRet: '', famille: '', retenu: false
                        };
                        if (suggestions.length >= AUTOCOMPLETION_ELEMENTS_NBRE) {
                                nom.label = '...';
                                nom.value = $('#taxon').val();
                                suggestions.push(nom);
                                return false;
                        } else {
                                nom.label = val.nom_sci_complet;
                                nom.value = val.nom_sci_complet;
                                nom.nt = val.num_taxonomique;
                                nom.nomSel = val.nom_sci;
                                nom.nomSelComplet = val.nom_sci_complet;
                                nom.numNomSel = val.nn;
                                nom.nomRet = val.nom_retenu_complet;
                                nom.numNomRet = val['nom_retenu.id'];
                                nom.famille = val.famille;
                                nom.retenu = (val.retenu == 'false') ? false : true;

                                suggestions.push(nom);
                        }
                });
        }
        return suggestions;
}

/*
* jQuery UI Autocomplete HTML Extension
*
* Copyright 2010, Scott González (http://scottgonzalez.com)
* Dual licensed under the MIT or GPL Version 2 licenses.
*
* http://github.com/scottgonzalez/jquery-ui-extensions
*
* Adaptation par Aurélien Peronnet pour la mise en gras des noms de taxons valides
*/
(function($) {
        var proto = $.ui.autocomplete.prototype,
                initSource = proto._initSource;

        function filter(array, term) {
                var matcher = new RegExp($.ui.autocomplete.escapeRegex(term), 'i');
                return $.grep(array, function(value) {
                        return matcher.test($('<div>').html(value.label || value.value || value).text());
                });
        }

        $.extend(proto, {
                _initSource: function() {
                        if (this.options.html && $.isArray(this.options.source)) {
                                this.source = function( request, response ) {
                                        response(filter(this.options.source, request.term));
                                };
                        } else {
                                initSource.call(this);
                        }
                },
                _renderItem: function(ul, item) {
                        if (item.retenu == true) {
                                item.label = '<strong>'+item.label+'</strong>';
                        }

                        return $('<li></li>')
                                .data('item.autocomplete', item)
                                .append($('<a></a>')[this.options.html ? 'html' : 'text'](item.label))
                                .appendTo(ul);
                }
        });
})(jQuery);

//+----------------------------------------------------------------------------------------------------------+
//UPLOAD PHOTO : Traitement de l'image
$(document).ready(function() {
        $('#fichier').on('click change', function(event) {
                if ($(this).val().length > 0) {
                        arreter(event);
                        var options = {
                                success: afficherMiniature, // post-submit callback
                                dataType: 'xml', // 'xml', 'script', or 'json' (expected server response type)
                                resetForm: true // reset the form after successful submit
                        };
                        $('#miniature').append(
                                '<img id="miniature-chargement" class="miniature" alt="chargement" src="'+CHARGEMENT_IMAGE_URL+'"/>');
                        $('#ajouter-obs').attr('disabled', 'disabled');
                        if (verifierFormat($(this).val())) {
                                $('#form-upload').ajaxSubmit(options);
                        } else {
                                $('#form-upload')[0].reset();
                                window.alert("Le format de fichier n'est pas supporté, les formats acceptés sont "+   $('#fichier').attr('accept'));
                        }
                        return false;
                }
        });

        $('#photo-placeholder').click(function(event) {
                $('#fichier').click();
        });

        $('body').on('click', '.effacer-miniature', function(event) {
                supprimerMiniature($(this));
        });
});



function verifierFormat(nom) {
        var parts = nom.split('.');
        extension = parts[parts.length - 1];
        return (extension.toLowerCase() == 'jpeg' || extension.toLowerCase() == 'jpg');
}

function afficherMiniature(reponse) {
        if (DEBUG) {
                var debogage = $('debogage', reponse).text();
                //console.log('Débogage upload : ' + debogage);
        }
        var message = $('message', reponse).text();
        if (message != '') {
                $('#miniature-msg').append(message);
        } else {
                $('#miniatures').append(creerWidgetMiniature(reponse));
        }
        $('#ajouter-obs').removeAttr('disabled');
}

function creerWidgetMiniature(reponse) {
        var miniatureUrl = $('miniature-url', reponse).text(),
                imgNom = $('image-nom', reponse).text(),
                html =
                        '<div class="miniature">'+
                                '<img class="miniature-img" class="miniature" alt="'+imgNom+'" src="'+miniatureUrl+'"/>'+
                                '<button class="btn effacer-miniature" type="button">Effacer</button>'+
                        '</div>'
        return html;
}

function supprimerMiniature(miniature) {
        miniature.parents('.miniature').remove();
}

function supprimerMiniatures() {
        $('#miniatures').empty();
        $('#miniature-msg').empty();
}


//+---------------------------------------------------------------------------------------------------------+
// FORMULAIRE : traitements génériques

$(document).ready(function() {
        // Interaction générales
        $('.alert .close').on('click', fermerPanneauAlert);
        $('.has-tooltip').tooltip('enable');
        $('#btn-aide').on('click', basculerAffichageAide);
        $('.dropdown-menu input, .dropdown-menu label').on('click', function(event) {
                event.stopPropagation();
        });

        // Afficher/Cacher champs cachés par défaut
        surChangementPeriodiciteTraitementPhyto();// Vérif lors du chargement de la page
        $('#periodicite-traitement-phyto').on('change', surChangementPeriodiciteTraitementPhyto);

        // Sliders
        transformerEnSlider('#presence-zone-vegetalise');
        transformerEnSlider('#hauteur-batiment-avoisinant');
        transformerEnSlider('#periodicite-traitement-phyto');
        transformerEnSlider('#resistance-traitement-phyto');
        transformerEnSlider('#vitesse-croissance');

        // Date picker
        configurerDatePicker('#date');
        configurerDatePicker('#date-arret-traitement-phyto');

        // Gestion de la liste des taxons
        surChangementTaxonListe();// Vérif lors du chargement de la page
        ajouterAutocompletionNoms();
        $('#taxon-liste').on('change', surChangementTaxonListe);

        // Validation du formulaire
        configurerFormValidator();
        definirReglesFormValidator();

        // Gestion des obs
        $('.cb-milieux').on('click', function(event) {
                $(this).valid();
                event.stopPropagation();
        });
        $('input#hauteur-plante').on('blur', function() {
                // if there's a bad value
                var valeur = $(this).val();
                if (! valeur.match(/^[0-9]+$/)) {
                        // replace it with nothing
                        var nouvelleValeur = valeur.replace(/[^0-9]/g, '');
                        $(this).val(nouvelleValeur);
                }
        });
        $('a.afficher-coord').on('click', basculerAffichageCoord);
        $('#ajouter-obs').on('click', ajouterObs);
        $('.obs-nbre').on('changement', surChangementNbreObs);
        $('body').on('click', '.supprimer-obs', supprimerObs);
        $('#transmettre-obs').on('click', transmettreObs);

        // Défilement des photos
        $('body').on('click', '.defilement-control-zone', function(event) {
                defilerMiniatures($(this));
        });
        $('body').on('mouseover', '.defilement-control-zone', function(event) {
                $('.defilement-control', this).removeClass('hidden');
        });
        $('body').on('mouseout', '.defilement-control-zone', function(event) {
                $('.defilement-control', this).addClass('hidden');
        });

});

function transformerEnSlider(selector) {
        $(selector).each(function(index, el) {
                // hide the element
                $(el).addClass('slider-on');

                // add the slider to each element
                var slider = $( '<div class="slider-holder"><div class="horizontal-slider"></div></div>' ).
                        insertBefore( el ).find('.horizontal-slider').slider({
                                min: 1,
                                max: el.options.length,
                                range: 'min',
                                value: el.selectedIndex + 1,
                                slide: function(event, ui) {
                                        el.selectedIndex = ui.value - 1;
                                        slider.find('a').text(el.options[el.selectedIndex].text);

                                        $(selector + ' option[selected="selected"]').removeAttr('selected');
                                        $(selector + ' :nth-child('+ui.value+')').attr('selected', 'selected')
                                        $(selector).valid();
                                },
                                stop: function() {
                                        $(el).change();
                                }
                        });

                slider.find('a').text(el.options[el.selectedIndex].text);

                // Create a legend under the slider so we can see the options
                var options = [];
                for (var option in $(el).children()) {
                        if (!isNaN(parseInt(option))) {
                                options.push(el.options[option].text);
                        }
                }
                // the width of each legend/option
                var width = (slider.width() / (options.length - 1));

                // Add the legend. Half the width of the first and last options for display consistency.
                slider.after('<div class="slider-legend"><p style="width:' + (width / 2) + 'px;text-align:left;">' +
                        options.join('</p><p style="width:' + width + 'px;">') +'</p></div>')
                        .parent().find('.slider-legend p:last-child').css('width', width / 2)
                        .css('text-align', 'right');

                // if there are too many options so that the text is wider than the width, then hide the text
                var lastChild = slider.parent().find('.slider-legend p:last-child');
                if (lastChild[0].clientWidth < lastChild[0].scrollWidth) {
                        slider.parent().find('.slider-legend p');//.css('text-indent', '200%');
                }
        });
}

function surChangementPeriodiciteTraitementPhyto() {
        if ($('#periodicite-traitement-phyto').val() === 'jamais') {
                $('#datp-zone').removeClass('hidden');
        } else {
                $('#datp-zone').addClass('hidden');
        }
}

function surChangementTaxonListe() {
        if ($('#taxon-liste').val() === '?') {
                $('#taxon-input-groupe').removeClass('hidden');
        } else {
                $('#taxon-input-groupe').addClass('hidden');
        }
}

function configurerDatePicker(selector) {
        $.datepicker.setDefaults($.datepicker.regional['fr']);
        $(selector).datepicker({
                dateFormat: 'dd/mm/yy',
                maxDate: new Date,
                showOn: 'button',
                buttonImageOnly: true,
                buttonImage: CALENDRIER_ICONE_URL,
                buttonText: 'Afficher le calendrier pour saisir la date.',
                showButtonPanel: true,
                onSelect: function(date) {
                        $(this).valid();
                }
        });
        $(selector + ' + img.ui-datepicker-trigger').appendTo(selector + '-icone.add-on');
}

function configurerFormValidator() {
        $.validator.addMethod(
                'dateCel',
                function (value, element) {
                        return value == '' || (/^[0-9]{2}[-\/][0-9]{2}[-\/][0-9]{4}$/.test(value));
                },
                'Format : jj/mm/aaaa. Date incomplète, utiliser 0, exemple : 00/12/2011.');

        $.extend($.validator.defaults, {
                ignore: [],// Forcer Jquery Validate à examiner les éléments avec en display:none;
                highlight: function(element) {
                        $(element).closest('.control-group').removeClass('success').addClass('error');
                },
                success: function(element) {
                        element.text('OK!').addClass('valid');
                        element.closest('.control-group').removeClass('error').addClass('success');

                        if (element.attr('id') == 'taxon' && $('#taxon').val() != '') {
                                // Si le taxon n'est pas lié au référentiel, on vide le data associé
                                if ($('#taxon').data('value') != $('#taxon').val()) {
                                        $('#taxon').data('numNomSel', '');
                                        $('#taxon').data('nomRet', '');
                                        $('#taxon').data('numNomRet', '');
                                        $('#taxon').data('nt', '');
                                        $('#taxon').data('famille', '');
                                }
                        }
                }
        });
}

function definirReglesFormValidator() {
        $('#form-observateur').validate({
                rules: {
                        courriel: {
                                required: true,
                                email: true},
                        courriel_confirmation: {
                                required: true,
                                equalTo: '#courriel'},
                        prenom: {
                                required: true},
                        nom: {
                                required: true},
                        personneStructure: {
                                required: true},
                        personneService: {
                                required: true}
                }
        });
        $('#form-site').validate({
                rules: {
                        station: {
                                required: true},
                        latitude : {
                                required: true,
                                range: [-90, 90]},
                        longitude: {
                                required: true,
                                range: [-180, 180]},
                        typoUrbaine: {
                                required: true},
                        revetementSol: {
                                required: true},
                        intensiteGestion: {
                                required: true},
                        periodiciteTraitementPhyto: {
                                required: true},
                        itineraireGestion: {
                                required: true}
                }
        });
        $('#form-date').validate({
                rules: {
                        date: {
                                required: true,
                                'dateCel' : true},
                        dateDerniereIntervention: {
                                required: true}
                },
                errorPlacement: function(error, element) {
                        if (element.attr('name') == 'date') {
                                element.parent('.input-prepend').after(error);
                        } else {
                                error.insertAfter(element);
                        }
                }
        });
        $('#form-obs').validate({
                rules: {
                        'taxon-liste': {
                                required: true},
                        'milieux[]': {
                                required: true,
                                minlength: 1},
                        hauteurPlante: {
                                required: true,
                                digits: true},
                        resistanceTraitementPhyto: {
                                required: true}
                },
                errorPlacement: function(error, element) {
                        if (element.attr('name') == 'milieux[]') {
                                error.insertAfter('#milieux-controls');
                        } else {
                                error.insertAfter(element);
                        }
                }
        });
}

function validerFormulaire() {
        var observateur = $('#form-observateur').valid(),
                station = $('#form-site').valid(),
                date = $('#form-date').valid(),
                obs = $('#form-obs').valid(),
                debRue = (latLngDeb == undefined) ? false : true,
                finRue = (latLngFin == undefined) ? false : true;
        var ok = (observateur && station && obs && date && debRue && finRue) ? true : false;
        //console.log(observateur+'-'+station+'-'+obs+'-'+date+'-'+debRue+'-'+finRue);
        return ok;
}

function fermerPanneauAlert() {
        $(this).parentsUntil('.zone-alerte', '.alert').hide();
}

function basculerAffichageAide() {
        if ($(this).hasClass('btn-warning')) {
                $('.has-tooltip').tooltip('enable');
                $(this).removeClass('btn-warning').addClass('btn-success');
                $('#btn-aide-txt', this).text("Désactiver l'aide");
        } else {
                $('.has-tooltip').tooltip('disable');
                $(this).removeClass('btn-success').addClass('btn-warning');
                $('#btn-aide-txt', this).text("Activer l'aide");
        }
}

function basculerAffichageCoord() {
        $('.afficher-coord-action').toggle();
        $('#coordonnees-geo').toggle('slow');
        //valeur false pour que le lien ne soit pas suivi
        return false;
}


//+----------------------------------------------------------------------------------------------------------+
// CRÉER OBS : Gestion des obs

var obsNbre = 0;
function ajouterObs() {
        if (validerFormulaire() == true) {
                obsNbre = obsNbre + 1;
                $('.obs-nbre').text(obsNbre);
                $('.obs-nbre').triggerHandler('changement');
                afficherObs();
                stockerObsData();
                supprimerMiniatures();
        } else {
                var debRue = (latLngDeb == undefined) ? false : true,
                        finRue = (latLngFin == undefined) ? false : true;
                if (debRue == false || finRue == false) {
                        afficherPanneau('#dialogue-form-invalide-rue');
                } else {
                        afficherPanneau('#dialogue-form-invalide');
                }
        }
}

function afficherObs() {
        var numNomSel = ($('#taxon-liste').val() == '?') ? $('#taxon').data('numNomSel') : $('#taxon-liste').val(),
                nomSpecial = $('#taxon-liste option:selected').hasClass('nom-special'),
                taxon = ($('#taxon-liste').val() == '?') ? $('#taxon').val() : $('#taxon-liste option:selected').data('nom-a-sauver'),
                referentiel = (numNomSel == undefined) ? '' : '['+NOM_SCI_REFERENTIEL+']',
                commune = $('#commune-nom').text(),
                codeInsee = $('#commune-code-insee').text(),
                lat = $('input[name="latitude"]').val(),
                lng = $('input[name="longitude"]').val(),
                date = $('#date').val(),
                site = $('#station').val(),
                revetement = $('#revetement-sol').val(),
                intensiteGestion = $('#intensite-gestion').val(),
                resistance = $('#resistance-traitement-phyto').val(),
                milieux = getMilieux(),
                notes = (nomSpecial ? taxons[numNomSel]['nom_fr'] + ".<br />" : '') + $('#notes').val();

        $('#liste-obs').prepend(
                '<div id="obs'+obsNbre+'" class="row-fluid obs obs'+obsNbre+'">'+
                        '<div class="span12">'+
                                '<div class="well">'+
                                        '<div class="obs-action pull-right has-tooltip" data-placement="bottom" '+
                                                'title="Supprimer cette observation de la liste à transmettre">'+
                                                '<button class="btn btn-danger supprimer-obs" value="'+obsNbre+'" title="'+obsNbre+'">'+
                                                        '<i class="icon-trash icon-white"></i>'+
                                                '</button>'+
                                        '</div> '+
                                        '<div class="row-fluid">'+
                                                '<div class="span2 obs-miniatures">'+
                                                        ajouterImgMiniatureAuTransfert()+
                                                '</div>'+
                                                '<div class="span8">'+
                                                        '<ul class="unstyled">'+
                                                                '<li>'+
                                                                        '<span class="nom-sci">' + taxon + '</span> ' +
                                                                        formaterNumNomSel(numNomSel)+
                                                                        '<span class="referentiel-obs">' + referentiel + '</span>' +
                                                                        ' observé à ' +
                                                                        '<span class="commune">' + commune + '</span> ' +
                                                                        '(' + codeInsee + ') [' + lat +' / ' + lng + ']' +
                                                                        ' le ' +
                                                                        '<span class="date">' + date + '</span>' +
                                                                '</li>' +
                                                                '<li>' +
                                                                        '<span>Site :</span> ' + site + ' ' + ' ; ' +
                                                                        '<span>Revêtement au sol :</span> ' + revetement + ' ' + ' ; ' +
                                                                        '<span>Intensité de gestion :</span> ' + intensiteGestion + ' ' + ' ; ' +
                                                                        '<span>Milieu :</span> ' + milieux + ' ' + ' ; ' +
                                                                        '<span>Résistance/Résilience :</span> ' + resistance + ' ' +
                                                                '</li>' +
                                                                '<li>' +
                                                                        'Commentaires : ' + notes +
                                                                '</li>'+
                                                        '</ul>'+
                                                '</div>'+
                                        '</div>'+
                                '</div>'+
                        '</div>'+
                '</div>');
}

function getMilieux() {
        var milieuxStr = '',
                milieux = [];
        $('.cb-milieux:checked').each(function() {
                milieux.push($(this).val());
        });

        milieuxStr = Array.prototype.slice.call(milieux).join(', ');
        return milieuxStr;
}

function ajouterImgMiniatureAuTransfert() {
        var html = '',
                miniatures = '',
                indicateurs = '',
                premiere = true,
                numero = 1;
        if ($('#miniatures img').length == 0) {
                html = '<img class="miniature" alt="Aucune photo"src="'+PAS_DE_PHOTO_ICONE_URL+'" />';
        } else if ($('#miniatures img').length >= 1) {
                $('#miniatures img').each(function() {
                        var visible = premiere ? 'miniature-selectionnee' : 'miniature-cachee',
                                css = $(this).hasClass('b64') ? 'miniature b64' : 'miniature',
                                src = $(this).attr('src'),
                                alt = $(this).attr('alt');

                        var miniature = '<img class="'+css+' '+visible+'"  alt="'+alt+'"src="'+src+'" />';
                        miniatures += miniature;

                        var indicateurActif = premiere ? 'active' : '';
                        var indicateur = '<li class="' + indicateurActif + '" data-numero="' + numero++ + '"></li>';
                        indicateurs += indicateur;

                        premiere = false;
                });

                if ($('#miniatures img').length == 1) {
                        html = miniatures;
                } else {
                        html =
                                '<div class="defilement">' +
                                        miniatures +
                                        '<a class="defilement-control-zone gauche">' +
                                        '       <span class="defilement-control gauche hidden">&#60;</span>' +
                                        '</a>' +
                                        '<a class="defilement-control-zone droite">' +
                                        '       <span class="defilement-control droite hidden">&#62;</span>' +
                                        '</a>' +
                                        '<ol class="defilement-indicateurs">' + indicateurs + '</ol>' +
                                '</div>';
                }
        }
        return html;
}

function defilerMiniatures(element) {
        var miniatureSelectionne = element.siblings('img.miniature-selectionnee');
        miniatureSelectionne.removeClass('miniature-selectionnee').addClass('miniature-cachee');
        var miniatureAffichee = miniatureSelectionne;

        var indicateurActif = element.parent().find('.defilement-indicateurs .active');
        indicateurActif.removeClass('active');

        if (element.hasClass('defilement-control-zone') && element.hasClass('gauche')) {
                if (miniatureSelectionne.prev('.miniature').length != 0) {
                        miniatureAffichee = miniatureSelectionne.prev('.miniature');
                        indicateurActif.prev().addClass('active');
                } else {
                        miniatureAffichee = miniatureSelectionne.siblings('.miniature').last();
                        indicateurActif.siblings().last().addClass('active');
                }
        } else {
                if (miniatureSelectionne.next('.miniature').length != 0) {
                        miniatureAffichee = miniatureSelectionne.next('.miniature');
                        indicateurActif.next().addClass('active');
                } else {
                        miniatureAffichee = miniatureSelectionne.siblings('.miniature').first();
                        indicateurActif.siblings().first().addClass('active');
                }
        }
        miniatureAffichee.addClass('miniature-selectionnee').removeClass('miniature-cachee');
}

function formaterNumNomSel(numNomSel) {
        var nn = '';
        if (numNomSel == undefined) {
                nn = '<span class="alert-error">[non lié au référentiel]</span>';
        } else {
                nn = '<span class="nn">[nn'+numNomSel+']</span>';
        }
        return nn;
}

function surChangementReferentiel() {
        NOM_SCI_REFERENTIEL = $('#referentiel').val();
        $('#taxon').val('');
}

function surChangementNbreObs() {
        if (obsNbre == 0) {
                $('#transmettre-obs').attr('disabled', 'disabled');
                $('#ajouter-obs').removeAttr('disabled');
                $('#zone-liste-obs').addClass('hidden');
        } else {
                $('#zone-liste-obs').removeClass('hidden');

                if (obsNbre > 0 && obsNbre < OBS_MAX_NBRE) {
                        $('#transmettre-obs').removeAttr('disabled');
                        $('#ajouter-obs').removeAttr('disabled');
                } else if (obsNbre >= OBS_MAX_NBRE) {
                        $('#ajouter-obs').attr('disabled', 'disabled');
                        afficherPanneau('#dialogue-bloquer-creer-obs');
                }
        }
}

function supprimerObs() {
        var obsId = $(this).val();
        // Problème avec IE 6 et 7
        if (obsId == "Supprimer") {
                obsId = $(this).attr("title");
        }
        supprimerObsParId(obsId);
}

function supprimerObsParId(obsId) {
        obsNbre = obsNbre - 1;
        $(".obs-nbre").text(obsNbre);
        $(".obs-nbre").triggerHandler('changement');
        $('.obs'+obsId).remove();
        $("#liste-obs").removeData('obsId'+obsId);
}

function initialiserBarreProgression() {
        $('#barre-progression-upload').attr('aria-valuenow', 0);
        $('#barre-progression-upload').attr('style', "width: 0%");
        $('#barre-progression-upload .sr-only').text("0/0 observations transmises");
        $('.progress').addClass('active');
        $('.progress').addClass('progress-striped');
}

function initialiserObs() {
        obsNbre = 0;
        nbObsTransmises = 0;
        nbObsEnCours = 0;
        totalObsATransmettre = 0;
        initialiserBarreProgression();
        $(".obs-nbre").text(obsNbre);
        $(".obs-nbre").triggerHandler('changement');
        $("#liste-obs").removeData();
        $('.obs').remove();
        $("#dialogue-bloquer-creer-obs").hide();
}

function getNomsImgsOriginales() {
        var noms = new Array();
        $('.miniature-img').each(function() {
                noms.push($(this).attr('alt'));
        });
        return noms;
}

function stockerObsData() {
        var nomHorsListe = $('#taxon-liste').val() == '?' ? true : false;
                nomSpecial = $('#taxon-liste option:selected').hasClass('nom-special'),
                numNomSel = nomHorsListe ? $('#taxon').data('numNomSel') : $('#taxon-liste').val(),
                nomSel = nomHorsListe ? $('#taxon').val() : $('#taxon-liste option:selected').data('nom-a-sauver'),
                nomRet = nomHorsListe ? $('#taxon').data('nomRet') : taxons[numNomSel]['nom_ret'],
                numNomRet = nomHorsListe ? $('#taxon').data('numNomRet') : taxons[numNomSel]['num_nom_ret'],
                numTaxon = nomHorsListe ? $('#taxon').data('nt') : taxons[numNomSel]['num_taxon'],
                famille = nomHorsListe ? $('#taxon').data('famille') : taxons[numNomSel]['famille'],
                referentiel = (numNomSel == undefined) ? '' : NOM_SCI_REFERENTIEL,
                notes = (nomSpecial ? taxons[numNomSel]['nom_fr'] + '. ' : '') + $('#notes').val();

        $('#liste-obs').data('obsId'+obsNbre, {
                'date': $('#date').val(),
                'notes': notes,

                'station': $('#station').val(),
                'latitude': $('#latitude').val(),
                'longitude': $('#longitude').val(),
                'commune_nom': $('#commune-nom').text(),
                'commune_code_insee': $('#commune-code-insee').text(),

                'nom_sel': nomSel,
                'num_nom_sel': numNomSel,
                'nom_ret': nomRet,
                'num_nom_ret': numNomRet,
                'num_taxon': numTaxon,
                'famille': famille,
                'referentiel': referentiel,

                'milieu': getMilieux(),

                // Ajout des champs images
                'image_nom': getNomsImgsOriginales(),

                // Ajout des champs étendus de l'obs
                'obs_etendue': getObsChpEtendus()
        });
        //console.log($('#liste-obs').data('obsId'+obsNbre));
}

function getObsChpEtendus() {
        var champs = [],
                perceptionTechnicien = getPerceptionTechnicien();
        if (perceptionTechnicien != undefined) {
                champs.push(perceptionTechnicien);
        }
        if (latLngDeb != undefined) {
                var latitudeDebutRue = {cle: 'latitudeDebutRue', label: 'Latitude du début de la rue', valeur: latLngDeb.lat().toFixed(5)};
                champs.push(latitudeDebutRue);
                var longitudeDebutRue = {cle: 'longitudeDebutRue', label: 'Longitude du début de la rue', valeur: latLngDeb.lng().toFixed(5)};
                champs.push(longitudeDebutRue);
        }
        if (latLngFin != undefined) {
                var latitudeFinRue = {cle: 'latitudeFinRue', label: 'Latitude de fin de la rue', valeur: latLngFin.lat().toFixed(5)};
                champs.push(latitudeFinRue);
                var longitudeFinRue = {cle: 'longitudeFinRue', label: 'Longitude de fin de la rue', valeur: latLngFin.lng().toFixed(5)};
                champs.push(longitudeFinRue);
        }

        $('.obs-chp-etendu').each(function() {
                var valeur = $(this).val(),
                        cle = $(this).attr('name'),
                        label = $(this).data('label');
                if (valeur != '') {
                        var chpEtendu = {cle: cle, label: label, valeur: valeur};
                        champs.push(chpEtendu);
                }
        });
        return champs;
}

function getPerceptionTechnicien() {
        var perceptionTechnicien = undefined,
                perceptions = [];
        $('.cb-perception-technicien:checked').each(function() {
                perceptions.push($(this).val());
        });
        if (perceptions.length > 0) {
                var valeur = Array.prototype.slice.call(perceptions).join(', ');
                perceptionTechnicien = {cle: 'perceptionTechnicien', label: "Perceptions par l'équipe", valeur: valeur};
        }
        return perceptionTechnicien;
}

//+----------------------------------------------------------------------------------------------------------+
// TRANSFERER OBS : envoie des obs au CEL
var nbObsEnCours = 1;
var totalObsATransmettre = 0;
function transmettreObs() {
        var observations = $("#liste-obs").data();
        if (observations == undefined || jQuery.isEmptyObject(observations)) {
                afficherPanneau("#dialogue-zero-obs");
        } else {
                nbObsEnCours = 1;
                nbObsTransmises = 0;
                totalObsATransmettre = $.map(observations, function(n, i) { return i; }).length;
                depilerObsPourEnvoi();
        }
        return false;
}

function depilerObsPourEnvoi() {
        var observations = $("#liste-obs").data();
        // la boucle est factice car on utilise un tableau
        // dont on a besoin de n'extraire que le premier élément
        // or javascript n'a pas de méthode cross browsers pour extraire les clés
        // TODO: utiliser var.keys quand ça sera plus répandu
        // ou bien utiliser un vrai tableau et pas un objet
        for (var obsNum in observations) {
                obsATransmettre = new Object();

            obsATransmettre['projet'] = TAG_PROJET;
            obsATransmettre['tag-obs'] = TAG_OBS;
            obsATransmettre['tag-img'] = TAG_IMG;

                var utilisateur = new Object();
                utilisateur.id_utilisateur = $("#id_utilisateur").val();
                utilisateur.prenom = $("#prenom").val();
                utilisateur.nom = $("#nom").val();
                utilisateur.courriel = $("#courriel").val();
                obsATransmettre['utilisateur'] = utilisateur;
                obsATransmettre[obsNum] = observations[obsNum];
                var idObsNumerique = obsNum.replace('obsId', '');
                if(idObsNumerique != "") {
                        envoyerObsAuCel(idObsNumerique, obsATransmettre);
                }

                break;
        }
}

var nbObsTransmises = 0;
function mettreAJourProgression() {
        nbObsTransmises++;
        var pct = (nbObsTransmises/totalObsATransmettre)*100;
        $('#barre-progression-upload').attr('aria-valuenow', nbObsTransmises);
        $('#barre-progression-upload').attr('style', "width: "+pct+"%");
        $('#barre-progression-upload .sr-only').text(nbObsTransmises+"/"+totalObsATransmettre+" observations transmises");

        if(obsNbre == 0) {
                $('.progress').removeClass('active');
                $('.progress').removeClass('progress-striped');
        }
}

function envoyerObsAuCel(idObs, observation) {
        var erreurMsg = '',
                debugNonJson = '';
        $.ajax({
                url: SERVICE_SAISIE_URL,
                type: 'POST',
                data: observation,
                dataType: 'json',
                beforeSend: function() {
                        $('#dialogue-obs-transaction-ko').hide();
                        $('#dialogue-obs-transaction-ok').hide();
                        $('.alert-txt').empty();
                        $('#chargement').show();
                },
                success: function(data, textStatus, jqXHR) {
                        // mise à jour du nombre d'obs à transmettre
                        // et suppression de l'obs
                        supprimerObsParId(idObs);
                        nbObsEnCours++;
                        // mise à jour du statut
                        mettreAJourProgression();
                        if(obsNbre > 0) {
                                // dépilement de la suivante
                                depilerObsPourEnvoi();
                        }
                        supprimerMiniatures();
                },
                statusCode: {
                        500: function(jqXHR, textStatus, errorThrown) {
                                erreurMsg += "Erreur 500 :\ntype : " + textStatus + ' ' + errorThrown + "\n";
                        }
                },
                error: function(jqXHR, textStatus, errorThrown) {
                        erreurMsg += "Erreur Ajax :\ntype : " + textStatus + ' ' + errorThrown + "\n";
                        try {
                                reponse = jQuery.parseJSON(jqXHR.responseText);
                                if (reponse != null) {
                                        $.each(reponse, function (cle, valeur) {
                                                erreurMsg += valeur + "\n";
                                        });
                                }
                        } catch(e) {
                                erreurMsg += "L'erreur n'est pas en JSON.";
                                debugNonJson = jqXHR.responseText;
                        }
                },
                complete: function(jqXHR, textStatus) {
                        var debugMsg = extraireEnteteDebug(jqXHR);

                        if (erreurMsg != '') {
                                if (DEBUG) {
                                        $('#dialogue-obs-transaction-ko .alert-txt').append('<pre class="msg-erreur">' + erreurMsg + '</pre>');
                                        $('#dialogue-obs-transaction-ko .alert-txt').append('<pre class="msg-debug">Débogage : ' + debugNonJson + debugMsg + '</pre>');
                                }
                                var hrefCourriel = 'mailto:cel_remarques@tela-botanica.org?' +
                                        'subject=Disfonctionnement du widget de saisie ' + TAG_PROJET +
                                        '&body=' + erreurMsg + "\nDébogage :\n" + debugMsg + debugNonJson;

                                // mise en valeur de l'obs en erreur + scroll vers celle ci en changeant le hash
                                $('#obs'+idObs+' div div').addClass('obs-erreur');
                                window.location.hash = "obs"+idObs;

                                $('#dialogue-obs-transaction-ko .alert-txt').append($('#tpl-transmission-ko').clone()
                                        .find('.courriel-erreur')
                                        .attr('href', hrefCourriel)
                                        .end()
                                        .html());
                                $('#dialogue-obs-transaction-ko').show();
                                $("#chargement").hide();
                                initialiserBarreProgression();
                        } else {
                                if (DEBUG) {
                                        $('#dialogue-obs-transaction-ok .alert-txt').append('<pre class="msg-debug">Débogage : ' + debugMsg + debugNonJson + '</pre>');
                                }
                                if(obsNbre == 0) {
                                        setTimeout(function() {
                                                $("#chargement").hide();
                                                $('#dialogue-obs-transaction-ok .alert-txt').append($('#tpl-transmission-ok').clone().html());
                                                $("#dialogue-obs-transaction-ok").show();
                                                window.location.hash = "dialogue-obs-transaction-ok";
                                                initialiserObs();
                                        }, 1500);

                                }
                        }
                }
        });
}