Subversion Repositories eFlore/Applications.cel

Rev

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

function WidgetPhotoPopup( proprietes ) {
        if( this.valOk( proprietes ) ) {
                this.urlWidget                    = proprietes.urlWidget;
                this.urls                         = proprietes.urls;
                this.infosImages                  = proprietes.infosImages;
                this.urlImage                     = proprietes.urlImage;
                this.indexPremiereImage           = proprietes.indexPremiereImage;
                this.indexImage                   = this.indexPremiereImage;
                this.tailleMax                    = proprietes.tailleMax;
                this.popupUrl                     = proprietes.popupUrl;
                this.urlBaseTelechargement        = proprietes.urlBaseTelechargement;
                this.urlServiceRegenererMiniature = proprietes.urlServiceRegenererMiniature;
                this.userId                                       = proprietes.userId;
                this.token                                                = proprietes.token;
                this.protocoles                                   = proprietes.protocoles;
                this.urlServiceDel                                = proprietes.urlServiceDel;
                this.urlServiceNewCel                     = proprietes.urlServiceNewCel;
        }
        this.protocole = null;
        this.voteId = null;
        this.votes = null;
        this.mettreAJourInfosImage();
}

WidgetPhotoPopup.prototype = new WidgetPhotoCommun();

WidgetPhotoPopup.prototype.initTpl = function() {
        this.redimensionnerGalerie();
        $( '#info-img-galerie' ).find( '.active' ).removeClass( 'active' );
        $( '#img-cadre-' + this.indexImage + ',#indicateur-img-' + this.indexImage ).addClass( 'active' );

        this.mettreAJourPopup();

        this.redimentionnerModaleCarousel();
};

WidgetPhotoPopup.prototype.initEvts = function() {
        const lthis = this;

        this.initEvtsDefilerImage();
        // this.initEvtsContact();
        $( window ).on( 'resize', lthis.redimentionnerModaleCarousel.bind( lthis ) );
        this.initEvtsFonctionsPhoto();
        this.initEvtsRetourGalerieResponsive();
        this.initEvtsToggleVolet();
};

WidgetPhotoPopup.prototype.mettreAJourPopup = function() {
        this.mettreAJourInfosImage();
        this.afficherTitreImage();
        this.traiterMetas();
        this.regenererMiniature();
        this.fournirLienIdentiplante();
        this.pivoterImage();
        this.initEvtsProtocole();
        this.initEvtsTagsPF();
        this.initEvtsTagsCel();
};

WidgetPhotoPopup.prototype.mettreAJourInfosImage = function() {
        this.item          = this.infosImages[this.urls[this.indexImage]];
        this.titreImage    = this.item['titre'];
        this.urlLienEflore = this.item['lien'];
        this.idImage       = this.item['id_photo'];

        // If last caract of the url is a ',' we remove it
        const lastCaractUrlImage = this.item['url_photo'].slice(-1);
        if (lastCaractUrlImage === ','){
                this.item['url_photo'] = this.item['url_photo'].replace(/.$/,'');
        }

        this.urlThisImage  = this.item['url_photo']+'.jpg';
        this.obs           = this.item['obs'];
        this.nn            = '[nn' + this.obs['nom_sel_nn']+']';
        this.urlIP         = this.obs['url_ip'];
        this.tagsImage     = this.tagsToArray( this.item['tags_photo'] );
        this.tagsObs       = this.tagsToArray( this.obs['tags_obs'] );
        let auteurMail = this.item['utilisateur']['mail_utilisateur'].split("@")[0];
        this.auteur        = this.item["utilisateur"]["nom_utilisateur"] ? this.item["utilisateur"]["nom_utilisateur"] : auteurMail;
        this.date          = this.item['date'];
        this.urlTpl        = this.item['url_tpl'];
};

WidgetPhotoPopup.prototype.tagsToArray = function( tags ) {
        if(!this.valOk(tags)) {
                return [];
        }
        tags = tags.replace( new RegExp('\\.'), '' ).split( ',' );

        let cleanTags       = [],
                nbTags          = tags.length,
                tag             = '',
                tagsSansEspaces = '',
                cleanTagIndex   = 0;

        for(let i = 0; i < nbTags; i++) {
                tag = tags[i];
                tagsSansEspaces = tag.replace( ' ', '');
                if( '' !== tagsSansEspaces ) {
                        cleanTags.push( tag.trim() );
                }
        }

        return cleanTags;
};

WidgetPhotoPopup.prototype.initEvtsDefilerImage = function() {
        const lthis = this;

        $( '#precedent, #suivant' ).off('click');

        $( '#precedent, #suivant' ).on( 'click', function() {
                lthis.defilerImage( this.id );
                lthis.initEvtsTagsPF();
        });

        $( '#print_content:not(saisir-tag)' ).on( 'keydown', function( event ) {

                const determinerSens = function( enventKey, left, right ) {
                        switch ( enventKey ) {
                                case left:
                                        return 'suivant';
                                case right:
                                        return 'precedent';
                                default:
                                        break;
                        }

                        return;
                }

                event = (event || window.event);
                // event.keyCode déprécié, on tente d'abord event.key
                let sens = ( 'key' in event ) ? determinerSens( event.key, 'ArrowLeft', 'ArrowRight' ) : determinerSens( event.keyCode, 37, 39 );;
console.log(sens);
                if ( lthis.valOk( sens ) ) {
                        lthis.defilerImage( sens );
                }
        });
};

