0

I'm looking for implement a Chronometer script in with JS in my Django web application. This chronometer has multiple functions :

  • User can start the chronometer (0:0s --> 1:2s)
  • User can stop the chronometer and start again (stop at 3:3s than if user click one more time on start --> 3:4, 3:5 ....)
  • User can reset the chronometer

I'm a beginner with Javascript and I would get your help in order to improve my script :

// Here set the minutes, seconds, and tenths-of-second when you want the chronometer to stop
// If all these values are set to 0, the chronometer not stop automatically
var stmints = 0;
var stseconds = 0;
var stzecsec = 0;

// function to be executed when the chronometer stops
// function toAutoStop() {
//  alert('You stopped the chronometer');
// }

// the initial tenths-of-second, seconds, and minutes
var zecsec = 0;
var seconds = 0;
var mints = 0;

var startchron = 0;

function chronometer() {
  if (startchron == 1) {
    zecsec += 1; // set tenths of a second

    // set seconds
    if (zecsec > 9) {
      zecsec = 0;
      seconds += 1;
    }

    // set minutes
    if (seconds > 59) {
      seconds = 0;
      mints += 1;
    }

    // adds data in #showtm
    document.getElementById('showtm').innerHTML = mints + ' : ' + seconds + '<sub>' + zecsec + '</sub>';

    // if the chronometer reaches to the values for stop, calls whenChrStop(), else, auto-calls chronometer()
    if (zecsec == stzecsec && seconds == stseconds && mints == stmints) toAutoStop();
    else setTimeout("chronometer()", 100);
  }
}

function startChr() {
  startchron = 1;
  chronometer();
} // starts the chronometer
function stopChr() {
  startchron = 0;
} // stops the chronometer
function resetChr() {
  zecsec = 0;
  seconds = 0;
  mints = 0;
  startchron = 0;
  document.getElementById('showtm').innerHTML = mints + ' : ' + seconds + '<sub>' + zecsec + '</sub>';
}
// start the chronometer, delete this line if you want to not automatically start the stopwatch
// startChr();
<div id="showtm" style="font-size:21px; font-weight:800;">0:0</div>
<button onclick="startChr()">Start the chronometer </button>
<button onclick="stopChr()">Stop the chronometer</button>
<button onclick="resetChr()">Reset the chronometer</button>

But I'm getting some issues with my script :

  1. The chronometer starts when the page is loaded. When I overcome to the HTML page or when I actualize my page, the chronometer starts. I would like to begin the chronometer only when users click on "start" (solved in my comment)

  2. I would like to pick-up the variable when I stop the chronometer in order to fill a Django form. How I can get this chronometer variable in my script ?

  3. When I start the chronometer it works fine, but If I'm watching another tab in my browser and I come back on the chronometer, time displayed is false because I launched on the same time my smartphone chronometer. The JS chronometer is delayed ..

Up to now, I'm getting these both issues :/

Thank you

EDIT :

My new code :

<div class="form" id="showtm" style="font-size:21px; font-weight:800;">0 minutes : 0 secondes : 0 millisecondes</div>
            <script type="text/javascript">

                // Here set the minutes, seconds, and tenths-of-second when you want the chronometer to stop
                // If all these values are set to 0, the chronometer not stop automatically
                var stmints = 0;
                var stseconds = 0;
                var stzecsec = 0;

                // function to be executed when the chronometer stops
                //function toAutoStop() {
                //alert('Vous avez stoppé le chronomètre');
                //}

                // the initial tenths-of-second, seconds, and minutes
                var zecsec = 0;
                var seconds = 0;
                var mints = 0;

                var startchron = 0;

                function chronometer() {
                if(startchron == 1) {
                    seconds += 1;       // set tenths of a second

                    // set seconds
                    //if(zecsec > 9) {
                    //zecsec = 0;
                    //seconds += 1;
                    //}

                    // set minutes
                    if(seconds > 59) {
                    seconds = 0;
                    mints += 1;
                    }

                    // adds data in #showtm
                    document.getElementById('showtm').innerHTML = mints+ ' min '+ seconds + ' sec ' + zecsec   ;

                    // if the chronometer reaches to the values for stop, calls whenChrStop(), else, auto-calls chronometer()
                    if(zecsec == stzecsec && seconds == stseconds && mints == stmints) toAutoStop();
                    else setTimeout("chronometer()", 1000);
                }
                }

                function startChr() { startchron = 1; chronometer(); }      // starts the chronometer
                function stopChr() { startchron = 0; }                      // stops the chronometer
                function resetChr() {
                zecsec = 0;  seconds = 0; mints = 0; startchron = 0; 
                document.getElementById('showtm').innerHTML = mints+ ' min '+ seconds+ ' sec ' + zecsec ;
                }
                // start the chronometer, delete this line if you want to not automatically start the stopwatch
                //startChr();

                document.getElementById('showtm').value=seconds;
            </script>
            <p></p>

            <div class="form">
            <button onclick="startChr()">Démarrer l'intervention </button>
            <button onclick="stopChr()">Stopper l'intervention</button>
            <button onclick="resetChr()">Reset de l'intervention</button>
            </div>
