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 :

Chrono JS: passer du procédural en POO


Sujet :

JavaScript

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

    Informations professionnelles :
    Activité : Développeur Web

    Informations forums :
    Inscription : Juin 2020
    Messages : 119
    Par défaut Chrono JS: passer du procédural en POO
    Bonjour, je viens vous solliciter car j'ai besoin d'aide.

    Je dois faire un compte à rebours de 20 minutes en javascript. Je propose ce code qui fonctionne en procédural :

    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
     
    startTimer = (duration, display) => {
        var timer = duration;
        var minutes;
        var seconds;
        setInterval(function () {
            minutes = parseInt(timer / 60);
            seconds = parseInt(timer % 60, 10);
     
            minutes = minutes < 10 ? "0" + minutes : minutes;
            seconds = seconds < 10 ? "0" + seconds : seconds;
     
            display.textContent = minutes + ":" + seconds;
     
            if (--timer < 0) {
                timer = duration;
            }
        }, duration);
    }
    Et j'appel cette fonction ailleurs, dans une méthode appartenant à ma class Reservation :
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
     
    Dom.getValider().addEventListener('click', () => {
         let twentyMinutes = 60 * 20, display = document.getElementById('time');
         startTimer(twentyMinutes, display, 1000);
    });
    En gros , lorsque je clique sur le bouton valider, la fonction startTimer se déclenche, le décompte de 20 minutes est lancé jusque 0.

    Mais ça se complique lorsque je transforme ce code en POO :

    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 Chrono {
        constructor(twentyMinutes) {
            this.twentyMinutes = twentyMinutes;
            this.timer = this.duration, 
            this.minutes,
            this.seconds;
            this.timeleft = document.querySelector('#time');
        }
     
        startTimer(duree) {
     
            setInterval(function () {
                this.minutes = parseInt(this.timer / 60);
                this.seconds = parseInt(this.timer % 60, 10);
     
                this.minutes = this.minutes < 10 ? "0" + this.minutes : this.minutes;
                this.seconds = this.seconds < 10 ? "0" + this.seconds : this.seconds;
     
                this.timeleft.textContent = this.minutes + ":" + this.seconds;
     
                if (--this.timer < 0) {
                    this.timer = this.duration;
                }
            }, duree);
        }
    }
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
     
    Dom.getValider().addEventListener('click', () => {
         const myChrono = new Chrono(60 * 20);
         myChrono.startTimer(1000);
    });
    Je pense avoir bien fait, je ne comprends pas. J'obtiens ceci dans la console lorsque je clique sur valider :
    Nom : chrono.png