// WidgetPhotoPopup.prototype.initEvtsContact = function() {
//      const lthis = this;
//
//      $( '#bloc-infos-img' ).on( 'click', '.lien_contact', function( event ) {
//              event.preventDefault();
//              lthis.chargerContenuModale( this.href );
//      });
// };

WidgetPhotoPopup.prototype.initEvtsFonctionsPhoto = function() {
        const lthis = this;

        $( '#boutons-footer #bloc-fct a, #retour-metas' ).on( 'click', function( event ){
                event.preventDefault();
                var voletAOuvrir = $( this ).data( 'volet' ),
                        voletAFermer = $( '.bloc-volet:not(.hidden)' ).data( 'volet' );

                lthis.ouvrirVoletFct( voletAOuvrir, voletAFermer );
                if ( window.matchMedia( '(max-width: 991px)' ).matches ) {
                        $( '#info-img-galerie' ).addClass( 'hidden' );
                        $( '#volet, #retour-galerie' ).removeClass( 'hidden' );
                        $( '#hide-metas-div' ).removeClass( 'hidden' );
                }
        });
};

WidgetPhotoPopup.prototype.initEvtsRetourGalerieResponsive = function() {
        $( '#retour-galerie' ).on( 'click', function( event ) {
                event.preventDefault();
                $( '#info-img-galerie' ).removeClass( 'hidden' );
                $( this ).addClass( 'hidden' );
                if ( window.matchMedia( '(max-width: 991px)' ).matches ) {
                        $( '#volet' ).addClass( 'hidden' );
                        $( '.bouton-fct.actif' ).removeClass( 'actif' );
                        $( '#hide-metas-div' ).addClass( 'hidden' );
                }
        });
};

WidgetPhotoPopup.prototype.initEvtsTagsCel = function(){
        const lthis = this;
        $( '#tags-cel' ).html('');

        $( '#tags-cel' ).append(
                "<p>"+ lthis.item['tags_photo']+"</p>"
        )
}

WidgetPhotoPopup.prototype.initEvtsTagsPF = function() {
        const tagsPfDiv = $('#tags-pf');
        tagsPfDiv.html('');
        tagsPfDiv.append('<a id="port" class="btn tag">Port</a>' +
                '<a id="fleur" class="btn tag">Fleur</a>' +
                '<a id="fruit" class="btn tag">Fruit</a>' +
                '<a id="feuille" class="btn tag">Feuille</a>' +
                '<a id="ecorce" class="btn tag">Ecorce</a>' +
                '<a id="rameau" class="btn tag">Rameau</a>' +
                '<a id="planche" class="btn tag">Planche</a>' +
                '<a id="rosette" class="btn tag">Rosette</a>' +
                '<a id="pousse" class="btn tag">Pousse</a>');

        this.tagsPf();
        this.tagsPfCustom();

        $( '#bloc-tags' ).off('click');

        $( '#bloc-tags' ).on( 'click', '.tag', function( event ) {
                event.preventDefault();
                $( this ).toggleClass( 'actif' );

                var motCleClique = '';
                motCleClique = $(this).attr('id');

                // Utiliser la méthode findIndex pour obtenir l'index de l'élément dans le tableau
                var indexElementTrouve = lthis.item['tags_pf'].findIndex(function (tag) {
                        return tag['mot_cle'] === motCleClique;
                });

                // Vérifier si l'élément a été trouvé
                if (indexElementTrouve !== -1) {
                        //supprimer tag dans DEL
                        if (lthis.item['tags_pf'][indexElementTrouve].hasOwnProperty('id_mot_cle') && lthis.item['tags_pf'][indexElementTrouve]['id_mot_cle'] != ''){
                                let url = lthis.urlServiceDel + 'mots-cles/' + lthis.item['tags_pf'][indexElementTrouve]['id_mot_cle']

                                lthis.envoyerVersService('DELETE', url)
                        }

                        // Supprimer l'élément de this.item['tags_pf'] à l'index trouvé
                        lthis.item['tags_pf'].splice(indexElementTrouve, 1);
                } else {
                        //Ajout tag dans le DEL
                        let url = lthis.urlServiceDel + 'mots-cles';
                        let donnees = {
                                "image" : lthis.idImage,
                                "mot_cle" : motCleClique,
                                "auteur.id" : lthis.item["utilisateur"]["id_utilisateur"]
                        }

                        lthis.envoyerVersService('PUT', url, null, JSON.stringify(donnees), function (erreur, tagId) {
                                if (erreur) {
                                        console.error("Erreur lors de la requête :", erreur);
                                } else {
                                        console.log('tag : ' + motCleClique + ' ajouté');
                                        lthis.item['tags_pf'].push({'id_mot_cle' : tagId['id'][0], 'mot_cle' : motCleClique})
                                }
                        });
                }
        });
        /* //@TODO est-ce qu'on garde cette croix?
        $( '#bloc-tags' ).on( 'click', '.custom-tag.actif .fermer', function( event ) {
                event.preventDefault();
                //                      Supprimer un custom-tag
                //      _OPTIONS
                // https://api-test.tela-botanica.org/service:del:0.1/mots-cles/38368
                //      _paramètres
                // L'id du tag à la fin de l'url
                //      _DELETE
                // https://api-test.tela-botanica.org/service:del:0.1/mots-cles/38368
                //      _réponse:
                // ""
                //                      Mettre à jour les mots cles
                //      _OPTIONS
                // https://api-test.tela-botanica.org/service:del:0.1/mots-cles?image=197938
                //      _GET
                // https://api-test.tela-botanica.org/service:del:0.1/mots-cles?image=197938
                $( this ).parent( '.custom-tag' ).remove();
        });
        */
/*
        $( '#bloc-tags' ).on( 'keyup', '.custom-tag.actif', function( event ) {
                let supprimerTag = false;

                event = ( event || window.event );
                // event.keyCode déprécié, on tente d'abord event.key
                if ( 'key' in event ) {
                        supprimerTag = ( 'Delete' === event.key || 'Backspace' === event.key );
                } else {
                        supprimerTag = ( 46 === event.keyCode || 8 === event.keyCode );
                }
                if ( supprimerTag ) {
                        //                      Supprimer un custom-tag
                        //      _OPTIONS
                        // https://api-test.tela-botanica.org/service:del:0.1/mots-cles/38368
                        //      _paramètres
                        // L'id du tag à la fin de l'url
                        //      _DELETE
                        // https://api-test.tela-botanica.org/service:del:0.1/mots-cles/38368
                        //      _réponse:
                        // ""
                        //                      Mettre à jour les mots cles
                        //      _OPTIONS
                        // https://api-test.tela-botanica.org/service:del:0.1/mots-cles?image=197938
                        //      _GET
                        // https://api-test.tela-botanica.org/service:del:0.1/mots-cles?image=197938
                        $( this ).parent( '.custom-tag' ).remove();
                }
        });
 */
};

