11/** 
22 * JavaScript30 by Wes Bos, https://javascript30.com/ 
33 * TypeScript implementation by Will Wager 
4-  * Project: 
5-  * Concepts: 
6-  * Key takeaways: 
7-  * Sidenotes: 
4+  * Project: Countdown Timer 
5+  * Concepts: Using Date and setInterval. Displaying countdowns to the DOM. 
6+  * Key takeaways: Use Date, not a counter with setInterval. 
7+  *   Preceeding zero for single digits pattern. 
8+  * Sidenotes: name attribute allows access through document global, but it's not very 
9+  *   Typescript friendly. 
810 * Compilation command: 
911 *   tsc --removeComments --strictNullChecks --noImplicitAny --target es5 typescripts.ts 
1012 */ 
13+ 
14+ interface  MyDocument  extends  Document  { 
15+   customForm : HTMLFormElement ; 
16+ } 
17+ 
18+ let  countdown : number ; 
19+ const  timerDisplay  =  document . querySelector ( '.display__time-left' ) !  as  HTMLHeadingElement ; 
20+ const  endTime  =  document . querySelector ( '.display__end-time' ) !  as  HTMLParagraphElement ; 
21+ const  buttons  =  document . querySelectorAll ( '[data-time]' ) !  as  NodeListOf < HTMLElement > ; 
22+ 
23+ function  timer ( seconds : number )  { 
24+   clearInterval ( countdown ) ; 
25+   const  now  =  Date . now ( ) ; 
26+   const  then  =  now  +  seconds  *  1000 ; 
27+   displayTimeLeft ( seconds ) ; 
28+   displayEndTime ( then ) ; 
29+ 
30+   countdown  =  setInterval ( ( )  =>  { 
31+     const  secondsLeft  =  Math . round ( ( then  -  Date . now ( ) )  /  1000 ) ; 
32+     if  ( secondsLeft  <  0 )  { 
33+       clearInterval ( countdown ) ; 
34+       return ; 
35+     } 
36+     displayTimeLeft ( secondsLeft ) ; 
37+   } ,  1000 ) ; 
38+ } 
39+ 
40+ function  displayTimeLeft ( seconds : number )  { 
41+   const  minutes  =  Math . floor ( seconds  /  60 ) ; 
42+   const  remainderSeconds  =  seconds  %  60 ; 
43+   const  display  =  `${ minutes }  :${ remainderSeconds  <  10  ? '0'  : '' } ${ remainderSeconds }  ` ; 
44+   document . title  =  display ; 
45+   timerDisplay . textContent  =  display ; 
46+ } 
47+ 
48+ function  displayEndTime ( timestamp : number )  { 
49+   const  end  =  new  Date ( timestamp ) ; 
50+   const  hour  =  end . getHours ( ) ; 
51+   const  adjustedHour  =  hour  >  12  ? hour  -  12  : hour ; 
52+   const  minutes  =  end . getMinutes ( ) ; 
53+   endTime . textContent  =  `Be back at ${ adjustedHour }  :${ minutes  <  10  ? '0'  : '' } ${ minutes }  ` ; 
54+ } 
55+ 
56+ function  startTimer ( )  { 
57+   const  seconds  =  Number ( this . dataset . time ) ; 
58+   timer ( seconds ) ; 
59+ } 
60+ 
61+ buttons . forEach ( button  =>  button . addEventListener ( 'click' ,  startTimer ) ) ; 
62+ ( document  as  MyDocument ) . customForm . addEventListener ( 'submit' ,  function  ( this : HTMLFormElement ,  e : Event )  { 
63+   e . preventDefault ( ) ; 
64+   const  mins  =  this . minutes . value ; 
65+   timer ( mins  *  60 ) ; 
66+   this . reset ( ) ; 
67+ } ) 
0 commit comments