Essex
  • 6,042
  • 11
  • 67
  • 139
  • I set as a comment `startChr();` just before `` and my chronometer seems to begin only when I click on start. So the first issue seems to be solve. – Essex Jul 12 '17 at 08:04
  • You got a comment there, explicitly saying // start the chronometer, delete this line if you want to not automatically start the stopwatch :) – Pavel Hasala Jul 12 '17 at 08:23
  • Also, can you please update your snippet, that it doesnt include the automatic start, and translate buttons to english? – Pavel Hasala Jul 12 '17 at 08:24
  • I will update my script, but the first issue is solved by deleting or set as a comment `startChr()`. It's my comment @PavelHasala ;) – Essex Jul 12 '17 at 08:26
  • I know, I was pointing out, that if you actualy look through the script, there was explicitly written that by deleting that line, chrono wont autostart :) – Pavel Hasala Jul 12 '17 at 08:28
  • Yes the issue is actually not there ;) I don't overcome to solve 2. and 3. :/ – Essex Jul 12 '17 at 08:29
  • I pasted answers to 2. and 3., but to be further help for the 2. form filling , you need to privide more info on the form fields – Pavel Hasala Jul 12 '17 at 08:49
  • Let us [continue this discussion in chat](http://chat.stackoverflow.com/rooms/148979/discussion-between-pavel-hasala-and-deadpool). – Pavel Hasala Jul 12 '17 at 08:56

1 Answers1

1

1. starting on load

you already solved, as it was commented in code to just delete startChr() at the end of the script.

// start the chronometer, delete this line if you want to not automatically start the stopwatch
startChr();

at the end of the script.

2. Picking values

You need to put handler function filling your form, called in stopChr. You use variables mints for minutes, seconds and zecsec for 1/00 seconds

function stopChr() {
    startchron = 0;
    // HERE YOU PUT YOUR HANDLER FUNCTION TO FILL YOUR FORM
    // mints:seconds, zecsec
}

3. chrono stoping

That is by design, tl;dr;

When a tab is inactive, only at a maximum of once per second the function is called.

As you are incrementing your chronometer by hundreths, not seconds (100ms instead of 1000ms), your chronometer is automaticly suspended. More on that topic you can read here How can I make setInterval also work when a tab is inactive in Chrome?

Working snipet for not suspending counter

/**
 *  SCRIPT
 */
// Here set the minutes, seconds, and tenths-of-second when you want the chronometer to stop
// If all these values are set to 0, the chronometer not stop automatically
var stmints = 0;
var stseconds = 0;
// selectors to elements, where we are displaying timer. They also are form fields, so they are going to be send to server
var mints_elm = document.getElementById('minutes')
var seconds_elm = document.getElementById('seconds')

// the initial tenths-of-second, seconds, and minutes
var seconds = 0;
var mints = 0;

var startchron = 0;

function chronometer() {
  if (startchron == 1) {
    seconds += 1; // set tenths of a second

    // set minutes
    if (seconds > 59) {
      seconds = 0;
      mints += 1;
    }

    // adds data in proper fields
    mints_elm.value = mints
    seconds_elm.value = seconds

    // if the chronometer reaches to the values for stop, calls whenChrStop(), else, auto-calls chronometer()
    if (seconds == stseconds && mints == stmints) {
      toAutoStop();
    } else {
      setTimeout("chronometer()", 1000);
     }
  }
}

function startChr() {
  startchron = 1;
  chronometer();
} // starts the chronometer
function stopChr() {
  startchron = 0;
} // stops the chronometer
function resetChr() {
  seconds = 0;
  mints = 0;
  startchron = 0;
  mints_elm.value = mints
  seconds_elm.value = seconds
}
/* css, just for better displaying */
input[type="text"] {
  font-size:21px; 
  font-weight:800;
  width: 50px;
  text-align: center;
  border: none;
  background: transparent;
}
<!-- HTML -->
<form id="form" action="#urltobackendservice">
  <input name="minutes" id="minutes" value="0" type="text" /> : 
  <input name="seconds" id="seconds" value="0" type="text" />
  <input type="submit" value="Send result" />
</form>
<hr />
<button onclick="startChr()">Start the chronometer </button>
<button onclick="stopChr()">Stop the chronometer</button>
<button onclick="resetChr()">Reset the chronometer</button>
Pavel Hasala
  • 946
  • 10
  • 14
  • Thank you for your answer. What I want to do with picking value is : save the js variable somewhere and use it in my django templates. – Essex Jul 12 '17 at 09:05
  • Well, you cant do that, as django is runned on server side and js on client. You need to fill it in the rendered template, or use ajax to replace the rendered part of the code, as you can send those chronometer variables as url params, and henc use them while rendering your django template – Pavel Hasala Jul 12 '17 at 09:17
  • Ok, the only thing is : I don't overcome to make `setInterval` in my script. So when the tab is inactive, the stopwatch doesn't work :/ I read your link about `setInterval` but I don't understand very well (first time I'm using JS) – Essex Jul 12 '17 at 11:20
  • It is the part "else setTimeout("chronometer()", 100);" As your chrono is incrementing by 100ms, so need 10 ticks for each second. You cant have that, if you dont want your timer to be suspended. there need to be value atleast 1000. But that will mean to change the skript so it increment "seconds" and not "zecsec" – Pavel Hasala Jul 12 '17 at 12:22
  • Your advice doesn't work. I set `1000` and I incremented seconds and not zecsec but it doesn't work ^^ – Essex Jul 12 '17 at 12:38
  • Can you provide your changed code, at form of a pastbin etc? – Pavel Hasala Jul 12 '17 at 14:05
  • And it didnt work for you, because you completely broke the html part :) I added working snippet to my answer. – Pavel Hasala Jul 12 '17 at 14:48
  • I read your answer. It works on SO, but not in my HTML template so I have to see why ;) Thank you anyway – Essex Jul 12 '17 at 15:20
  • Hope you get it. The way my example works is that you send those results via url parameters, so you can render it in your django templates. Non the less, if this is what you wanted, please mark the answer as correct, so we can check this question as solved :) – Pavel Hasala Jul 12 '17 at 15:28