WidgetPhotoPopup.prototype.defilerImage = function( sens ) {
        if ( 'suivant' === sens ) {
                this.indexImage++ ;
                if( this.indexImage >= this.urls.length ) {
                        this.indexImage = 0;
                }
        } else if ( 'precedent' === sens ) {
                this.indexImage--;
                if( this.indexImage < 0 ) {
                        this.indexImage = this.urls.length -1;
                }
        }
        // @TODO: Modifier l'attr content de 'meta[property=og:image]' et y mettre l'url de l'image
        this.mettreAJourPopup();
};

WidgetPhotoPopup.prototype.afficherTitreImage = function() {
        let lienContact  =
                        this.urlWidget +'?mode=contact&nn=' + this.nn +
                        '&nom_sci=' + this.obs['nom_sel'] +
                        '&date=' + this.date +
                        '&localisation=' + this.obs['localisation'] +
                        '&id_image=' + this.idImage +
                        '&auteur=' + this.auteur;

        if ( this.valOk( this.popupUrl ) ) {
                if (! this.popupUrl.match( new RegExp( 'img:' + this.idImage ) ) ) {
                        this.popupUrl = this.actualiserPopupUrl( this.popupUrl, this.urlThisImage );
                }
                lienContact += '&popup_url=' + encodeURIComponent( this.popupUrl );
        }

        $( '#bloc-infos-img' ).html(
                this.afficherLien( this.urlLienEflore, this.obs['nom_sel'] )+
                ' par '+
                '<a class="lien_contact" href="' + this.item['urlProfil'] + '" target="_blank" title="Afficher le profil">' + this.auteur + '</a> '+
                ' le ' + this.date + ' - ' + this.obs['localisation']
        );
};

WidgetPhotoPopup.prototype.actualiserPopupUrl = function( queryString, remplacement ) {
        let queryStringParsee = queryString.substring(1).split('&');

        $.each( queryStringParsee,  function( i, param ) {
                if( /url_image/.test( param ) ) {
                        queryString = queryString.replace( param, 'url_image=' + remplacement );
                        return false;
                }
        });
        return queryString;
};

