1
1
/**
2
2
* JavaScript30 by Wes Bos, https://javascript30.com/
3
3
* 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.
8
10
* Compilation command:
9
11
* tsc --removeComments --strictNullChecks --noImplicitAny --target es5 typescripts.ts
10
12
*/
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