Affichages : 640
Taille : 1,8 Ko
    (içi, cela correspond à chrono.js:19)

    On dirait que le chrono est enclenché (d'ou le numéro qui change , içi avec 8, 9, 10, etc) mais il n'arrive pas à lire ce qu'il y a après le "textContent".
    Je ne comprends pas car cela marche en procédural. J'ai juste changé l'affichage du chrono , non plus dans le display mais dans ma balise #time (this.timeleft).

    Merci par avance de m'aider car je bute sur ça depuis ce matin...

  2. #2
    Modérateur

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

    Informations forums :
    Inscription : Janvier 2011
    Messages : 17 198
    Par défaut
    Bonjour,
    tu as le même problème que celui rencontré dans pas mal de discussions, c'est lié à la valeur du this lorsque la fonction dans ton setInterval est exécutée, mets un console.log(this) juste pour voir
    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
    startTimer(duree) {
        // sauve le contexte
        const thisObj = this;  
     
        setInterval(function () {
            // juste pour voir et comprendre 
            console.log("this :", this);
            console.log("thisObj :", thisObj);
     
            this.minutes = parseInt(this.timer / 60);
            this.seconds = parseInt(this.timer % 60, 10);
     
            this.minutes = this.minutes < 10 ? "0" + this.minutes : this.minutes;
            this.seconds = this.seconds < 10 ? "0" + this.seconds : this.seconds;
     
            this.timeleft.textContent = this.minutes + ":" + this.seconds;
     
            if (--this.timer < 0) {
                this.timer = this.duration;
            }
        }, duree);
    }

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

    Informations professionnelles :
    Activité : Développeur Web

    Informations forums :
    Inscription : Juin 2020
    Messages : 119
    Par défaut
    Merci pour ta réponse. J'ai trouvé un code beaucoup plus simple pour moi :

    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
    class Chrono {
        constructor(minutes, secondes) {
            this.minutes = minutes;
            this.secondes = secondes;
            this.a;
        }
     
       startTimer() {
            // sauve le contexte
            const thisObj = this;
            setInterval(function () {
                // juste pour voir et comprendre 
                console.log("this :", this);
                console.log("thisObj :", thisObj);
                this.a = new Date();
                Dom.getTime().innerHTML = this.minutes + ":" + this.secondes;
                this.secondes--;
                if (this.secondes == 0) {
                    this.minutes--;
                    this.secondes = 60;
                    if (this.minutes == 0) {
                        this.minutes = 2;
                    }
                }
            }, 1000);
        }
    }
    Cette fois-ci, je n'ai aucun message d'erreur lorsque je clique sur valider, mais , au lieu d'avoir le décompte (20:00, 19:59, 19:58, etc) j'ai à la place undefined: undefined, puis undefined : NaN .

    Je rappel que j’exécute ce code au moment du clique sur le bouton "Valider" dans une autre class
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
     
    Dom.getValider().addEventListener('click', () => {
         const myChrono = new Chrono(19, 59);
         myChrono.startTimer();
    J'ai essayé console.log(this) et cela me met ceci :

    > this : Window
    > thisObj : Chrono > minutes: 19
    secondes: 59
    __proto__: Object


    > this : Window*{parent: Window, opener: null, top: Window, length: 0, frames: Window,*…}
    Mais cela ne m'aide pas plus que ça. lorsque je déroule cette ligne, j'ai énormément de choses mais je ne pense pas que cela soit utile.

    Pour infos j'ai ceci dans ma class Dom ( qui est positionné avant toute mes class)
    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 Dom {
        constructor() {
        }
     
        static getCanvas() {
            return document.getElementById('canvas');
        }
     
        static getValider() {
            return document.querySelector('.valider');
        }
     
        static getAnnuler() {
            return document.querySelector('.annuler');
        }
     
        static getTime() {
            return document.querySelector('#time');
        }
     
        static getStations() {
            return document.getElementById('info-station');
        }
     
        static getEtat() {
            return document.getElementById('status');
        }
     
        static getNom() {
            return document.getElementById('name');
        }
     
        static getAdresse() {
            return document.getElementById('address');
        }
     
        static getVeloDispo() {
            return document.getElementById('available_bikes');
        }
     
        static getPlaceDispo() {
            return document.getElementById('bike_stands');
        }
    }
     
    const myStation = new Dom();
    On retrouve bien la variable time. Donc je ne comprends pas pourquoi javascript n'arrive pas à lire ce qu'il y a après .innerHTML :
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    Dom.getTime().innerHTML = this.minutes + ":" + this.secondes;

    Vraiment je préfère programmer en procédural car je trouve cela plus simple mais on m'oblige de ne faire que de la POO

  4. #4
    Modérateur

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

    Informations forums :
    Inscription : Janvier 2011
    Messages : 17 198
    Par défaut
    J'ai essayé console.log(this) et cela me met ceci :
    ...
    > this : Window
    > thisObj : Chrono > minutes: 19
    ...
    Mais cela ne m'aide pas plus que ça. lorsque je déroule cette ligne, j'ai énormément de choses mais je ne pense pas que cela soit utile.
    cela te dit que la fonction startTimer est appelée dans le contexte thisObj, à savoir ta classe Chrono et que la fonction exécutée dans ton setInterval est exécutée dans le contexte window.

    En clair tu cherches à modifier la variable secondes appartenant à window et celle-ci n'existe pas, incrémenter une variable qui vaut undefined ne fait rien de bon

    Remplace tes this.nomVariable par thisObj.nomVaraible et regarde ce qui se passe.

    PS :
    au passage ta Class Dom ne vaut pas grand chose et l'utilisation que tu en fais est incorrecte, mais c'est une autre histoire !

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

    Informations professionnelles :
    Activité : Développeur Web

    Informations forums :
    Inscription : Juin 2020
    Messages : 119
    Par défaut
    Merci en effet je ne sais pas encore très bien interprêter les messages de la console de ce genre je suis relativement nouveau en javascript. J'étudie ça demain matin merci

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

    Informations professionnelles :
    Activité : Développeur Web

    Informations forums :
    Inscription : Juin 2020
    Messages : 119
    Par défaut
    PS :
    au passage ta Class Dom ne vaut pas grand chose et l'utilisation que tu en fais est incorrecte, mais c'est une autre histoire !
    Enfait j'ai deja vu plusieurs étudiant faire cela. sauf que moi j'ai fait des getters (comme mon mentor m'a conseillé) de manière à pouvoir utiliser ces variables partout. En quoi cette méthode est incorrect ?

  7. #7
    Modérateur

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

    Informations forums :
    Inscription : Janvier 2011
    Messages : 17 198
    Par défaut
    En quoi cette méthode est incorrect ?
    ce n'est pas tant la méthode, je parle de la déclaration, qui est incorrecte mais la façon dont tu l'utilises.

    Lorsque tu écris const myStation = new Dom() on s'attend à ce que tu utilises myStation, mais comme les méthodes sont statiques tu ne peut pas, elles ne sont visibles que par Dom.

    Le plus gros défaut que j'y trouve est qu'à chaque appel tu refais un document.getElementById, ou autres, et qu'à chaque fois que tu vas définir un nouvel élément dans le DOM tu vas ajouter une méthode, là c'est très moyen.
    Il faut factoriser et mettre en cache tes éléments.

    Je ne sais si je dois aller plus loin dans ce sens ?

    Nota au passage, il me semble que je t'avais fournie une astuce lors de ta dernière discussion, pour rappe c'est icil.

    Une autre remarque au passage concernant le fait de faire confiance au délai de setTimeout, il vaut mieux faire une contrôle avec la date/heure en cours tu auras une meilleur garantie du délai réel, fais des tests en changeant de page et en y revenant.

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

    Informations professionnelles :
    Activité : Développeur Web

    Informations forums :
    Inscription : Juin 2020
    Messages : 119
    Par défaut
    Cela a fonctionné, je te remercie !

    J'ai fait comme tu m'as indiqué, c'est à dire de mettre thisObj.nomVariable à la place de this.nomVariable.

    Donc si j'ai bien compris la fonction setInterval s'éxécutait dans le contexte window et non dans le contexte de la class Chrono(), et pour contre carrer cette problématique il fallait ajouter dans startTimer() puis remplacer les this.nomVariable par thisObj.nomVariable dans setInterval pour que les 2 soient lié ?

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

    Informations professionnelles :
    Activité : Développeur Web

    Informations forums :
    Inscription : Juin 2020
    Messages : 119
    Par défaut
    Citation Envoyé par NoSmoking Voir le message

    Le plus gros défaut que j'y trouve est qu'à chaque appel tu refais un document.getElementById, ou autres, et qu'à chaque fois que tu vas définir un nouvel élément dans le DOM tu vas ajouter une méthode, là c'est très moyen.
    Il faut factoriser et mettre en cache tes éléments.

    Je ne sais si je dois aller plus loin dans ce sens ?
    J'ai compris. A l'origine j'ai créé cette classe uniquement si je dois réutiliser un élément du dom dans plusieurs class différente, ce qui me permet d'éviter de dupliquer les éléments HTML. Peut-être qu'à l'avenir je trouverai une meilleur méthode. J'irais jeter un coup d'oeil à ton astuce pour voir si ça peut m'aider pour cela.

  10. #10
    Membre émérite
    Femme Profil pro
    Autre
    Inscrit en
    Janvier 2017
    Messages
    340
    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 : 340
    Par défaut
    Bonjour,
    Citation Envoyé par NoSmoking Voir le message
    cela te dit que la fonction startTimer est appelée dans le contexte thisObj, à savoir ta classe Chrono et que la fonction exécutée dans ton setInterval est exécutée dans le contexte window.
    J'ai un peu de mal avec cette formulation (à moins que ce ne soit pour être mieux compris ?) qui est pourtant assez en accord avec la documentation française, mais peut-être moins avec l'anglaise.

    Je mets deux passages en comparaison :
    Français :
    https://developer.mozilla.org/fr/doc...%A9rateur_this
    1) "Valeur
    L'objet JavaScript représentant le contexte..."

    2) "...les fonctions fléchées dans lesquelles this correspond à la valeur du contexte englobant."

    Anglais :
    https://developer.mozilla.org/en-US/...Operators/this

    1) "Value
    A property of an execution context..."

    2) "it retains the this value of the enclosing lexical context"

    La formulation anglaise me paraît plus précise, voire plus exacte.

    Citation Envoyé par Lunesti Voir le message
    Donc si j'ai bien compris la fonction setInterval s'éxécutait dans le contexte window et non dans le contexte de la class Chrono()
    La formulation me dérange.
    Déjà ce n'est pas la fonction setInterval qui nous préoccupe, mais plutôt celle qu'on lui a mise comme premier argument.

    Je pense qu'il y a deux concepts importants pour mieux comprendre :
    - Contexte d'exécution, en lien avec la valeur de this.
    - Environnement lexical, en lien avec la portée des variables.


    Quand on exécute la fonction startTimer, on entre dans un nouveau contexte d'exécution.
    A ce moment, this est défini selon la façon dont a été appelée cette fonction.
    Quand on appelle cette fonction en faisant myChrono.startTimer(1000); alors this correspondra à l'objet myChrono.
    Il existe d'autres façons d'appeler cette fonction pour lesquelles this pourrait avoir une autre valeur.

    Ensuite, la fonction setInterval elle-même (pas son premier argument) est appelée depuis ce contexte d'exécution.
    Son exécution entraînera un nouveau contexte d'exécution.
    Mais peu importe ici la mécanique exacte de la fonction setInterval.

    Enfin, concernant la fonction mise en premier argument de setInterval :
    Quand elle sera exécutée, on entrera dans un nouveau contexte d'exécution et, encore une fois, this sera défini selon la façon dont est appelée cette fonction.
    Cette fois-ci c'est window et non plus myChrono qui sera choisi pour this.


    Puisque la valeur de this ne nous convient plus, une solution possible (une autre étant les fonctions fléchées) est de se baser sur l'environnement lexical.
    L'important est l'endroit où est définie la fonction et pas celui d'où elle est appelée.
    Or, à l'endroit où est définie notre fonction, on peut ajouter une variable/constante à laquelle on aura alors accès : const thisObj = this;.

  11. #11
    Modérateur

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

    Informations forums :
    Inscription : Janvier 2011
    Messages : 17 198
    Par défaut
    Citation Envoyé par Lunesti
    Donc si j'ai bien compris la fonction setInterval s'éxécutait dans le contexte window et non dans le contexte de la class Chrono(),
    Pas exactement c’est
    et que la fonction exécutée dans ton setInterval est exécutée dans le contexte window.
    voir également l'explication de Loralina.


    Citation Envoyé par Loralina
    J'ai un peu de mal avec cette formulation (à moins que ce ne soit pour être mieux compris ?)
    C’est tout à fait cela, on est d’accord sur le fond, il n’est pas toujours aisé de trouver la formulation la plus claire qui soit aussi la plus simple à comprendre, ce mécanisme étant loin d’être intuitif.


    Citation Envoyé par Loralina
    Puisque la valeur de this ne nous convient plus, une solution possible (une autre étant les fonctions fléchées) est de se baser sur l'environnement lexical.
    Les solutions sont nombreuses, « préservation » du contexte, mise en place d’une closure, création d’une fonction dédiée avec utilisation de bind …

    L’utilisation des fonctions fléchées est effectivement la solution la plus simple à mettre en oeuvre sous réserve que l’on n’ait pas a supporté IE.


    @Lunesti :
    Un autre point, tu arrêtes ton timer comment en fin de décomptage ?

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

    Informations professionnelles :
    Activité : Développeur Web

    Informations forums :
    Inscription : Juin 2020
    Messages : 119
    Par défaut
    Citation Envoyé par NoSmoking Voir le message
    @Lunesti :
    Un autre point, tu arrêtes ton timer comment en fin de décomptage ?
    Bonne question, la réservation doit s'expirer automatiquement au bout de 20 minutes. Ce qui veut dire qu'au bout de 20 minutes les données de réservations ne sont plus
    enregistré par cette personne SAUF son nom et son prénom (au cas où cette même personne voudrait à nouveau effectuer une réservation, on garde en cache son nom et prénom)

    Je n'ai pas encore proposé de code pour l'expiration automatique. Mais ce sera quelque chose comme : lorsque le chrono atteint 00:00, la réservation expire (et on rajoute 1 vélo à la station réservé.)

    J'ai cependant revu mon code un peu différement entre temps. Je devais (pour ne pas dire obligatoirement) créer une class Station qui contient les données des stations. Ensuite je créé un objet intermédiaire qui gère le formulaire avant la réservation (objet Formulaire). un objet Modal est aussi créé pour gérer les events de la modal, placé avant la réservation.

    Je devais avant tout bien découper les éléments et bien intégrer la notion d'objet.

    Pour ce faire , dans ma fonction addMarkers() je créé 3 nouvelles instances (formulaire, station, resa) qui sont appelé lors du clique sur un marker.

    fonction addMarkers()
    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
    //Ajouter Markers
        addMarkers() {
            this.stations.forEach((data) => {
                L.marker(Object.values(data.position), {
                    "data": data,  // on garde ici les données intéressantes
                    icon: this.iconBleue
                })
                    .addTo(this.map)
                    .on("click", function () {
     
                        const formulaire = new Formulaire();
                        formulaire.showForm();
                        formulaire.checkForm();
     
                        const station = new Station(data);
                        station.display();
     
                        const resa = new Reservation(data);
                        resa.dataRecord();
                        resa.cancelReservation();
                    });
     
                //Si la station est OPEN, marker couleur bleue. Sinon, couleur rouge
                if (data.status === "OPEN" && data.available_bikes > 0) {
                    L.marker({ icon: this.iconBleue })
                }
                else {
                    L.marker({ icon: this.iconRouge })
                }
            });
        }
    class Station
    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
    class Station {
        constructor(data) {
            this.status = data.status;
            this.name = data.name;
            this.address = data.address;
            this.available_bikes = data.available_bikes;
            this.bike_stands = data.bike_stands;
        }
     
        display() {
            Dom.getEtat().innerHTML = this.status;
            Dom.getNom().innerHTML = this.name;
            Dom.getAdresse().innerHTML = this.address;
            Dom.getVeloDispo().innerHTML = this.available_bikes;
            Dom.getPlaceDispo().innerHTML = this.bike_stands;
        };
     
    }
    class Formulaire
    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
    class Formulaire {
     
        showForm() {
       //On fait apparaitre le formulaire sur le côté en réduisant la taille de la map
            Dom.getMap().style.width = '60%';
            Dom.getForm().style.display = 'block';
        }
     
        checkForm() {
            //Si le formulaire est vide, on laisse cacher la modal et le canvas
            Dom.getReserver().addEventListener('click', () => {
                if (Dom.getNomObligatoire().value == '' && Dom.getPrenomObligatoire().value == '') {
                    Dom.getModal().style.display = 'none';
                    Dom.getCanvas().style.display = 'none';
                    alert('Veuillez renseigner votre nom et votre prénom');
                }
            });
        }
     
    }

    class Modal
    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
    class Modal {
     
        showModal() {
            //Si le formulaire est rempli, on fait apparaitre la modal et le canvas
            Dom.getReserver().addEventListener('click', () => {
                if (Dom.getNomObligatoire().value != '' && Dom.getPrenomObligatoire().value != '') {
                    Dom.getModal().style.display = 'block';
                    Dom.getCanvas().style.display = 'block';
                }
            });
        }
     
        eventCanvas() {
            //Lorsqu'on clique sur le canvas, on switch le bouton réserver par le bouton valider
            Dom.getCanvas().addEventListener('click', () => {
                Dom.getReserver().style.display = 'none';
                Dom.getValider().style.display = 'block';
            });
        }
     
        closeModal() {
            // Quand l'utilisateur clique sur la croix, il ferme la modal
            Dom.getCloseModal().addEventListener('click', () => {
                Dom.getModal().style.display = "none";
            });
            // Quand l'utilisateur clique quelque part dans la fenêtre, il ferme la modal
            window.addEventListener('click', (event) => {
                if (event.target == Dom.getModal()) {
                    Dom.getModal().style.display = "none";
                }
            });
        }
    }
     
    const modal = new Modal();
    modal.showModal();
    modal.eventCanvas();
    modal.closeModal();

    class Reservation
    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
    class Reservation {
        constructor(data) {
        //Objet réservation qui va contenir les données
            this.reservation = {
                nom: data.name,
                etat: data.status,
                adresse: data.address,
                veloDispo: data.available_bikes,
                placeDispo: data.bike_stands
            };
        }
     
        dataRecord() {
          //Lorsqu'on clique sur Valider, on enregistre les données de réservation
            Dom.getValider().addEventListener('click', () => {
                //On stocke les données dans le navigateur
                sessionStorage.setItem("infos", JSON.stringify(this.reservation));
                localStorage.setItem("nom et prénom: ", Dom.getNomObligatoire().value + ' ' + Dom.getPrenomObligatoire().value + '');
                //On appel la class Chrono
                const myChrono = new Chrono(19, 59);
                myChrono.startTimer(1000);            
            });
        }
     
       //Si l'utilisateur annule sa réservation avant les 20 minutes imparti
        cancelReservation() {
            Dom.getAnnuler().addEventListener('click', () => {
                //On remplace le paragraphe
                Dom.getReservationValider().innerHTML = 'Votre réservation est annulé';
                Dom.getReserver().style.display = 'block';
             //On clean la valeur des champs
                Dom.getNomObligatoire().value = '';
                Dom.getPrenomObligatoire().value = '';
            });
        }
    }

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

    Informations professionnelles :
    Activité : Développeur Web

    Informations forums :
    Inscription : Juin 2020
    Messages : 119
    Par défaut
    Merci pour ton explication Loralina

  14. #14
    Modérateur

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

    Informations forums :
    Inscription : Janvier 2011
    Messages : 17 198
    Par défaut
    Attention : ne t’emballe pas, concentre toi sur la résolution de ton problème de chronomètre, le reste est une autre histoire, d'autant que ton souci initial est résolu !

    Une discussion = une question
    Poser plusieurs questions dans un seul et même fil nuit grandement à la qualité du forum : notamment, lors d'une recherche, tout le contenu du fil n'est pas indiqué dans le titre, elle devient donc plus ardue.

  15. #15
    Membre très actif
    Homme Profil pro
    bricoleur par les mots
    Inscrit en
    Avril 2015
    Messages
    733
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Âge : 80
    Localisation : France, Seine Maritime (Haute Normandie)

    Informations professionnelles :
    Activité : bricoleur par les mots
    Secteur : Distribution

    Informations forums :
    Inscription : Avril 2015
    Messages : 733
    Par défaut
    jour

    ça en fait des class y' a pas plus simple ?

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

    Informations professionnelles :
    Activité : Développeur Web

    Informations forums :
    Inscription : Juin 2020
    Messages : 119
    Par défaut
    Sujet Résolu

  17. #17
    Modérateur

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

    Informations forums :
    Inscription : Janvier 2011
    Messages : 17 198
    Par défaut
    Sujet résolu peut-être pas, ton souci initial du this oui.

    Ton vrai but étant de créer une « classe » chrono autant essayer de la faire réutilisable, c'est aussi un peu le but, et la plus indépendante possible en se posant les bonnes questions au départ.
    C'est comme cela que l'on progresse

    Mais c'est à toi de voir !

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

    Informations professionnelles :
    Activité : Développeur Web

    Informations forums :
    Inscription : Juin 2020
    Messages : 119
    Par défaut
    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 Chrono {
        constructor(minutes, secondes) {
            this.minutes = minutes;
            this.secondes = secondes;
            this.time = document.querySelector('#time');
            this.a;
        }
     
       startTimer() {
           console.log('ok');
            // sauve le contexte
            const thisObj = this;
            setInterval(function()  {
     
                console.log("this :", this); 
                console.log("thisObj :", thisObj);
                thisObj.a = new Date();
                thisObj.time.innerHTML = thisObj.minutes + ":" + thisObj.secondes;
                thisObj.secondes--;
                if (thisObj.secondes == 0) {
                    thisObj.minutes--;
                    thisObj.secondes = 60;
                    if (thisObj.minutes == 0) {
                        thisObj.minutes = 2;
                    }
                }
            }, 1000);
        }
    }
    Voici ma class Chrono. Lorsque tu dis réutilisable je n'ai pas trop compris, tu veux dire afin de l'utiliser dans d'autres circonstances ? cela dépasserait les attentes de ce projet, car je dois simplement créer un compte à rebours de 20 minutes après la validation. Ici tout est fonctionnel et déclenché quand il le faut. Après il manque effectivement un morceau de code qui arrêterait le chrono au bout de 20 minutes avec un message. Mais Hormis cela le code (la class Chrono) est fonctionnel en POO

    Pour rappel je déclenche le Chrono lorsque je clique sur Valider
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
    7
    8
     Dom.getValider().addEventListener('click', () => {
                const myChrono = new Chrono(19, 59);
                myChrono.startTimer(1000);
               //Le texte du chrono apparait
                this.chrono.style.display = "block";
                Dom.getAnnuler().style.display = 'block';
                this.formulaire.style.height = "500px";
            });

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

    Informations professionnelles :
    Activité : Développeur Web

    Informations forums :
    Inscription : Juin 2020
    Messages : 119
    Par défaut
    Citation Envoyé par melka one Voir le message
    ça en fait des class y' a pas plus simple ?
    Oui il existe plus simple, j'aurais pu ne pas créer autant de class mais le piège est de ne pas tomber trop dans la facilité afin de proposer quelque chose de cohérent. Le but de ce projet est d'intégrer la notion d'Objet.

  20. #20
    Modérateur

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

    Informations forums :
    Inscription : Janvier 2011
    Messages : 17 198
    Par défaut
    •••
    cela dépasserait les attentes de ce projet, car je dois simplement créer un compte à rebours de 20 minutes après la validation.
    donc une seule location/validation prévue.

    •••
    Ici tout est fonctionnel et déclenché quand il le faut.
    Cela ne représente qu'une fonctionnalité qui marche car comme tu le dis
    Après il manque effectivement un morceau de code qui arrêterait le chrono au bout de 20 minutes avec un message. Mais Hormis cela le code (la class Chrono) est fonctionnel en POO
    de plus ce n'est pas fonctionnel mais c'est écrit correctement

    •••
    Les fonctionnalités minimum de ton « chrono » sont après initialisation :
    • le démarrer ;
    • l'arrêter, en cas d'annulation ;
    • décompter et afficher le temps restant ;
    • lancer une action en fin de décomptage.

    C'est sur cette base que tu écris le squelette de ta class :
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    class Chrono {
      constructor() {
      }
      startTimer() {
      }
      stopTimer() {
      }
      decompteTimer() {
      }
    }
    Ensuite il suffit d'étoffer le squelette, souvent plus facile à dire qu'à faire, mais au départ il faut avoir une bonne vision de ce que l'on souhaite faire.

    •••
    Concernant le décomptage il est préférable de tester le temps passé entre le lancement du chrono et le moment où l'on fait l'affichage, le comptage comme tu l'as prévue ne te garantissant nullement le temps réel passé.

    •••
    Je te mets ce que cela pourrait donner, il y a des commentaires pour que tu t'y retrouves
    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 Chrono {
      // il serait peut-être plus judicieux de passer le temps en secondes directement
      constructor(minutes = 0, secondes = 0) {
        // élément pour affichage, pourrait être passé en paramètre
        this.elem = document.querySelector('#time');
        // duree du chrono en ms
        this.duree = ((minutes * 60) + secondes) * 1000;
        // pour gérer le timer sur stop
        this.iTimer = null;
        // time en ms de la fin du chrono
        this.timeEnd;
      }
     
      startTimer() {
        // calcul time de fin en ms
        this.timeEnd = Date.now() + this.duree;
        // on passe par une arrow function pour la gestion du this
        // voir commentaire dans discussion
        this.iTimer = setInterval(() => {
          this.decompteTimer();
        }, 1000);
        // affiche la 1st fois
        this.decompteTimer();
      }
     
      stopTimer() {
        clearInterval(this.iTimer);
      }
     
      decompteTimer() {
        // calcul en secondes
        const reste = Math.ceil((this.timeEnd - Date.now()) / 1000);
        if (reste > 0) {
          // formatage de la sortie, plein de façon de faire
          // ou avec String(number).padStart(2, "00");
          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);
          // affichage temps restant
          this.elem.textContent = h + ":" + m + ":" + s;
        }
        else {
          clearInterval(this.iTimer);
          // action à faire quand c'est fini
          this.elem.textContent = "Comptage terminé !";
        }
      }
    }
    A toi d'analyser, de comprendre et d’exploiter.

    Bon courage.

    [Edit]Suppression d'un Math.ceil inutile

+ Répondre à la discussion
Cette discussion est résolue.
Page 1 sur 2 12 DernièreDernière

Discussions similaires

  1. Passer du procédural à la POO
    Par MonsieurPoulet dans le forum Langage
    Réponses: 7
    Dernier message: 19/09/2013, 10h18
  2. Passer une procédure en paramètres
    Par FamiDoo dans le forum Windows Forms
    Réponses: 5
    Dernier message: 17/02/2008, 14h41
  3. Passer des procédures stockées à Hibernate
    Par zizoux5 dans le forum Hibernate
    Réponses: 2
    Dernier message: 11/04/2007, 13h08
  4. Comment passer une procédure en paramètre ?
    Par gudul dans le forum Langage
    Réponses: 4
    Dernier message: 30/09/2005, 13h57
  5. Passer une procédure en paramètre ?
    Par Cornell dans le forum Langage
    Réponses: 2
    Dernier message: 24/10/2003, 12h21

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