WidgetPhotoPopup.prototype.redimentionnerModaleCarousel = function() {
        this.redimensionnerGalerie();
        if ( window.matchMedia( '(max-width: 991px)' ).matches ) {
                $( '#volet, #retour-galerie' ).addClass( 'hidden' );
                $( '#info-img-galerie' ).removeClass( 'hidden' );
                $( '.bouton-fct.actif' ).removeClass( 'actif' );
                $( '.nettoyage-volet.haut' ).text( $( '#bloc-infos-img' ).text() );
                $( '#boutons-footer, #info-img-galerie' ).removeClass( 'col-lg-8' );
                $( '#bloc-infos-img, #volet' ).removeClass( 'col-lg-4' );
        } else {
                $( '#volet, #info-img-galerie' ).removeClass( 'hidden' );
                if ( this.valOk( $( '.bloc-volet:not(.hidden)' ) ) ) {
                        $( '.bouton-fct.' + $( '.bloc-volet:not(.hidden)' ).data( 'volet' ) ).addClass( 'actif' );
                }
                $( '.nettoyage-volet.bas' ).text( $( '#bloc-infos-img' ).text() );
                $( '#boutons-footer, #info-img-galerie' ).addClass( 'col-lg-8' );
                $( '#bloc-infos-img, #volet' ).addClass( 'col-lg-4' );
                $( '#retour-galerie' ).addClass( 'hidden' );
        }
};

WidgetPhotoPopup.prototype.redimensionnerGalerie = function() {
        var maxSize = ( $( window ).width() / $( window ).height() ) < 1 ? $( window ).width() : $( window ).height();

        maxSize -= 30;
        $( '.carousel-item img' ).each( function( index, image ) {
                var proportion  = image.dataset.width / image.dataset.height,
                        cssResize   = {};

                if ( proportion >= 1 ) {
                        cssResize['width'] = maxSize;
                }
                if ( proportion <= 1) {
                        cssResize['height'] = maxSize;
                }
                $( image ).css( cssResize );
        });
};

WidgetPhotoPopup.prototype.ouvrirVoletFct = function( voletAOuvrir, voletAFermer ) {
        if( voletAOuvrir !== voletAFermer ) {
                $( '#boutons-footer  .' + voletAFermer ).removeClass( 'actif' );
                $( '#boutons-footer  .' + voletAOuvrir ).addClass( 'actif' );
                $( '#bloc-' + voletAFermer ).addClass( 'hidden' );
                $( '#bloc-' + voletAOuvrir ).removeClass( 'hidden' );
                $( '#volet' ).scrollTop(0);
                $( '#retour-metas' ).removeClass( 'hidden', 'meta' === voletAOuvrir );
        }
};

WidgetPhotoPopup.prototype.tagsPf = function () {
        const lthis = this;
        $('#tags-pf-supp').html('');

        lthis.item['tags_pf'].forEach(tag => {
                const tagElement = document.getElementById(tag['mot_cle']);

                // Vérifier si l'élément existe
                if (tagElement) {
                        // Ajouter la classe 'active' à l'élément <a>
                        tagElement.classList.add('actif');
                } else {
                        $('#tags-pf-supp').append('<a id="'+tag['mot_cle']+'" class="btn tag custom-tag actif">' + tag['mot_cle'] + '&nbsp;' +
                                // '<i class="fas fa-times-circle fermer"></i>' +
                                '</a>')
                }
        });
}

WidgetPhotoPopup.prototype.tagsPfCustom = function() {
        const lthis = this;

        $( '#saisir-tag' ).on( 'blur keyup', function( event ) {
                event = ( event || window.event );

                var ajouterTag = ( 'blur' === event.type );

                // event.keyCode déprécié, on tente d'abord event.key
                if ( 'key' in event  ) {
                        if ( 'Enter' === event.key ) {
                                ajouterTag = true;
                        }
                } else if ( 13 === event.keyCode ) {
                        ajouterTag = true;
                }
                if      ( ajouterTag ) {
                        var nouveauTag     = $( this ).val(),
                                nouveauTagAttr = lthis.chaineValableAttributsHtml( nouveauTag.toLowerCase() );

                        if( lthis.valOk( nouveauTagAttr ) && !lthis.valOk( $( '#' + nouveauTagAttr + '.tag' ) ) ) {
                                $( '#tags-pf-supp' ).append(
                                        '<a id="' + nouveauTagAttr + '" class="btn tag custom-tag actif">' +
                                                nouveauTag + '&nbsp;' +
                                        // '<i class="fas fa-times-circle fermer"></i>' +
                                        '</a>'
                                );

                                let url = lthis.urlServiceDel + 'mots-cles';
                                let donnees = {
                                        "image" : lthis.idImage,
                                        "mot_cle" : nouveauTagAttr,
                                        "auteur.id" : lthis.item["utilisateur"]["id_utilisateur"]
                                }

                                // Envoie du nouveau tag dans le DEL
                                lthis.envoyerVersService('PUT', url, null, JSON.stringify(donnees), function (erreur, tagId) {
                                        if (erreur) {
                                                console.error("Erreur lors de la requête :", erreur);
                                        } else {
                                                console.log('tag : ' + nouveauTagAttr + ' ajouté');
                                                lthis.item['tags_pf'].push({'id_mot_cle' : tagId['id'][0], 'mot_cle' : nouveauTagAttr})
                                        }
                                });

                                // $( '#form-tags-auteur' )[0].reset();
                                $( this ).val( '' );
                        }
                }
        });
};

WidgetPhotoPopup.prototype.traiterMetas = function() {
        this.afficherMetas();
        this.afficherPopupLocalisation();
        this.afficherMetasPlus();
        this.fournirLienTelechargement();
};

