IdentifiantMot de passe
Loading...
Mot de passe oublié ?Je m'inscris ! (gratuit)
Navigation

Inscrivez-vous gratuitement
pour pouvoir participer, suivre les réponses en temps réel, voter pour les messages, poser vos propres questions et recevoir la newsletter

JavaScript Discussion :

Conserver les données du formulaire après un refresh


Sujet :

JavaScript

  1. #21
    Membre du Club
    Homme Profil pro
    Développeur Web
    Inscrit en
    Juin 2020
    Messages
    119
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Âge : 35
    Localisation : France, Oise (Picardie)

    Informations professionnelles :
    Activité : Développeur Web

    Informations forums :
    Inscription : Juin 2020
    Messages : 119
    Points : 64
    Points
    64
    Par défaut
    Merci pour ta réponse, effectivement cela fonctionne

    Mais il me semble pas que ta méthode me permette de récupérer le chrono qui défile dans le DOM car ce qu'on a stocké dans le storage est la date /l'heure de fin du chrono. J'ai besoin de récupérer le chrono qui continue de défiler depuis le storage (ou depuis un autre endroit mais je ne vois pas du tout), et pas la date / heure de fin. Est-ce que je peux cependant déclarer un autre sessionStorage pour stocker le chrono en temps réel et pouvoir le récupérer après un refresh ?

  2. #22
    Membre éclairé
    Femme Profil pro
    Autre
    Inscrit en
    Janvier 2017
    Messages
    335
    Détails du profil
    Informations personnelles :
    Sexe : Femme
    Localisation : France, Nord (Nord Pas de Calais)

    Informations professionnelles :
    Activité : Autre

    Informations forums :
    Inscription : Janvier 2017
    Messages : 335
    Points : 715
    Points
    715
    Par défaut
    Bonjour,
    Citation Envoyé par Lunesti Voir le message
    ...cela fonctionne
    Mais...
    En clair :
    1) Le résultat est-il parfaitement conforme à ce qui est souhaité ?
    Par exemple, si on rafraîchit à 9h55m30s et que l'heure de fin enregistrée est 10h, alors le chronomètre démarrera à 4m30s : cela convient-il ?

    2) La méthode est-elle conforme à ce qui est attendu ? (Vu que c'est sans doute pour un exercice, cette histoire de réservation de vélos étant récurrente sur le forum.)
    Parce que je vous sens réfractaire à cette méthode basée sur la date, indépendamment du fait qu'elle donne le bon résultat.

    Citation Envoyé par Lunesti Voir le message
    J'ai besoin de récupérer le chrono qui continue de défiler depuis le storage (ou depuis un autre endroit mais je ne vois pas du tout), et pas la date / heure de fin.
    Quand la page est déchargée, le chronomètre ne pourra pas continuer à tourner dans le "storage" en attendant qu'on revienne sur la page.
    Donc si on ne mémorise pas la date de fin, l'alternative est le temps restant, sachant que, dans ce cas, si la page met une seconde à se recharger, le temps total d'attente aura été augmenté d'une seconde.

  3. #23
    Membre du Club
    Homme Profil pro
    Développeur Web
    Inscrit en
    Juin 2020
    Messages
    119
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Âge : 35
    Localisation : France, Oise (Picardie)

    Informations professionnelles :
    Activité : Développeur Web

    Informations forums :
    Inscription : Juin 2020
    Messages : 119
    Points : 64
    Points
    64
    Par défaut
    Merci pour ta réponse !

    Citation Envoyé par Loralina Voir le message

    En clair :
    1) Le résultat est-il parfaitement conforme à ce qui est souhaité ?
    Oui, j'ai bien la date et l'heure de fin qui s'affiche sur mon storage. En revanche je rencontre quelques difficultés pour placer ces fonctions:
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    window.addEventListener("beforeunload", function (event) {}
    et
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    window.addEventListener("load", function (event) {}
    car elles fonctionnent qu'à partir de cette instance:

    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
     const chrono = new Chrono(20);
            chrono.startTimer();
    mais j'ai créé cette instance dans une autre class qui est Réservation.Car c'est dans cette class que j'appel ma class Chrono. Donc je déduis qu'il faut mettre ces 2 events dans ma class Réservation pour que ça fonctionne , comme ceci :

    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    15
    16
    17
    18
    19
    20
    21
    22
    23
    24
    25
    26
    27
    28
    29
    30
    31
    32
    33
    34
    35
    36
    37
    38
    39
    40
    41
    42
    43
    44
    45
    46
    47
    48
    class Reservation {
     
        constructor(station, min, sec) {
            this.station = station;
            this.min = min;
            this.sec = sec;
            this.status = Dom.textChronoElement;
        }
     
        storeDatas() {
            const storage = new Storage(this.station);
            storage.dataRecord(this.station);
        }
     
        startReservation() {
            console.log('chrono');
            const chrono = new Chrono(20);
            chrono.startTimer();
     
            window.addEventListener("beforeunload", function(event) {
                console.log('temps restant > 0')
                    // récup. du temps restant
                const tempsRestant = chrono.timeEnd - Date.now();
                if (tempsRestant > 0) {
                    console.log('temps > 0')
     
                    // store date de fin du chrono en millisecondes
                    sessionStorage.setItem("timeEnd", chrono.timeEnd);
                    // juste pour voir clairement la date dans le storage
                    sessionStorage.setItem("dateEnd", new Date(chrono.timeEnd));
                } else {
                    sessionStorage.clear();
                }
                window.addEventListener("load", function(event) {
     
                    // read date de fin du chrono en millisecondes
                    // Attention cast string to number avec l'unary plus (+)
                    const timeEnd = +sessionStorage.getItem("timeEnd");
                    const tempsRestant = timeEnd - Date.now();
                    if (tempsRestant > 0) {
                        Dom.textChronoElement.style.display = 'inline';
                        // relance timer avec date de fin de chrono
                        chrono.startTimer(timeEnd);
                    }
                });
            });
        }
    }

    Le problème étant que cela soit situé en dehors de ma class Chrono() , les conditions de refresh ne devraient normalement pas se situer dans ma class Réservation mais (je pense) dans ma class Chrono()...



    Citation Envoyé par Loralina Voir le message
    Par exemple, si on rafraîchit à 9h55m30s et que l'heure de fin enregistrée est 10h, alors le chronomètre démarrera à 4m30s : cela convient-il ?

    Il faut que, lors du refresh je mette un display 'inline' sur le texte affichant le chrono pour que celui-ci s'affiche (car il est caché de base) mais je ne sais pas trop dans quelle fonction mettre ce display inline.

    Citation Envoyé par Loralina Voir le message

    2) La méthode est-elle conforme à ce qui est attendu ? (Vu que c'est sans doute pour un exercice, cette histoire de réservation de vélos étant récurrente sur le forum.)
    Parce que je vous sens réfractaire à cette méthode basée sur la date, indépendamment du fait qu'elle donne le bon résultat.
    Au début je ne savais pas qu'on pouvait fonctionner de cette façon, j'étais fixé par l'idée que le chrono 'en temps réel' devait s'afficher dans le sessionStorage et que lorsqu'on actualise le chrono continue de s'écouler. Mais ce n'était sans doute pas ce qu'il fallait faire, j'ai appris qu'on pouvait faire autrement, comme la solution de No smoking.


    Citation Envoyé par Loralina Voir le message
    Quand la page est déchargée, le chronomètre ne pourra pas continuer à tourner dans le "storage" en attendant qu'on revienne sur la page.
    Donc si on ne mémorise pas la date de fin, l'alternative est le temps restant, sachant que, dans ce cas, si la page met une seconde à se recharger, le temps total d'attente aura été augmenté d'une seconde.
    Ok j'ai compris, nous ne pouvons pas stocker le chrono en temps réel dans le storage mais plutôt la date et l'heure de fin. Cela dit le compteur doit s'afficher dans mon HTML même lorsqu'on refresh.

  4. #24
    Membre éclairé
    Femme Profil pro
    Autre
    Inscrit en
    Janvier 2017
    Messages
    335
    Détails du profil
    Informations personnelles :
    Sexe : Femme
    Localisation : France, Nord (Nord Pas de Calais)

    Informations professionnelles :
    Activité : Autre

    Informations forums :
    Inscription : Janvier 2017
    Messages : 335
    Points : 715
    Points
    715
    Par défaut
    D'accord, je comprends mieux les problématiques.
    Je n'ai pas regardé en détail le code, d'où le fait que je ne donnerai pas de consignes pour structurer l'ensemble.
    J'ai simplement fait ceci :
    J'ai copié-collé les codes de NoSmoking et la classe Reservation que vous venez de mettre.
    J'ai fait quelques adaptations pour avoir quelque chose de fonctionnel dans le cadre d'un exemple minimaliste réalisé en quelques minutes, donc pas du grand art.
    Il s'agit uniquement de donner quelques pistes de réflexion.

    Citation Envoyé par Lunesti Voir le message
    Le problème étant que cela soit situé en dehors de ma class Chrono() , les conditions de refresh ne devraient normalement pas se situer dans ma class Réservation mais (je pense) dans ma class Chrono()...
    Pas forcément.
    Il est bien d'avoir une classe Chrono la plus pure/indépendante possible.

    Citation Envoyé par Lunesti Voir le message
    Il faut que, lors du refresh je mette un display 'inline' sur le texte affichant le chrono pour que celui-ci s'affiche (car il est caché de base) mais je ne sais pas trop dans quelle fonction mettre ce display inline.
    Dans mon exemple, je l'ai mis dans le constructeur de Chrono, mais idéalement, je le mettrais plutôt en dehors.
    D'ailleurs, je passerais plutôt l'élément cible au niveau des paramètres.

    Voilà mon code de test :
    Code HTML : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    15
    16
    17
    18
    19
    20
    21
    22
    23
    24
    25
    26
    27
    28
    29
    30
    31
    32
    33
    34
    35
    36
    37
    38
    39
    40
    41
    42
    43
    44
    45
    46
    47
    48
    49
    50
    51
    52
    53
    54
    55
    56
    57
    58
    59
    60
    61
    62
    63
    64
    65
    66
    67
    68
    69
    70
    71
    72
    73
    74
    75
    76
    77
    78
    79
    80
    81
    82
    83
    84
    85
    86
    87
    88
    89
    90
    91
    92
    93
    94
    95
    96
    97
    98
    99
    100
    101
    102
    103
    104
    105
    106
    107
    108
    109
    110
    111
    112
    113
    <head>
    <style>
    #time {
            display:inline;
    }
    </style>
    <script>
    class Chrono {
            constructor(minutes = 0, secondes = 0) {
                    this.elem = document.querySelector('#time');
                    this.elem.style.display=""; //l'affichage par défaut s'applique
                    this.duree = ((minutes * 60) + secondes) * 1000;
                    this.iTimer = null;
                    this.timeEnd;
            }
     
            startTimer(timeEnd) {
                    if( timeEnd) {
                            this.timeEnd = timeEnd;
                    }
                    else {
                            this.timeEnd = Date.now() + this.duree;
                    }
                    this.iTimer = setInterval(() => {
                            this.decompteTimer();
                    }, 1000);
                    this.decompteTimer();
            }
     
            stopTimer() {
                    clearInterval(this.iTimer);
            }
     
            decompteTimer() {
                    const reste = Math.ceil((this.timeEnd - Date.now()) / 1000);
                    if (reste > 0) {
                            const h = ("00" + parseInt(reste / 3600, 10)).slice(-2);
                            const m = ("00" + parseInt((reste % 3600) / 60, 10)).slice(-2);
                            const s = ("00" + parseInt((reste % 3600) % 60, 10)).slice(-2);
                            this.elem.textContent = h + ":" + m + ":" + s;
                    }
                    else {
                            clearInterval(this.iTimer);
                            this.elem.textContent = "Comptage terminé !";
                    }
            }
    }
     
    class Reservation {
            constructor(station, min, sec) {
                    this.station = station;
                    this.min = min;
                    this.sec = sec;
                    //this.status = Dom.textChronoElement; /!\/!\/!\ ligne désactivée pour le test
            }
     
            storeDatas() {
                    const storage = new Storage(this.station);
                    storage.dataRecord(this.station);
            }
     
            startReservation() {
                    console.log('chrono');
                    const chrono = new Chrono(20);
                    chrono.startTimer();
     
                    window.addEventListener("beforeunload", function (event) {
                            // récup. du temps restant
                            const tempsRestant = chrono.timeEnd - Date.now();
                            if (tempsRestant > 0){
                                    // store date de fin du chrono en millisecondes
                                    sessionStorage.setItem( "timeEnd", chrono.timeEnd);
                                    // juste pour voir clairement la date dans le storage
                                    sessionStorage.setItem( "dateEnd", new Date( chrono.timeEnd));
                            }
                            else {
                                    sessionStorage.clear();
                            }
                    });
            }
     
            checkReservation() {
                    // read date de fin du chrono en millisecondes
                    // Attention cast string to number avec l'unary plus (+)
                    const timeEnd = +sessionStorage.getItem( "timeEnd");
                    const tempsRestant = timeEnd - Date.now();
                    if( tempsRestant > 0){
                            const chrono = new Chrono();
                            // relance timer avec date de fin de chrono
                            chrono.startTimer(timeEnd);
                            return true;
                    }
                    return false;
            }
    }
     
    window.addEventListener("load", function (event) {
            const ob_buttonStart=document.getElementById("buttonStart");
            if(ob_reservation.checkReservation()===false) {
                    ob_buttonStart.addEventListener("click",function (event) {
                            this.disabled=true;
                            ob_reservation.startReservation();
                    });
            }
            else {
                    ob_buttonStart.disabled=true;
            }
    });
    const ob_reservation=new Reservation("test",20,0);
    </script>
    </head>
    <div id="time" style="display:none;"></div>
    <input type="button" id="buttonStart" value="Démarrer">

  5. #25
    Membre du Club
    Homme Profil pro
    Développeur Web
    Inscrit en
    Juin 2020
    Messages
    119
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Âge : 35
    Localisation : France, Oise (Picardie)

    Informations professionnelles :
    Activité : Développeur Web

    Informations forums :
    Inscription : Juin 2020
    Messages : 119
    Points : 64
    Points
    64
    Par défaut
    Ça fonctionne, merci beaucoup !

    Pour l'affichage du chrono je l'ai inséré dans la fonction decompteTimer()

    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    decompteTimer() {
            const reste = Math.ceil((this.timeEnd - Date.now()) / 1000);
            if (reste > 0) {
                Dom.textChronoElement.style.display = 'inline';
                const h = ("00" + parseInt(reste / 3600, 10)).slice(-2);
                const m = ("00" + parseInt((reste % 3600) / 60, 10)).slice(-2);
                const s = ("00" + parseInt((reste % 3600) % 60, 10)).slice(-2);
                Dom.minElement.textContent = m + ":";
                Dom.secElement.textContent = s;
            } else {
                clearInterval(this.iTimer);
                Dom.textChronoElement.textContent = "Comptage terminé !";
            }
        }
    Maintenant Je dois stopper le chrono lors du clique sur le bouton Annuler et récupérer les données via une API Ajax

    Sujet Résolu

  6. #26
    Membre éclairé
    Femme Profil pro
    Autre
    Inscrit en
    Janvier 2017
    Messages
    335
    Détails du profil
    Informations personnelles :
    Sexe : Femme
    Localisation : France, Nord (Nord Pas de Calais)

    Informations professionnelles :
    Activité : Autre

    Informations forums :
    Inscription : Janvier 2017
    Messages : 335
    Points : 715
    Points
    715
    Par défaut
    Bonjour,
    Citation Envoyé par Lunesti Voir le message
    Ça fonctionne
    Chouette !

    Citation Envoyé par Lunesti Voir le message
    Pour l'affichage du chrono je l'ai inséré dans la fonction decompteTimer()
    Ce serait mieux dans startTimer.

  7. #27
    Membre du Club
    Homme Profil pro
    Développeur Web
    Inscrit en
    Juin 2020
    Messages
    119
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Âge : 35
    Localisation : France, Oise (Picardie)

    Informations professionnelles :
    Activité : Développeur Web

    Informations forums :
    Inscription : Juin 2020
    Messages : 119
    Points : 64
    Points
    64
    Par défaut
    Citation Envoyé par Loralina Voir le message
    Ce serait mieux dans startTimer.
    Ca marche aussi merci

  8. #28
    Membre du Club
    Homme Profil pro
    Développeur Web
    Inscrit en
    Juin 2020
    Messages
    119
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Âge : 35
    Localisation : France, Oise (Picardie)

    Informations professionnelles :
    Activité : Développeur Web

    Informations forums :
    Inscription : Juin 2020
    Messages : 119
    Points : 64
    Points
    64
    Par défaut
    Le sujet initial étant résolu je rencontre tout de même encore une difficulté lorsque qu'il s'agit d'arrêter le chrono 'manuellement'.

    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
     cancel() {
            Dom.cancelButtonElement.addEventListener('click', () => {
                const stopChrono = new Chrono();
                stopChrono.stopTimer();
                Dom.textChronoElement.textContent = "Réservation annulée";
                console.log('Annuler la réservation')
                    //On ajoute un vélo à la station
                this.station.addBike();
                Dom.availableBikesElement.innerHTML = this.station.getAvailableBikes();
            });
        }
    Tout mes gestionnaires d'évènements sont dans ma class Formulaire (pour une question de cohérence) donc pour cibler une méthode dans la class Chrono() je crée une nouvelle instance.

    Lorsque je clique sur annuler, j'appel la méthode stopTimer() mais cela ne fonctionne pas. J'ai ce message dans la console

    Nom : chronoEvent.png
Affichages : 98
Taille : 2,2 Ko

    le nombre tout à gauche défile toute les secondes, je dois en conclure que mon chrono est toujours actif.

    Une idée d'où cela pourrait venir ?


    Ma class chrono



    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    15
    16
    17
    18
    19
    20
    21
    22
    23
    24
    25
    26
    27
    28
    29
    30
    31
    32
    33
    34
    35
    36
    37
    38
    39
    40
    41
    42
    43
    44
    45
    46
    class Chrono {
        constructor(minutes = 0, secondes = 0) {
            //this.elem = document.querySelector('#time');
            Dom.textChronoElement.style.display = ""; //l'affichage par défaut s'applique
            this.duree = ((minutes * 60) + secondes) * 1000;
            this.iTimer = null;
            this.timeEnd;
        }
     
        startTimer(timeEnd) {
            if (timeEnd) {
                Dom.textChronoElement.style.display = 'inline';
                this.timeEnd = timeEnd;
            } else {
                this.timeEnd = Date.now() + this.duree;
            }
            this.iTimer = setInterval(() => {
                this.decompteTimer();
            }, 1000);
            //this.iTimer = setInterval(this.decompteTimer.bind(this), 1000);
            // this.decompteTimer();
        }
     
        stopTimer() {
            clearInterval(this.iTimer);
        }
     
        decompteTimer() {
            const reste = Math.ceil((this.timeEnd - Date.now()) / 1000);
            if (reste > 0) {
                Dom.reserveElement.style.display = 'none';
                Dom.cancelButtonElement.style.display = 'flex';
     
                //const h = ("00" + parseInt(reste / 3600, 10)).slice(-2);
                const m = ("00" + parseInt((reste % 3600) / 60, 10)).slice(-2);
                const s = ("00" + parseInt((reste % 3600) % 60, 10)).slice(-2);
                Dom.minElement.textContent = m + ":";
                Dom.secElement.textContent = s;
            } else {
                clearInterval(this.iTimer);
                Dom.textChronoElement.textContent = "Comptage terminé !";
                Dom.reserveElement.style.display = 'block';
                Dom.cancelButtonElement.style.display = 'none';
            }
        }
    }

  9. #29
    Membre éclairé
    Femme Profil pro
    Autre
    Inscrit en
    Janvier 2017
    Messages
    335
    Détails du profil
    Informations personnelles :
    Sexe : Femme
    Localisation : France, Nord (Nord Pas de Calais)

    Informations professionnelles :
    Activité : Autre

    Informations forums :
    Inscription : Janvier 2017
    Messages : 335
    Points : 715
    Points
    715
    Par défaut
    Bonjour,
    Citation Envoyé par Lunesti Voir le message
    pour cibler une méthode dans la class Chrono() je crée une nouvelle instance.
    La propriété iTimer de la nouvelle instance sera propre à cette instance.
    A moins de lui donner la même valeur, la fonction clearInterval ne recevra pas le bon identifiant.

    Une solution assez simple est de définir une seule instance au niveau global et d'utiliser toujours la même ensuite.
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    const chrono = new Chrono(20);
    window.addEventListener("load", function (event) {
    ou (selon ce qu'il y a dans le constructeur) :
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    let chrono;
    window.addEventListener("load", function (event) {
    chrono = new Chrono(20);
    Une solution plus aboutie conceptuellement pourrait être de définir l'instance comme une propriété de classe, mais derrière il faut réussir à y accéder aux endroits du code où on en a besoin...

    Citation Envoyé par Lunesti Voir le message
    J'ai ce message dans la console
    C'est sans doute une conséquence de l'instruction Dom.textChronoElement.textContent = "Réservation annulée"; qui a retiré des éléments html auxquels se réfère le chronomètre qui continue de tourner (l'erreur serait au niveau de Dom.minElement qui est peut-être une propriété statique accessible en GET).

    Citation Envoyé par Lunesti Voir le message
    Ma class chrono
    A soigner et épurer, exemple :
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    15
    16
    17
    18
    19
    20
    21
    22
    23
    24
    25
    26
    27
    28
    29
    30
    31
    32
    33
    34
    35
    36
    37
    38
    39
    40
    class Chrono {
    	constructor(minutes = 0, secondes = 0) {
    		this.duree = ((minutes * 60) + secondes) * 1000;
    		this.iTimer = null;
    		this.timeEnd = null;
    	}
     
    	startTimer(timeEnd) {
    		Dom.textChronoElement.style.display = 'inline';
    		Dom.reserveElement.style.display = 'none';
    		Dom.cancelButtonElement.style.display = 'flex';
    		if (timeEnd) {
    			this.timeEnd = timeEnd;
    		} else {
    			this.timeEnd = Date.now() + this.duree;
    		}
    		this.iTimer = setInterval(() => {
    			this.decompteTimer();
    		}, 1000);
    		this.decompteTimer();
    	}
     
    	stopTimer() {
    		clearInterval(this.iTimer);
    		this.iTimer=null;
    	}
     
    	decompteTimer() {
    		const reste = Math.ceil((this.timeEnd - Date.now()) / 1000);
    		if (reste > 0) {
    			Dom.minElement.textContent = ('0' + parseInt((reste % 3600) / 60, 10)).slice(-2) + ':';
    			Dom.secElement.textContent = ('0' + parseInt((reste % 3600) % 60, 10)).slice(-2);
    		} else {
    			this.stopTimer();
    			Dom.textChronoElement.textContent = 'Comptage terminé !';
    			Dom.reserveElement.style.display = 'block';
    			Dom.cancelButtonElement.style.display = 'none';
    		}
    	}
    }
    On peut aussi ajouter un contrôle en cas de double appel à startTimer.
    D'un point de vue conceptuel, il pourrait être mieux que la classe Formulaire gère tous les affichages...

  10. #30
    Modérateur

    Avatar de NoSmoking
    Homme Profil pro
    Inscrit en
    Janvier 2011
    Messages
    16 959
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Localisation : France, Isère (Rhône Alpes)

    Informations forums :
    Inscription : Janvier 2011
    Messages : 16 959
    Points : 44 122
    Points
    44 122
    Par défaut
    Tu t'évertues à surcharger ta classe Chrono, ou alors il fallait en faire « un vrai composant », je présumes que la méthode cancel() est ajouté à celle-ci, pourquoi tu disposes déjà de la méthode stopTimer().

    Quelque chose comme
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
    stopTimer() {
      clearInterval(this.iTimer);
      this.elem.textContent = "Comptage annulé !";
      // ici action sur réservation
      reservation.clear(); // à adapter
    }
    C'est dans cette dernière que tu dois réaliser ton action d'annulation ou faire appel à une action/fonction qui prend en charge la « fermeture » de ton Chrono et le « clear » de ta réservation.

    Remarques :
    #1 :
    Dans ta méthode cancel() tu mets en place l'observateur d'événement mais celui-ci n'est pas appelé, donc rien ne se passe tant que le bouton n'est pas cliqué.

    #2 :
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    const stopChrono = new Chrono();
    stopChrono.stopTimer();
    là tu crées un nouveau Chrono mais tu n'interagis pas avec celui en cours.

  11. #31
    Membre du Club
    Homme Profil pro
    Développeur Web
    Inscrit en
    Juin 2020
    Messages
    119
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Âge : 35
    Localisation : France, Oise (Picardie)

    Informations professionnelles :
    Activité : Développeur Web

    Informations forums :
    Inscription : Juin 2020
    Messages : 119
    Points : 64
    Points
    64
    Par défaut
    Merci pour ta réponse ,

    Citation Envoyé par Loralina Voir le message
    C'est sans doute une conséquence de l'instruction Dom.textChronoElement.textContent = "Réservation annulée"; qui a retiré des éléments html auxquels se réfère le chronomètre qui continue de tourner (l'erreur serait au niveau de Dom.minElement qui est peut-être une propriété statique accessible en GET).
    En effet j'avais un élément DOM dont je modifiais la valeur mais j'ai ajouté un autre ID pour ne pas à avoir à modifier celui existant et je n'ai plus ce problème.

    La propriété iTimer de la nouvelle instance sera propre à cette instance.
    A moins de lui donner la même valeur, la fonction clearInterval ne recevra pas le bon identifiant.

    Une solution assez simple est de définir une seule instance au niveau global et d'utiliser toujours la même ensuite.
    J'essaye de comprendre.

    La solution c'est de définir une instance global donc par exemple en dessous d'une class (ex)

    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    15
    16
     
    class Chrono {
        constructor() {
     
        }
     
            }
        }
    }
     
    //portée global
     
    const chrono = new Chrono(20);
    window.addEventListener("load", function(event) {
        //Code
    });
    En quoi le fait de créer une instance à l'extérieur d'une class va me permettre de récupérer ce dont j'ai besoin, à savoir la foncton stopTimer() ? car dans tout les cas, je vais devoir écrire quelque chose du type
    Et cela reviendrait au même que précédemment, à savoir que la méthode stopTimer() ne sera pas lu.

    Et puis, pourquoi déclarer un évènement onload sachant que je veux simplement faire une action lors d'un clique ? (désolé si ça peut paraître évident pour certains mais je suis encore à mes débuts en javascript^^)


    Une solution plus aboutie conceptuellement pourrait être de définir l'instance comme une propriété de classe, mais derrière il faut réussir à y accéder aux endroits du code où on en a besoin...

    D'un point de vue conceptuel, il pourrait être mieux que la classe Formulaire gère tous les affichages...
    Oui c'est pas faux je vais essayer de trier tout ça

  12. #32
    Membre éclairé
    Femme Profil pro
    Autre
    Inscrit en
    Janvier 2017
    Messages
    335
    Détails du profil
    Informations personnelles :
    Sexe : Femme
    Localisation : France, Nord (Nord Pas de Calais)

    Informations professionnelles :
    Activité : Autre

    Informations forums :
    Inscription : Janvier 2017
    Messages : 335
    Points : 715
    Points
    715
    Par défaut
    Citation Envoyé par Lunesti Voir le message
    En effet j'avais un élément DOM dont je modifiais la valeur mais j'ai ajouté un autre ID pour ne pas à avoir à modifier celui existant et je n'ai plus ce problème.
    A voir... (ce qui ne veut pas dire que j'ai envie de voir )

    Citation Envoyé par Lunesti Voir le message
    La solution c'est de définir une instance global donc par exemple en dessous d'une class (ex)
    C'est une solution. Elle est simple, à défaut d'être la meilleure, mais au moins elle permet d'avancer et aussi de comprendre certaines notions.

    Citation Envoyé par Lunesti Voir le message
    En quoi le fait de créer une instance à l'extérieur d'une class va me permettre de récupérer ce dont j'ai besoin, à savoir la foncton stopTimer() ? car dans tout les cas, je vais devoir écrire quelque chose du type
    Et cela reviendrait au même que précédemment, à savoir que la méthode stopTimer() ne sera pas lu.
    La fonction stopTimer était lue, mais le this ne se référait pas au même objet.

    Le problème est de se lancer dans des classes, tout ça, sans maîtriser des notions de base et surtout savoir trouver les erreurs.
    Comment savoir si une fonction est appelée ?
    Comment savoir si une valeur est correcte ?
    En faisant des affichages.
    Exemple :
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    	startTimer(timeEnd) {
    		//...
    		this.iTimer = setInterval(() => {
    			this.decompteTimer();
    		}, 1000);
    console.log("startTimer this.iTimer",this.iTimer);
    		this.decompteTimer();
    	}
    	stopTimer() {
    console.log("stopTimer this.iTimer",this.iTimer);
    		clearInterval(this.iTimer);
    		this.iTimer=null;
    	}
    Ensuite, pour mieux comprendre certaines problématiques, il faut sortir de votre projet et faire des tests simples à part.
    Ce que vous avez fait revient à :
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
    //a et b sont des instances de la même classe
    const a={};
    const b={};
    a.iTimer=setInterval(function(){alert(123)},2000);
    b.iTimer=null;
    clearInterval(b.iTimer); //ça n'arrêtera rien
    Citation Envoyé par Lunesti Voir le message
    Et puis, pourquoi déclarer un évènement onload sachant que je veux simplement faire une action lors d'un clique ?
    Le onload ici sera utile pour y placer du code qui doit être exécuté une fois la page chargée.
    Par exemple, si on veut accéder à un élément de la page et que cet élément est défini après la balise <script> où on met le code, alors on ne peut pas cibler tout de suite cet élément vu qu'il n'existe pas encore.
    Dans mon exemple, j'ai mis le onload par rapport à l'exemple que j'avais précédemment donné, simplement pour situer où placer la déclaration de chrono, dans le cadre de la solution de facilité que j'ai indiquée.

    A noter que NoSmoking a écrit un message juste avant le vôtre, je ne sais pas si vous l'avez vu.

  13. #33
    Modérateur

    Avatar de NoSmoking
    Homme Profil pro
    Inscrit en
    Janvier 2011
    Messages
    16 959
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Localisation : France, Isère (Rhône Alpes)

    Informations forums :
    Inscription : Janvier 2011
    Messages : 16 959
    Points : 44 122
    Points
    44 122
    Par défaut
    Citation Envoyé par Loralina
    Le problème est de se lancer dans des classes, tout ça, sans maîtriser des notions de base ...
    je rajouterais sans avoir au préalable bien identifié les interactions entre chaque.

    Je reprend le bout de code que j'ai placé juste avant, à savoir ;
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
    stopTimer() {
      clearInterval(this.iTimer);
      this.elem.textContent = "Comptage annulé !";
      // ici action sur réservation
      reservation.clear(); // à adapter
    }
    et il est en vérité à ch...r si l'on veut respecter une certaine logique, je m'explique.

    En fait la liaison/relation est Réservation -> Chrono et non l'inverse, qu'est ce qui déclenche le Chrono ... la validation de la réservation ... donc la classe Reservation devrait instancier son propre Chrono.
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
    class Reservation {
      constructor(station, min, sec) {
        this.station = station;
        this.chrono = new Chrono(20);
        //...       
      }
    donc pas de variable/instance « global » pour le chrono.

    De même on n'arrête pas le chrono, on annule la réservation qui elle annulera le chrono
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
    7
    8
    class Reservation {
      constructor(station, min, sec) {
        //...       
      }
      cancel() {
        this.chrono.stopTimer();
        // et le reste des opérations
      }
    j'espère ne pas trop t'avoir embrouiller

  14. #34
    Membre du Club
    Homme Profil pro
    Développeur Web
    Inscrit en
    Juin 2020
    Messages
    119
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Âge : 35
    Localisation : France, Oise (Picardie)

    Informations professionnelles :
    Activité : Développeur Web

    Informations forums :
    Inscription : Juin 2020
    Messages : 119
    Points : 64
    Points
    64
    Par défaut
    Effectivement suite au post de Loralina j'ai décidé de déclarer les instances dans le constructeur.

    Et je vais poursuivre sur ce qu'à dit noSmoking, notamment l'action d'annulation sur stopTimer();

    De manière très simplifié voici ce que ça donne :

    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    15
    16
    17
    18
    19
    20
    21
    22
    23
    24
    25
    26
     
    class Formulaire {
        constructor() {
            //...
            this.reservation = new Reservation();
            //...
     
        }
        validerFormulaire() {
            const resa = this.reservation;
            resa.dataStore();
            resa.demarrerReservation();
        }
        check() {
         //Si les données du formulaire existent, on les récupère dans le DOM
        }
     
        requiredFields() {
     
        }
     
        switchButton() {
     
        }
     
    }



    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    15
    16
    17
    18
    19
    20
    21
    22
    23
    24
    25
    26
    27
    28
    29
     
     
    class Reservation {
        constructor() {
            //...
            this.storage = new Storage();
            this.chrono = new Chrono(20);
            //...
     
        }
        dataStore() {
           const storage = this.storage;
           storage.enregistrerDonnees;
        }
     
        demarrerReservation() {
            const chrono = this.chrono;
            chrono.startTimer();
           //Enlever un vélo à la station réservée
           //....
        }
     
        annulerReservation() {
            const chrono = this.chrono;
            chrono.stopTimer();
            //Ajouter un vélo à la station réservée
         //...
        }
    }

    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    15
    class Storage {
     
        constructor(station) {
            this.station = station;
        }
     
        enregistrerDonnees(station) {
            sessionStorage.setItem("station", JSON.stringify(station)); 
            localStorage.setItem("firstname", Dom.firstnameElement.value);
            localStorage.setItem('lastname', Dom.lastnameElement.value);
        }
     
        //Des statics pour pouvoir récupérer les getItem ailleurs
     
    }

  15. #35
    Membre du Club
    Homme Profil pro
    Développeur Web
    Inscrit en
    Juin 2020
    Messages
    119
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Âge : 35
    Localisation : France, Oise (Picardie)

    Informations professionnelles :
    Activité : Développeur Web

    Informations forums :
    Inscription : Juin 2020
    Messages : 119
    Points : 64
    Points
    64
    Par défaut
    Lorsque je refresh, on récupère le chrono, ça c'est OK

    Lorsque je clique sur annuler, j'appel la méthode eventCancel qui arrête le chrono, ça c'est OK

    Mais lorsque le chrono est stoppé, et que je refresh à ce moment là, le chrono repart...





    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    15
    16
    17
    18
    19
    20
    21
    22
    23
    24
    25
    26
    27
    28
    29
    30
    31
    32
    33
    34
    35
    36
    37
    38
    39
    40
    41
    42
    43
    44
    45
    46
    47
    48
    49
    50
    51
    52
    53
    54
    55
    56
    57
    58
    59
    60
    61
    62
    63
    64
    65
    66
    67
    68
    69
    70
    71
     class Reservation {
        constructor(station, min, sec) {
            this.station = station;
            this.min = min;
            this.sec = sec;
            this.chrono = new Chrono(20);
            this.onload();
            this.onBeforeUnload();
        }
     
        storeDatas() {
            console.log('Données enregistrées dans le store')
            const storage = new Storage(this.station);
            storage.dataRecord(this.station);
     
        }
     
        startResa() {
     
            console.log('Réservation validée');
            //this.station.removeBike();
            const chrono = this.chrono;
            chrono.startTimer();
            // this.station.getRemoveBike();
        }
     
        cancelResa() {
            console.log('Réservation annulée')
                //On ajoute un vélo à la station
                //this.station.getAddBike();
            const chrono = this.chrono;
            chrono.stopTimer();
        }
     
        onloadEvent() {
            const chrono = this.chrono;
            console.log('onload');
            const timeEnd = +sessionStorage.getItem("timeEnd");
            const tempsRestant = timeEnd - Date.now();
            if (tempsRestant > 0) {
                // relance timer avec date de fin de chrono
                chrono.startTimer(timeEnd);
                Dom.reserveElement.style.display = 'none';
                Dom.cancelButtonElement.style.display = 'flex';
            }
        }
     
        onBeforeUnloadEvent() {
     
            const chrono = this.chrono;
            const tempsRestant = chrono.timeEnd - Date.now();
            console.log(tempsRestant)
            if (tempsRestant > 0) {
                // store date de fin du chrono en millisecondes
                sessionStorage.setItem("timeEnd", chrono.timeEnd);
                // juste pour voir clairement la date dans le storage
                sessionStorage.setItem("dateEnd", new Date(chrono.timeEnd));
            } else {
                sessionStorage.clear();
            }
     
        }
     
        onload() {
            window.addEventListener('load', this.onloadEvent.bind(this));
        }
     
        onBeforeUnload() {
            window.addEventListener('beforeunload', this.onBeforeUnloadEvent.bind(this));
        }
    }


    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
        eventCancel() {
            Dom.cancelButtonElement.addEventListener('click', () => {
                console.log("clique sur annuler");
                const resa = this.resa;
                resa.cancelResa();
                Dom.cancelMessageElement.style.display = 'block';
                Dom.reserveElement.style.display = 'block';
                Dom.cancelButtonElement.style.display = 'none';
                //On ajoute un vélo à la station
                Dom.availableBikesElement.innerHTML = this.station.getAvailableBikes();
            });
        }

  16. #36
    Membre du Club
    Homme Profil pro
    Développeur Web
    Inscrit en
    Juin 2020
    Messages
    119
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Âge : 35
    Localisation : France, Oise (Picardie)

    Informations professionnelles :
    Activité : Développeur Web

    Informations forums :
    Inscription : Juin 2020
    Messages : 119
    Points : 64
    Points
    64
    Par défaut
    J'ai ajouté ceci dans ma fonction onload() :

    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    if (Dom.cancelButtonElement.addEventListener) {
                this.cancelResa();
            }
    Ce qui interrompt bien le chrono même lorsque je refresh, mais entre le temps ou je clique sur annuler et le temps que je refresh, le chrono a continué de tourner.

    Ex: si j'interromps le chrono à 18:55 minutes, et que je refresh 10 secondes plus tard, le chrono va afficher à 18:45 (en étant stoppé). Est-ce que c'est correct ? Tout en sachant que je peux modifier le texte avec textContent, mais je voulais voir comment le chrono se comporte lorsqu'on annule.

  17. #37
    Membre éclairé
    Femme Profil pro
    Autre
    Inscrit en
    Janvier 2017
    Messages
    335
    Détails du profil
    Informations personnelles :
    Sexe : Femme
    Localisation : France, Nord (Nord Pas de Calais)

    Informations professionnelles :
    Activité : Autre

    Informations forums :
    Inscription : Janvier 2017
    Messages : 335
    Points : 715
    Points
    715
    Par défaut
    Bonjour,
    Citation Envoyé par Lunesti Voir le message
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    if (Dom.cancelButtonElement.addEventListener) {
                this.cancelResa();
            }
    Ce test sera toujours vrai si le bouton existe (sinon il y aura une erreur de script).

    Citation Envoyé par Lunesti Voir le message
    Ce qui interrompt bien le chrono même lorsque je refresh, mais entre le temps ou je clique sur annuler et le temps que je refresh, le chrono a continué de tourner.
    Si le clearInterval s'est exécuté, alors non le chronomètre n'a pas continué de tourner.
    Mais je suppose qu'en cas de rafraîchissement il est relancé par rapport à la date de fin mémorisée et immédiatement stoppé par le code que vous avez ajouté.

    Ensuite, c'est juste une affaire de bon sens :
    - Dans la fonction onBeforeUnloadEvent, on enregistre, modifie ou supprime dans le "storage" les informations souhaitées en fonction de l'état du chronomètre.
    Si vous avez repris le code que j'ai donné, vous avez dans la fonction stopTimer, l'instruction this.iTimer=null;.
    Si la propriété iTimer est à null, c'est que le chronomètre ne tourne pas.
    Après, ça peut-être une autre propriété...
    Dans le "storage", vous pouvez alors supprimer la date de fin ou ajouter une autre donnée indiquant si le chronomètre tourne.

    - Dans la fonction onloadEvent, en fonction des informations du "storage", on sait exactement comment on doit initialiser le chronomètre.

  18. #38
    Membre du Club
    Homme Profil pro
    Développeur Web
    Inscrit en
    Juin 2020
    Messages
    119
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Âge : 35
    Localisation : France, Oise (Picardie)

    Informations professionnelles :
    Activité : Développeur Web

    Informations forums :
    Inscription : Juin 2020
    Messages : 119
    Points : 64
    Points
    64
    Par défaut
    Citation Envoyé par Loralina Voir le message
    Mais je suppose qu'en cas de rafraîchissement il est relancé par rapport à la date de fin mémorisée et immédiatement stoppé par le code que vous avez ajouté.
    Effectivement, si le chrono se relance c'était sûrement du au fait que le storage n'était pas clear(). ce que je viens de faire est :
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
    7
    8
        cancelResa() {
            console.log('Réservation annulée')
                //On ajoute un vélo à la station
                //this.station.getAddBike();
            const chrono = this.chrono;
            chrono.stopTimer();
            sessionStorage.clear();
        }

    j'ai simplement ajouté sessionStorage.clear() dans la fonction qui annule la réservation et donc le chrono, ce qui en cas de rechargement de la page le chrono n'est plus relancé par apport à la date de fin qui était mémorisé. Je viens de tester et , en cas de refresh après un clique sur annuler, le storage est bien clear et je reviens bien sur ma page comme si j'entrais à nouveau sur mon site.
    super !

  19. #39
    Membre éclairé
    Femme Profil pro
    Autre
    Inscrit en
    Janvier 2017
    Messages
    335
    Détails du profil
    Informations personnelles :
    Sexe : Femme
    Localisation : France, Nord (Nord Pas de Calais)

    Informations professionnelles :
    Activité : Autre

    Informations forums :
    Inscription : Janvier 2017
    Messages : 335
    Points : 715
    Points
    715
    Par défaut
    Avec ce code :
    Quand on clique sur Annuler, le "storage" est effacé, d'accord.
    Mais si on rafraîchit, la fonction onBeforeUnloadEvent est exécutée juste avant et donc devrait enregistrer la date de fin (si le test tempsRestant > 0 est validé).
    Donc quand la page est rechargée, le "storage" ne devrait pas être vide.
    A bien vérifier.

  20. #40
    Membre du Club
    Homme Profil pro
    Développeur Web
    Inscrit en
    Juin 2020
    Messages
    119
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Âge : 35
    Localisation : France, Oise (Picardie)

    Informations professionnelles :
    Activité : Développeur Web

    Informations forums :
    Inscription : Juin 2020
    Messages : 119
    Points : 64
    Points
    64
    Par défaut
    Je confirme qu'après un refresh le store n'est pas vide, j'obtiens les données de la station , dateEnd et timeEnd.

    En revanche timeEnd est null avant le refresh. C'est que les données du timer sont enregistrés après le chargement et non pas directement après la validation

    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    class Storage {
     
        constructor(station) {
            this.station = station;
            this.chrono = new Chrono(20);
        }
     
        dataRecord(station) {
            const chrono = this.chrono;
            sessionStorage.setItem("timeEnd", chrono.timeEnd);
            sessionStorage.setItem("station", JSON.stringify(station)); 
            localStorage.setItem("firstname", Dom.firstnameElement.value);
            localStorage.setItem('lastname', Dom.lastnameElement.value);
        }
    il y a un soucis de lecture du "chrono.timeEnd" que je ne peux pas récupérer de cette façon.

    Alors que dans cette méthode :

    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    15
     onBeforeUnloadEvent() {
     
            const chrono = this.chrono;
            const tempsRestant = chrono.timeEnd - Date.now();
            console.log(tempsRestant)
            if (tempsRestant > 0) {
                // store date de fin du chrono en millisecondes
                sessionStorage.setItem("timeEnd", chrono.timeEnd);
                // juste pour voir clairement la date dans le storage
                sessionStorage.setItem("dateEnd", new Date(chrono.timeEnd));
            } else {
                sessionStorage.clear();
            }
     
        }
    chrono.timeEnd est bien lu après avoir déclaré une instance de chrono. Y a t-il quelque chose à changer/Modifier/Ajouter ?

+ Répondre à la discussion
Cette discussion est résolue.
Page 2 sur 3 PremièrePremière 123 DernièreDernière

Discussions similaires

  1. Réponses: 12
    Dernier message: 10/12/2017, 15h38
  2. Thread Threapool: main() continue de tourner même après réalisation des tâches
    Par jamesleouf dans le forum Concurrence et multi-thread
    Réponses: 1
    Dernier message: 09/05/2011, 16h07
  3. include et refresh de page
    Par Prosis dans le forum Langage
    Réponses: 4
    Dernier message: 22/01/2007, 15h39
  4. Refresh de page initiale après saisie dans une popup
    Par muppetshow dans le forum Général JavaScript
    Réponses: 7
    Dernier message: 16/03/2005, 12h21
  5. Kill procédure qui continue de tourner en bas. 9i
    Par nuke_y dans le forum Oracle
    Réponses: 10
    Dernier message: 15/11/2004, 10h06

Partager

Partager
  • Envoyer la discussion sur Viadeo
  • Envoyer la discussion sur Twitter
  • Envoyer la discussion sur Google
  • Envoyer la discussion sur Facebook
  • Envoyer la discussion sur Digg
  • Envoyer la discussion sur Delicious
  • Envoyer la discussion sur MySpace
  • Envoyer la discussion sur Yahoo