0
let hours =0;
let minutes = 0;
let seconds = 0;
let displayHrs = document.getElementById("hours");
let displayMins = document.getElementById("minutes");
let displaySecs = document.getElementById("seconds");



var interval;
const startBtn =  document.getElementById("start");
const stopBtn =  document.getElementById("stop");
const resetBtn =  document.getElementById("reset");


const  startTimer  = () => {

    seconds++;
    if(seconds < 9){
        displaySecs.innerHTML = "0" + seconds;
    }
    if(seconds > 9){
        displaySecs.innerHTML = seconds;
    }
   if(seconds > 60){
        minutes++;
        seconds = seconds -(minutes *60);
    }
    if (minutes < 9){
        displayMins.innerHTML = "0" + minutes;
    }
     if (minutes > 9){
        displayMins.innerHTML = minutes;
    }
     if (minutes> 60){
        hours++;
        minutes = minutes -(minutes *60);
    }
};
startBtn.onclick = () => {
   interval = setInterval( startTimer);
}

The simple application crashes when I click the startBtn by indicating that displaySecs is null. I watched several tutorial and tried to create my own custom timer. Are there too many if statements? Is there a simpler cleaner way to do this?

Heretic Monkey
  • 10,498
  • 6
  • 45
  • 102
  • 1
    Please include your HTML as well – dale landry Oct 18 '20 at 00:08
  • where is the delay argument ? (in `setInterval( startTimer)` ), by the way `setInterval` can't be a timmer method – Mister Jojo Oct 18 '20 at 00:13
  • 1
    Does this answer your question? [Why does jQuery or a DOM method such as getElementById not find the element?](https://stackoverflow.com/questions/14028959/why-does-jquery-or-a-dom-method-such-as-getelementbyid-not-find-the-element) – Heretic Monkey Oct 18 '20 at 00:16
  • 1
    Note that because you don't pass an interval to `setInterval`, it will repeat on every cycle of the JavaScript event loop; basically the default for the delay argument is 0. This will have massive repercussions on the performance of the application. See [MDN's documentation of `setInterval`](https://developer.mozilla.org/en-US/docs/Web/API/WindowOrWorkerGlobalScope/setInterval) for more. – Heretic Monkey Oct 18 '20 at 00:22

2 Answers2

3

No such thing as too many if statements, as far as your program is concerned.

displaySecs is null means that document.getElementById() could not find the element with the matching id, so I suggest you go back and make sure that you actually have one with the id of seconds

Also check your other ones as they may possibly have the same problems.

(also I'm pretty sure your setInterval doesn't actually do 1 second intervals, you need to specify 1000 milliseconds in the parameters)

1

this way:

let hours   = 0
  , minutes = 0
  , seconds = 0
  , interval
  ;
const startBtn  = document.getElementById('start')
  ,   stopBtn   = document.getElementById('stop')
  ,   resetBtn  = document.getElementById('reset')
  , displayHrs  = document.getElementById('hours')
  , displayMins = document.getElementById('minutes')
  , displaySecs = document.getElementById('seconds')
  ;
const  startTimer = () =>
  {
  seconds++
  if (seconds > 60)
    {
    minutes++;
    seconds = 0
    }   
  if (minutes > 60)
    {
    hours++;
    minutes = 0
    }
  displaySecs.textContent = ((seconds < 10)?'0':'') + seconds 
  displayMins.textContent = ((minutes < 10)?'0':'') + minutes 
  displayHrs.textContent  = ((hours < 10)?'0':'') + hours 
  }
startBtn.onclick = () =>
  {
  startBtn.disabled = true
  stopBtn.disabled  = false
  interval = setInterval( startTimer, 1000)
  }
stopBtn.onclick = () =>
  {
  startBtn.disabled = false
  stopBtn.disabled  = true
  clearInterval(interval)
  }
resetBtn.onclick = () =>
  {
  startBtn.disabled = false
  stopBtn.disabled  = true
  clearInterval(interval)
  hours = minutes = seconds = 0
  displaySecs.textContent = displayMins.textContent = displayHrs.textContent = '00'
  }
<p>
  <span id="hours">00</span>h
  <span id="minutes">00</span>m
  <span id="seconds">00</span>s
</p>

<button id="start">start</button>
<button id="stop" disabled>stop</button>
<button id="reset">reset</button>

following the PO's comments for a request for additional explanation on:

displaySecs.textContent = ((seconds < 10)?'0':'') + seconds 

this is like

displaySecs.textContent = (seconds < 10)?'0':''; // set value to character zero if the value
                                                // of second is less than 10
                                               
                                              // otherwise set an empty string

displaySecs.textContent += seconds;  // add the value of seconds             

(seconds < 10)?'0':'' is Conditional (ternary) operator
it is like this function :

function F(second) {
  if (seconds < 10) return '0'  // return string with a character of zéro
  else              return ''   // return an empty string 
}

Nb: your code use an oposite test if(seconds > 9) == if the value is greather than 9. I believe I read somewhere that testing if an integer is less than 10 requires less cycle for the processor than testing if it is supper to 9 - this needs to be verified (but it's not very important, it's just a matter of habit).
.

if my code was without parentheses before the + seconds as:

displaySecs.textContent =  (seconds < 10)?'0':''  + seconds 

it would be interpreted as follows:

displaySecs.textContent =  (seconds < 10) ? '0' : (''+ seconds) 

and would just output the character zero for all values less than 10 (zero through nine) - which would be an error

so I have to precise the order of imperetation with correct parentheses:

displaySecs.textContent = ( (seconds < 10) ? '0' : '' ) + seconds 

hope this explanation will help you?

Mister Jojo
  • 12,060
  • 3
  • 14
  • 33