WidgetPhotoPopup.prototype.afficherMetas = function() {
        const lthis         = this;
        const META_CONTENUS = {
                'nom' : this.afficherLien( this.urlLienEflore, this.obs['nom_sel'] ),
                'localisation' : this.obs['localisation'],
                'auteur' : this.auteur,
                'date-obs' : this.date,
                'commentaire' : this.obs['commentaire'],
                'certitude' : this.obs['certitude'],
                'fiabilite' : this.obs['fiabilite'],
                'num-photo' : this.idImage,
                'titre-original' : this.item['nom_original'],
                'date-photo' : this.formaterDate( this.item['date_photo'] ),
                'attribution-copy' : this.item['attribution'],
                'url-copy' : this.urlThisImage
        };

        $.each( META_CONTENUS, function( attrId, contenu ) {
                let $metaContainer = $( '#bloc-meta #'+attrId );

                if ( lthis.valOk( contenu ) ) {
                        switch( attrId ) {
                                case 'attribution-copy' :
                                case 'url-copy' :
                                        $metaContainer.val( contenu );
                                        lthis.copieAutoChamp( $metaContainer );
                                        break;
                                case 'nom' :
                                        $( '.contenu', $metaContainer ).html( contenu );
                                        $( '.bouton', $metaContainer ).attr( 'href', lthis.urlLienEflore );
                                        break;
                                case 'auteur' :
                                        $( '.bouton', $metaContainer ).attr( 'href', lthis.item['urlProfil'] );
                                default:
                                        $( '.contenu', $metaContainer ).text( contenu );
                                        break;
                        }
                }
        });
};

WidgetPhotoPopup.prototype.copieAutoChamp = function( $champACopier ) {
        $champACopier.off( 'click' ).on( 'click', function() {
                $( '#attribution-copy, #url-copy' ).removeClass( 'hidden' )
                        .find( '.copy-message' ).remove();

                $( this ).select();
                document.execCommand( 'copy' );

                $( this ).after(
                        '<p class="copy-message alert-success" style="width: 100%; height:' + $( this ).outerHeight() + 'px; margin: 0; display:flex;">'+
                                '<span style="margin:auto; font-size:1rem;">Copié dans le presse papier</span>'+
                        '</p>'
                ).addClass( 'hidden' );

                setTimeout( function() {
                        $( '.copy-message' ).remove();
                        $champACopier.removeClass( 'hidden' );
                }, 1000 );
        });
};

WidgetPhotoPopup.prototype.afficherMetasPlus = function() {
        const lthis         = this;
        const META_LABELS  = {
                'id_obs' : 'observation n°',
                'projet' : 'projet',
                'nom_referentiel' : 'réferentiel',
                'date_obs' : 'date d´observation',
                'nom_sel': 'nom scientifique',
                'nom_sel_nn' : 'nom scientifique n°',
                'nom_ret' : 'nom retenu',
                'nom_ret_nn' : 'nom retenu n°',
                'famille' : 'famille',
                'tags_obs' : 'tags de l´observation',
                'lieudit' : 'lieu dit',
                'station' : 'station',
                'milieu' : 'milieu',
                'latitude' : 'latitude',
                'longitude' : 'longitude',
                'altitude' : 'altitude',
                'localisation_precision': 'précision de la localisation',
                'code_insee' : 'code insee de la commune',
                'dept' : 'département',
                'pays' : 'pays',
                'est_ip_valide' : 'validée sur identiplante',
                'score_ip' : 'score identiplante',
                'url_ip' : 'url identiplante',
                'abondance' : 'abondance',
                'phenologie' : 'phénologie',
                'spontaneite' : 'spontaneite',
                'type_donnees' : 'type de donnees',
                'biblio' : 'bibliographie',
                'source' : 'source',
                'herbier' : 'herbier',
                'observateur' : 'observateur',
                'observateur_structure' : 'structure'
        };

        const $contenuPlusMeta  = $( '#contenu-meta-plus' );
        let degres = $contenuPlusMeta.is( ':visible' ) ? '180' : '0';

        this.rotationFleche( degres );
        $contenuPlusMeta.empty();

        $.each( META_LABELS, function( cle, label ) {
                let idAttr = cle.replace( '_', '-' ),
                        contenu = lthis.obs[cle];

                switch( cle ) {
                        case 'nom_sel':
                                contenu = lthis.afficherLien( lthis.urlLienEflore, contenu );
                                break;

                        case 'nom_ret':
                                let urlEfloreNomRetenu = lthis.urlLienEflore.replace( lthis.obs['nom_sel_nn'], lthis.obs['nom_ret_nn'] );

                                contenu = lthis.afficherLien( urlEfloreNomRetenu, contenu );
                                break;

                        case 'url_ip':
                                contenu = lthis.afficherLien( contenu, contenu );
                                break;

                        case 'est_ip_valide':
                        case 'herbier':
                                if( '0' === contenu ) {
                                        contenu = 'non';
                                }
                                break;

                        case 'date_obs':
                                contenu = lthis.formaterDate( contenu );
                                break;

                        case 'tags_obs':
                                let tagsObsLength = lthis.tagsObs.length;
                                contenu = lthis.tagsObs.join( '<br>' );
                                break;

                        default:
                                break;
                }

                if ( lthis.valOk( contenu ) ) {
                        $contenuPlusMeta.append(
                                '<li id="' + idAttr + '-meta-plus" class="row">'+
                                        '<div class="col-5 label">' + label.charAt( 0 ).toUpperCase() + label.slice( 1 ) + '</div>'+
                                        '<div class="col-7 contenu">' + contenu + '</div>'+
                                '</li>'
                        );
                }
        });

        if( !$contenuPlusMeta.hasClass( 'actif' ) ) {
                $contenuPlusMeta.hide();
        }

        let estVisible = false;

        $( '#plus-meta' ).off( 'click' ).on( 'click', function( event ) {
                event.preventDefault();
                $contenuPlusMeta.toggle( 200, function() {
                        estVisible = $contenuPlusMeta.is( ':visible' );
                        degres     = estVisible ? '180' : '0';
                        $( this ).toggleClass( 'actif', estVisible );
                        lthis.rotationFleche( degres );
                });
        });
};

