Skip to content

Commit dd8ba25

Browse files
committed
Project 29 complete.
1 parent 9eb7134 commit dd8ba25

File tree

2 files changed

+66
-6
lines changed

2 files changed

+66
-6
lines changed

29 - Countdown Timer/index.html

+5-2
Original file line numberDiff line numberDiff line change
@@ -1,11 +1,13 @@
11
<!DOCTYPE html>
22
<html lang="en">
3+
34
<head>
45
<meta charset="UTF-8">
56
<title>Countdown Timer</title>
67
<link href='https://fonts.googleapis.com/css?family=Inconsolata' rel='stylesheet' type='text/css'>
78
<link rel="stylesheet" href="style.css">
89
</head>
10+
911
<body>
1012
<div class="timer">
1113
<div class="timer__controls">
@@ -24,6 +26,7 @@ <h1 class="display__time-left"></h1>
2426
</div>
2527
</div>
2628

27-
<script src="scripts-START.js"></script>
29+
<script src="typescripts.js"></script>
2830
</body>
29-
</html>
31+
32+
</html>

29 - Countdown Timer/typescripts.ts

+61-4
Original file line numberDiff line numberDiff line change
@@ -1,10 +1,67 @@
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

Comments
 (0)