Partage
  • Partager sur Facebook
  • Partager sur Twitter

Reinitialiser un setInterval() sur compte à rebour

Sujet résolu
    16 mars 2023 à 16:52:33

    Bonjour à tous, 

    J'ai un petit souci avec cette fonction :

    <script>
        $(function() {
    
                                                                   
         //Function to update counters on all elements with class counter
            var doUpdate = function() {
                $('#countdown').each(function() {
                  var count = parseInt($(this).html());
                     if (count !== 0) {
                         $(this).html(count - 1);
                     }
                 });
                                    };
    
             //Schedule the update to happen once every second
              setInterval(doUpdate, 1000);
    
           });
    
      </script>

    C'est un compte à rebour simple qui marche très bien, au chargement du div appelé avec ajax en jquery la première fois, le décompte se fait normalement à chaque seconde. Le problème survient quand je recharge le div une deuxième fois, et pire si plus, le décompte va 2, 3, 4 gois plus vite à chaque chargement de div. Donc si j'en déduit correctement, les setInterval() se superposent...

    J'ai essayé ceci :

    <script>
        $(function() {    
    
         // Tentative de remise à zéro mais... :( 
         clearInterval(doUpdate);
         $("#countdown").removeClass( ".active" );
    
    
                                                                   
         //Function to update counters on all elements with class counter
            var doUpdate = function() {
                $('#countdown').each(function() {
                  var count = parseInt($(this).html());
                     if (count !== 0) {
                         $(this).html(count - 1);
                     }
                 });
                                    };
    
             //Schedule the update to happen once every second
              setInterval(doUpdate, 1000);
    
           });
    
      </script>

    Et plusieurs autres "solutions" sans succès...

    Si je fais un refresh de la page, pas de souci, le compte à rebour redéfinle OK...

    Que puis-je faire pour que le compte à rebour reparte de là où il devrait partir mais sans superpositions de setInterval() ?

    -
    Edité par OliverTwist15 16 mars 2023 à 17:01:22

    • Partager sur Facebook
    • Partager sur Twitter
      19 mars 2023 à 2:17:57

      Pour le coup, j'ai trouvé tout seul, et je poste ici si ça peut servir.

      J'ai mis le script du compte à rebours dans l'index, ce script se charge donc au chargement et/ou refresh et une fois qu'on charge le script en ajax avec le span avec l'id qui correspond, ça marche. Pour ne pas avoir de superposition de setInterval(), et bien il suffit de ne charger qu'une fois au final... 

      • Partager sur Facebook
      • Partager sur Twitter
        19 mars 2023 à 9:51:51

        OliverTwist15 a écrit:

        Pour le coup, j'ai trouvé tout seul, et je poste ici si ça peut servir.

        J'ai mis le script du compte à rebours dans l'index, ce script se charge donc au chargement et/ou refresh et une fois qu'on charge le script en ajax avec le span avec l'id qui correspond, ça marche. Pour ne pas avoir de superposition de setInterval(), et bien il suffit de ne charger qu'une fois au final... 


        Hello, il s'agit d'une solution en effet mais le mieux aurait été d'avoir une logique qui permet de bien clear l'interval comme il faut.

        Première question : Est-ce que je tu utilise jQuery car tu utilise quelque chose qui demande d'importer ce dernier ou est-ce un choix personnel ? dans le second cas peux-tu nous détailler pourquoi tu l'utilise ?

        Ensuite tu parle de charger dans l'index et que le script se charge en ajax mais on ne vois pas dans le code à quoi sa correspond exactement, il faudrait à minima donner le code qui fait ce chargement.

        Enfin il y a plein de chose à redire dans le code :

        • Utilisation de "var" la ou un const ou let aurai suffit
        • tu fait une boucle sur tous les élements d'id "countdown" sauf que un id est unique dans un code html donc pourquoi boucler ?
        • tu te sers de la valeur qu'il y a dans ton countdown html pour faire le calcul. Pourquoi ne pas avoir simplement une variable ?
        • on va pas changer tous le code back pour ça mais il est préférable de renvoyer du json quand on fait de l'ajax plutôt que tous le html

        Voici ce que cela donne :

        Déjà dans le html j'ai mis le fichier "counter.js" dans la partie "head" du html avec l'attribut "defer" :

        <script src="/counter.js" defer></script>


        Ensuite au niveau du html j'ai fait quelque chose de simple :

        <section class="container">
            <h1>Compteur</h1>
            <div>
                <label for="counterInput">Quel valeur voulez-vous ?</label><br>
                <input type="number" id="counterInput">
            </div>
            <button type="button" id="submitCounter">Utiliser ce compteur</button>
        </section>
        
        <section id="result"></section>


        Pour le fichier qui sera appeler en ajax, c'est du php qui renvoie du html (même si comme dis plus haut il faudrait retourner du json) :

        <?php
        $counter = intval($_GET['counter'] ?? '1');
        if ($counter < 1) {
            $counter = 1;
        }
        ?>
        <div class="counter" data-start="<?= $counter ?>"><?= $counter ?></div>
        


        Enfin voici le js :

        const counterInputEl = document.getElementById('counterInput')
        const submitCounterEl = document.getElementById('submitCounter')
        const resultEl = document.getElementById('result')
        
        let counterIntervalId = null
        let counterEl = null
        let counter = 0
        
        function startCounter(newCounterValue) {
          // Si l'élément n'existe pas, on arrête le compteur
          if (counterEl === null) {
            return undefined
          }
        
          // Si le compteur est déjà lancé, on l'arrête
          if (counterIntervalId) {
            clearInterval(counterIntervalId)
          }
        
          counter = newCounterValue
        
          counterIntervalId = setInterval(() => {
            counter = counter - 1
            counterEl.innerHTML = counter
        
            if (counter === 0) {
              clearInterval(counterIntervalId)
            }
          }, 1000)
        }
        
        function fetchCounter(counterValue) {
          return fetch(`/get_counter.php?counter=${counterValue}`)
            .then((response) => response.text())
        }
        
        submitCounterEl.addEventListener('click', () => {
          // On récupère la valeur du compteur
          const counterValue = parseInt(counterInputEl.value)
        
          // Si la valeur n'est pas un nombre, on arrête la fonction
          if (isNaN(counterValue)) {
            resultEl.innerText = 'Invalid counter value'
            return undefined
          }
        
          fetchCounter(counterValue).then((html) => {
            resultEl.innerHTML = html
        
            // On récupère l'élément du compteur
            counterEl = document.querySelector('.counter')
        
            // On lance le compteur.
            // J'ai utilisé ce qui est renvoyé par le serveur,
            // mais on peut aussi utiliser la valeur du champ directement
            startCounter(parseInt(counterEl.dataset.start))
          })
        })
        


        Il y a des moyens d'optimiser le script largement mais c'est déjà un bon début.

        • Partager sur Facebook
        • Partager sur Twitter

        Reinitialiser un setInterval() sur compte à rebour

        × Après avoir cliqué sur "Répondre" vous serez invité à vous connecter pour que votre message soit publié.
        • Editeur
        • Markdown