WidgetPhotoPopup.prototype.rotationFleche = function( degres ) {
        $( '#plus-meta i' ).css({
                '-webkit-transform' : 'rotate('+ degres +'deg)',
                '-moz-transform' : 'rotate('+ degres +'deg)',
                '-ms-transform' : 'rotate('+ degres +'deg)',
                'transform' : 'rotate('+ degres +'deg)'
        });
};

WidgetPhotoPopup.prototype.fournirLienTelechargement = function() {
        const lthis = this;

        $( '#formats' ).on( 'change', function() {
                let format             = ( $( this ).val() || 'O' ),
                        lienTelechargement = lthis.urlBaseTelechargement + lthis.idImage + '?methode=telecharger&format=' + format;

                $( '#telecharger' ).attr( 'href', lienTelechargement );
        });

        $( '#formats' ).trigger( 'change' );
};


WidgetPhotoPopup.prototype.afficherPopupLocalisation = function() {
        const lthis = this;

        $( '#localisation a.bouton' ).on( 'click', function( event ){
                event.preventDefault();

                $( this ).after(
                        '<div id="localisation-map-container">'+
                                '<button id="map-close" type="button" class="bouton btn btn-sm btn-outline-secondary" aria-label="Close">'+
                                        '<span aria-hidden="true">×</span>'+
                                '</button>'+
                                '<div id="localisation-map"></div>'+
                        '</div>'
                );

                let lat = lthis.obs['latitude'],
                        lng = lthis.obs['longitude'],
                        map = L.map( 'localisation-map', {
                                zoomControl: true,
                                dragging: false,
                                scrollWheelZoom: 'center'
                        } ).setView( [lat, lng], 12 );

                map.markers = [];

                L.tileLayer(
                        // 'https://osm.tela-botanica.org/tuiles/osmfr/{z}/{x}/{y}.png',
                        'https://a.tile.openstreetmap.fr/osmfr/{z}/{x}/{y}.png',
                        {
                                attribution: 'Data © <a href="http://osm.org/copyright">OpenStreetMap</a>',
                                maxZoom: 18
                        }
                ).addTo( map );

                map.addLayer( new L.FeatureGroup() );

                let marker = new L.Marker(
                        {
                                'lat': lat,
                                'lng': lng
                        },
                        {
                                draggable: false,
                        }
                );


                map.addLayer( marker );
                map.markers.push( marker );

                $( '#map-close' ).on( 'click', function( event ){
                        $( '#localisation-map-container' ).remove();
                });
        });

        $( '#fenetre-modal' ).on( 'click', function( event ) {
                if(
                        !$( event.target ).closest( '#localisation-map-container' ).length
                        && !$( event.target ).closest( '#obs-localisation' ).length
                ) {
                        $( '#localisation-map-container' ).remove();
                }
        });
};


WidgetPhotoPopup.prototype.regenererMiniature = function() {
        const lthis = this;
        $( '#regenerer-miniature' ).off( 'click' ).on( 'click', function( event ) {
                event.preventDefault();

                let url = lthis.urlServiceRegenererMiniature + lthis.idImage;
                $.get( url, function( data ) {
                                console.log( data );
                        lthis.forcerMajImage(lthis.urlThisImage, lthis.urlTpl);
                        }
                ).fail( function() {
                        console.log( 'La régénération d´image ne s´est pas faite' );
                });
        });
};

WidgetPhotoPopup.prototype.formaterDate = function( sqlDate ) {
        dateFormatee = sqlDate
                .substring( 0, 10 )
                .split( '-' )
                .reverse()
                .join('/');

        return dateFormatee;
};

WidgetPhotoPopup.prototype.afficherLien = function( url, nom ) {
        if( !/https?:\/\//.test( url ) ) {
                url = 'https://' + url;
        }
        return '<a href="' + url + '" target="_blank">' + nom + '</a> ';
};

WidgetPhotoPopup.prototype.fournirLienIdentiplante = function() {
        const lthis = this;
        $( '.signaler-erreur-obs' ).each( function() {
                $( this ).attr( 'href', 'https://' + lthis.urlIP );
        });
};

WidgetPhotoPopup.prototype.initEvtsProtocole = function() {
        const lthis = this;
        $('#bloc-notes-protocole').addClass('hidden');
        lthis.votes = null
        //On transforme la promesse en array
        const PROTOCOLES_ARRAY = Object.values(lthis.protocoles);

        const $select = $('#protocole');
        $select.empty(); // Clear existing options

        // Add the default hidden option
        $select.append('<option value="" selected hidden>Choix du protocole</option>');

        PROTOCOLES_ARRAY.forEach(protocoleData => {
                $select.append(`<option id="protocole_${protocoleData['protocole.id']}" value="protocole_${protocoleData['protocole.id']}">${protocoleData['protocole.intitule']}</option>`);
        })

        $( '#protocole').on( 'change', function( event ){
                event.preventDefault();
                lthis.votes = null

                var id = $(this).children(":selected").attr("id");
                var protocole = id.split("_")[1];

                $('#bloc-notes-protocole').removeClass('hidden');

                // Find the object corresponding to the selected id (protocole.id)
                var selectedProtocoleData = PROTOCOLES_ARRAY.find(protocoleData => protocoleData['protocole.id'] === protocole);

                lthis.protocole = selectedProtocoleData['protocole.id'];
                const message = selectedProtocoleData['protocole.descriptif'];

                $('#message-protocole').html('<p>' + message + '</p>');

                // On envoie le protocole sélectionné à la partie "vote"
                // On récupère tous les votes de l'image depuis pictoflora
                lthis.votes = lthis.getVotes(lthis.protocole)

                // Si l'utilisateur est connect, on vérifie s'il a déjà voté pour cette image et on affiche les étoiles
                // correspondantes
                if(lthis.userId){
                        lthis.checkUserVote(lthis.userId, lthis.protocole, lthis.votes);
                } else {
                        lthis.voteId = null;
                        lthis.removeVoteStars()
                }

                // Remove any previous click event listeners on rating stars
                for (let i=1; i<=5; i++){
                        $("#rating-star-"+i).off("click");
                }

                // Si l'utilisateur vote, on affiche les étoiles correspondantes et on l'envoie vers pictoflora
                lthis.traiterVote();
        });
}

WidgetPhotoPopup.prototype.traiterVote = function () {
        const lthis = this;
        let starSelected = 0
        let mode = '';

        $("#note").attr("value", -1);

        // Traitement du bouton suppression du vote
        $("#note-remove").click(function (){
                lthis.removeVoteStars();
                mode = 'DELETE';
                // On n'envoie le vote que si l'utilisateur est connecté
                if (lthis.userId) {
                        lthis.sendVote(lthis.userId, lthis.protocole, starSelected, mode, lthis.voteId);
                }
        })

        // Si l'utilisateur a déjà voté pour cette image on affiche son vote et on passe en mode modification
        let userAVoter = lthis.checkUserVote(lthis.userId, lthis.protocole, lthis.votes);
        userAVoter ? mode = 'POST' : mode = 'PUT';

        // Affichage du nombre d'étoiles sélectionnées et envoi du vote
        for (let i=1; i<=5; i++){
                $("#rating-star-"+i).click(function () {
                        starSelected = i
                        lthis.displayVote(starSelected);
                        $("#note").attr("value", starSelected);
                        // On n'envoie le vote que si l'utilisateur est connecté
                        if (lthis.userId){
                                lthis.sendVote(lthis.userId, lthis.protocole, starSelected, mode);
                        }
                });
        }
};

// Envoi du vote vers la fonction sendVote() du fichier php
WidgetPhotoPopup.prototype.sendVote = function (userId, protocole, note, mode, voteId){
        const lthis = this;

        var xhttp = new XMLHttpRequest();
        xhttp.onreadystatechange = function() {
                if (this.readyState == 4 && this.status == 200) {
                        let votesUrl = lthis.urlServiceDel + 'images/' + lthis.idImage + '/votes';
                        // Récupération des données et maj de l'affichage
                        lthis.envoyerVersService('GET', votesUrl, null, null, function (erreur, data) {
                                if (erreur) {
                                        console.error("Erreur lors de la requête :", erreur);
                                } else {
                                        lthis.item["votes"] = Object.values(data['resultats']);
                                        lthis.getVotes(protocole)
                                }
                        });
                        console.log('vote envoyé')
                }
        };

        var url = "../widget:cel:photo/";

        // Convertir les données en une chaîne JSON pour les envoyer dans le corps de la requête
        var data = {
                idImage: this.idImage,
                mode: mode,
                user: userId,
                protocole: protocole,
                vote: note,
                voteId: voteId
        }
        var jsonData = JSON.stringify(data);

        xhttp.open("POST", url+"?action=send_pf_vote", true);
        xhttp.setRequestHeader("Content-Type", "application/json");
        xhttp.send(jsonData);
}

WidgetPhotoPopup.prototype.getVotes = function (protocoleId){
        let votes = Object.values(this.item["votes"]);
        let noteMoyenne = 0;
        let nombreVotes= 0;
        let noteTotal = 0;
        let itemVotes = [];

        votes.forEach(vote => {
                if (vote["protocole.id"] == protocoleId){
                        nombreVotes++
                        noteTotal += parseInt(vote["vote"]);
                        noteMoyenne = (noteTotal / nombreVotes).toFixed(1)
                        itemVotes.push(vote);
                }
        })

        let elementNoteMoyenne = $("#note-moyenne .contenu");
        elementNoteMoyenne.text(noteMoyenne);

        let elementNoteCount = $("#note-count .contenu");
        elementNoteCount.text(nombreVotes);

        return itemVotes;
}

WidgetPhotoPopup.prototype.displayVote = function (note){
        lthis.removeVoteStars();

        for (let i=1; i<=5; i++){
                for (let j=1; j<=note; j++){
                        $("#rating-star-"+j).removeClass('far').addClass('fa').css("color", "#c3d45d");
                }
        }
}

WidgetPhotoPopup.prototype.removeVoteStars = function (){
        $(".notation-star").removeClass('fa').addClass('far').css("color", "grey");
        $("#note").attr("value", -1);
}

WidgetPhotoPopup.prototype.checkUserVote = function (userId, protocoleId, votes){
        let userVote = null;

        votes.forEach(vote => {
                if (vote["protocole.id"] == protocoleId && vote["auteur.id"] == userId){
                        userVote = vote;
                }
        })

        if (userVote){
                this.displayVote(userVote['vote']);
                // this.traiterVote()
                this.voteId = userVote['vote.id'];

                return true
        } else {
                this.voteId = null;
                this.removeVoteStars()
        }
}

WidgetPhotoPopup.prototype.pivoterImage = function() {
        lthis = this;

        let newCel = lthis.urlServiceNewCel + "photo_rotations?photoId=" + lthis.idImage + "&degrees=";
        let url = '';

        $( '#pivoter-droite' ).off( 'click' ).on( 'click', function( event ) {
                event.preventDefault();

                url = "";
                lthis.pivoter('droite');
                url = newCel + "-90";
                // lthis.envoyerVersService('GET', url, lthis.token )

                lthis.envoyerVersService('GET', url, lthis.token, null, function (erreur, cb) {
                        lthis.forcerMajImage(lthis.urlThisImage, lthis.urlTpl);
                });

                // lthis.forcerMajImage(lthis.urlThisImage);
        });

        $( '#pivoter-gauche' ).off( 'click' ).on( 'click', function( event ) {
                event.preventDefault();

                url = "";
                lthis.pivoter('gauche');
                url = newCel + "90";
                lthis.envoyerVersService('GET', url, lthis.token, null, function (erreur, cb) {
                        lthis.forcerMajImage(lthis.urlThisImage, lthis.urlTpl);
                });
        });
};

WidgetPhotoPopup.prototype.pivoter = function(direction) {
        let imageSelected = $('img[src="' + lthis.urlThisImage + '"]').attr('id');
        let angle = $('#' + imageSelected).data('angle');

        if (angle == 360 || angle == (-360) || angle == undefined){
                angle = 0
        }
        if (direction == 'droite'){
                angle += 90;
        } else {
                angle -= 90;
        }

        $('#' + imageSelected).css("transform", "rotate(" + angle + "deg) ");
        $('#' + imageSelected).data('angle', angle);
}

WidgetPhotoPopup.prototype.forcerMajImage = function (urlImage, urlTpl){
        var indexPourcentage = urlTpl.indexOf('%');
        urlTpl = urlTpl.substring(0, indexPourcentage);

        // Sélectionne l'élément img avec l'attribut src égal à this.urlImage
        var $image = $('img[src^="' +  urlTpl + '"]');

        // Ajoute un paramètre unique à l'URL pour éviter le cache
        var newSrc = urlImage + '?timestamp=' + new Date().getTime();

        // Met à jour l'attribut 'src' de l'image avec la nouvelle URL
        $image.attr('src', newSrc);
}

WidgetPhotoPopup.prototype.initEvtsToggleVolet = function (){
        lthis = this;

        $('#hide-metas-div').off('click').on('click', function () {
                $('#hide-metas-div').toggleClass('volet-hidden')
                $('#hide-metas i').toggleClass('fa-angle-double-left')
                $('#hide-metas i').toggleClass('fa-angle-double-right')
                if ($('#hide-metas-div').hasClass('volet-hidden')){
                        $('#hide-metas').attr('title', "Afficher le volet d'information")
                } else {
                        $('#hide-metas').attr('title', "Cacher le volet d'information")
                }

                $( '#volet, #retour-galerie' ).toggleClass( 'hidden' );
                $( '#boutons-footer, #info-img-galerie' ).toggleClass( 'col-lg-8' );
        })
}