Skip to content

Commit 99e37f2

Browse files
committedMar 4, 2023
add new projects
1 parent d51b3e3 commit 99e37f2

File tree

17 files changed

+781
-0
lines changed

17 files changed

+781
-0
lines changed
 

‎projects/basic-calculator/index.html

Lines changed: 32 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,32 @@
1+
<!DOCTYPE html>
2+
<html>
3+
<head>
4+
<title>Simple Calculator</title>
5+
<link rel="stylesheet" href="style.css" />
6+
</head>
7+
<body>
8+
<div class="calculator">
9+
<input type="text" id="result" readonly /><br /><br />
10+
<div class="buttons">
11+
<button class="clear">C</button>
12+
<button class="operator">/</button>
13+
<button class="operator">*</button>
14+
<button class="operator">-</button>
15+
<button class="number">7</button>
16+
<button class="number">8</button>
17+
<button class="number">9</button>
18+
<button class="operator">+</button>
19+
<button class="number">4</button>
20+
<button class="number">5</button>
21+
<button class="number">6</button>
22+
<button class="equals">=</button>
23+
<button class="number">1</button>
24+
<button class="number">2</button>
25+
<button class="number">3</button>
26+
<button class="number">0</button>
27+
<button class="decimal">.</button>
28+
</div>
29+
</div>
30+
<script src="script.js"></script>
31+
</body>
32+
</html>

‎projects/basic-calculator/script.js

Lines changed: 35 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,35 @@
1+
const resultField = document.getElementById("result");
2+
const buttons = document.querySelectorAll("button");
3+
4+
for (let i = 0; i < buttons.length; i++) {
5+
const button = buttons[i];
6+
button.addEventListener("click", function () {
7+
const buttonValue = button.textContent;
8+
if (buttonValue === "C") {
9+
clearResult();
10+
} else if (buttonValue === "=") {
11+
calculate();
12+
} else {
13+
appendValue(buttonValue);
14+
}
15+
});
16+
}
17+
18+
function appendValue(val) {
19+
resultField.value += val;
20+
}
21+
22+
function clearResult() {
23+
resultField.value = "";
24+
}
25+
26+
function calculate() {
27+
const expression = resultField.value;
28+
const result = eval(expression);
29+
// In JavaScript, eval() is a built-in function that evaluates a string as if it were a JavaScript code and returns the result. It can be used to dynamically evaluate expressions or code that is generated at runtime.
30+
31+
// In the context of a calculator, eval() can be used to evaluate the arithmetic expression entered by the user and return the result.
32+
33+
// For example, if the user enters the expression "2 + 3 * 4", eval("2 + 3 * 4") will return 14, which is the result of evaluating the expression.
34+
resultField.value = result;
35+
}

‎projects/basic-calculator/style.css

Lines changed: 82 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,82 @@
1+
* {
2+
box-sizing: border-box;
3+
}
4+
5+
/* By setting box-sizing: border-box on all elements, we are ensuring that any padding or border we add to an element will be included in its total size. */
6+
7+
.calculator {
8+
max-width: 400px;
9+
margin: 0 auto;
10+
margin-top: 30px;
11+
padding: 20px;
12+
background-color: #f2f2f2;
13+
border: 1px solid #ccc;
14+
border-radius: 5px;
15+
box-shadow: 0 2px 5px rgba(0, 0, 0, 0.3);
16+
}
17+
18+
#result {
19+
width: 100%;
20+
padding: 10px;
21+
font-size: 24px;
22+
border: none;
23+
border-radius: 5px;
24+
box-shadow: 0 2px 5px rgba(0, 0, 0, 0.3) inset;
25+
26+
/* In this case, the box-shadow property is set to 0 2px 5px rgba(0, 0, 0, 0.3) inset. This means that the shadow will have no horizontal offset (0), a vertical offset of 2px, a blur radius of 5px, and a color of rgba(0, 0, 0, 0.3). The inset keyword is used to specify that the shadow should be an inset shadow, rather than an outset shadow. */
27+
}
28+
29+
.buttons {
30+
display: grid;
31+
grid-template-columns: repeat(4, 1fr);
32+
/* grid-template-columns: repeat(4, 1fr) is a CSS property that sets the size of each column in a grid container. In this case, the repeat(4, 1fr) value creates a grid with four equal-sized columns.
33+
34+
The fr unit stands for "fractional unit" and is used to divide the available space in a grid container. In this case, each column takes up an equal fraction of the available space, regardless of the size of the container.
35+
36+
So, with grid-template-columns: repeat(4, 1fr), the grid container will be divided into four equal-sized columns, which is what we want for our calculator layout. */
37+
grid-gap: 10px;
38+
margin-top: 20px;
39+
}
40+
41+
button {
42+
padding: 10px;
43+
font-size: 24px;
44+
border: none;
45+
border-radius: 5px;
46+
box-shadow: 0 2px 5px rgba(0, 0, 0, 0.3);
47+
cursor: pointer;
48+
transition: background-color 0.3s ease;
49+
}
50+
51+
button:hover {
52+
background-color: #ddd;
53+
}
54+
55+
.clear {
56+
background-color: #ff4136;
57+
color: #fff;
58+
}
59+
60+
.operator {
61+
background-color: #0074d9;
62+
color: #fff;
63+
}
64+
65+
.number {
66+
background-color: #fff;
67+
color: #333;
68+
}
69+
70+
.equals {
71+
grid-row: span 3;
72+
/* grid-row: span 3; is a CSS property that sets the number of rows an element spans in a CSS grid container.
73+
74+
In this case, span 3 is used to make the element span three rows in the grid container. */
75+
background-color: #01ff70;
76+
color: #fff;
77+
}
78+
79+
.decimal {
80+
background-color: #fff;
81+
color: #333;
82+
}

‎projects/image-search-app/app.js

Lines changed: 70 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,70 @@
1+
// Set the access key for the Unsplash API
2+
const accessKey = "3I7M0FgMDBz0BC9OMC4e4wi9ByTMXZYt0Rk4fQ15TKs";
3+
4+
// Get elements from the HTML document using their IDs
5+
const searchForm = document.getElementById("search-form");
6+
const searchInput = document.getElementById("search-input");
7+
const searchResults = document.getElementById("search-results");
8+
const showMoreButton = document.getElementById("show-more-button");
9+
10+
// Initialize variables
11+
let page = 1;
12+
let query = "";
13+
14+
// Create an asynchronous function to search for images
15+
async function searchImages() {
16+
// Set the query value to the input value from the search form
17+
query = searchInput.value;
18+
// Create the URL for the Unsplash API with the page number, query, and access key
19+
const url = `https://api.unsplash.com/search/photos?page=${page}&query=${query}&client_id=${accessKey}`;
20+
// Send a request to the API and wait for the response
21+
const response = await fetch(url);
22+
// Parse the response data as JSON
23+
const data = await response.json();
24+
// Get the results array from the response data
25+
const results = data.results;
26+
27+
// If this is the first page of results, clear the search results div
28+
if (page === 1) {
29+
searchResults.innerHTML = "";
30+
}
31+
32+
// Loop through each result and create a div with an image and link for each one
33+
results.forEach((result) => {
34+
const imageWrapper = document.createElement("div");
35+
imageWrapper.classList.add("search-result");
36+
37+
const image = document.createElement("img");
38+
image.src = result.urls.small;
39+
image.alt = result.alt_description;
40+
41+
const imageLink = document.createElement("a");
42+
imageLink.href = result.links.html;
43+
imageLink.target = "_blank";
44+
imageLink.textContent = result.alt_description;
45+
46+
imageWrapper.appendChild(image);
47+
imageWrapper.appendChild(imageLink);
48+
searchResults.appendChild(imageWrapper);
49+
});
50+
51+
// Increment the page number for the next search
52+
page++;
53+
54+
// Show the "show more" button if there are more than one page of results
55+
if (page > 1) {
56+
showMoreButton.style.display = "block";
57+
}
58+
}
59+
60+
// Listen for a submit event on the search form, prevent the default action, and search for images
61+
searchForm.addEventListener("submit", (event) => {
62+
event.preventDefault();
63+
page = 1;
64+
searchImages();
65+
});
66+
67+
// Listen for a click event on the "show more" button and search for more images
68+
showMoreButton.addEventListener("click", () => {
69+
searchImages();
70+
});

‎projects/image-search-app/index.html

Lines changed: 28 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,28 @@
1+
<!DOCTYPE html>
2+
<html lang="en">
3+
<head>
4+
<meta charset="UTF-8" />
5+
<title>Unsplash Image Search App</title>
6+
<link rel="stylesheet" href="style.css" />
7+
</head>
8+
<body>
9+
<h1>Image Search App</h1>
10+
<form id="search-form">
11+
<input type="text" id="search-input" placeholder="Search for images..." />
12+
<button type="submit" id="search-button">Search</button>
13+
</form>
14+
<div id="search-results">
15+
<!-- <div class="search-result">
16+
<img
17+
src="https://images.unsplash.com/photo-1503696967350-ad1874122058?crop=entropy&amp;cs=tinysrgb&amp;fit=max&amp;fm=jpg&amp;ixid=Mnw0MTc4MDN8MHwxfHNlYXJjaHwxfHxuaWNlfGVufDB8fHx8MTY3NzgxOTYwMg&amp;ixlib=rb-4.0.3&amp;q=80&amp;w=400"
18+
alt="beach near road at daytime"
19+
/><a href="https://unsplash.com/photos/mpVZVCClgac" target="_blank"
20+
>beach near road at daytime</a
21+
>
22+
</div> -->
23+
</div>
24+
<button id="show-more-button">Show More</button>
25+
26+
<script src="app.js"></script>
27+
</body>
28+
</html>

‎projects/image-search-app/style.css

Lines changed: 170 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,170 @@
1+
body {
2+
background-color: #f9f9f9; /* Sets the background color of the body element to a light gray */
3+
font-family: Arial, sans-serif; /* Sets the font family of the text inside the body to Arial or a generic sans-serif font */
4+
font-size: 16px; /* Sets the font size of the text inside the body to 16 pixels */
5+
line-height: 1.6; /* Sets the line height of the text inside the body to 1.6 times the font size */
6+
color: #333; /* Sets the color of the text inside the body to a dark gray */
7+
}
8+
9+
h1 {
10+
font-size: 36px; /* Sets the font size of the h1 heading to 36 pixels */
11+
font-weight: bold; /* Makes the h1 heading bold */
12+
text-align: center; /* Centers the h1 heading horizontally within its container */
13+
margin-top: 40px; /* Adds a top margin of 40 pixels to the h1 heading */
14+
margin-bottom: 60px; /* Adds a bottom margin of 60 pixels to the h1 heading */
15+
}
16+
17+
#search-form {
18+
display: flex; /* Set the display property of the element to flex */
19+
justify-content: center; /* Center the child elements horizontally */
20+
align-items: center; /* Center the child elements vertically */
21+
margin-bottom: 60px; /* Add a bottom margin of 60 pixels to the element */
22+
}
23+
24+
#search-input {
25+
width: 60%; /* Set the width of the element to 60% of its container */
26+
max-width: 400px; /* Set the maximum width of the element to 400 pixels */
27+
padding: 10px 20px; /* Add 10 pixels of padding to the top and bottom and 20 pixels of padding to the left and right of the element */
28+
border: none; /* Remove the border from the element */
29+
border-radius: 5px; /* Add a 5-pixel radius to the element's border corners */
30+
box-shadow: 0px 0px 5px rgba(0, 0, 0, 0.2); /* Add a 5-pixel box shadow to the element */
31+
font-size: 18px; /* Set the font size of the element to 18 pixels */
32+
color: #333; /* Set the text color of the element to #333 */
33+
}
34+
35+
#search-button {
36+
padding: 10px 20px; /* Sets the padding of the button */
37+
background-color: #4caf50; /* Sets the background color of the button */
38+
color: white; /* Sets the text color of the button */
39+
font-size: 18px; /* Sets the font size of the button text */
40+
border: none; /* Removes the border of the button */
41+
border-radius: 5px; /* Sets the border radius of the button */
42+
box-shadow: 0px 0px 5px rgba(0, 0, 0, 0.2); /* Sets the box shadow of the button */
43+
cursor: pointer; /* Changes the cursor to pointer when hovering over the button */
44+
transition: background-color 0.3s ease-in-out; /* Sets the transition effect when the background color changes */
45+
}
46+
47+
#search-button:hover {
48+
background-color: #3e8e41; /* Changes the background color when hovering over the button */
49+
}
50+
51+
#search-results {
52+
display: flex; /* sets the display type of the element to flex*/
53+
flex-wrap: wrap; /* allows the flex items to wrap to multiple lines*/
54+
justify-content: space-between; /* aligns the flex items along the main axis with equal spacing between them*/
55+
margin: 0 auto; /* sets the top and bottom margins to 0 and the left and right margins to auto*/
56+
max-width: 1200px; /* sets the maximum width of the element to 1200 pixels*/
57+
}
58+
59+
/* Sets the styles for an individual search result element */
60+
.search-result {
61+
/* Adds 60px margin to the bottom of each search result element */
62+
margin-bottom: 60px;
63+
64+
/* Sets the width of the search result element to 30% of the parent container */
65+
width: 30%;
66+
67+
/* Adds rounded corners to the search result element */
68+
border-radius: 5px;
69+
70+
/* Adds a box shadow to the search result element */
71+
box-shadow: 0px 0px 5px rgba(0, 0, 0, 0.2);
72+
73+
/* Hides any content that overflows the search result element */
74+
overflow: hidden;
75+
}
76+
77+
.search-result img {
78+
/* Sets the width of the image to 100% of its container element */
79+
width: 100%;
80+
81+
/* Sets the height of the image to 200 pixels */
82+
height: 200px;
83+
84+
/* Determines how the image should be resized to cover its container without distorting its aspect ratio */
85+
object-fit: cover;
86+
87+
/* Specifies that any changes to the transform property of the image should be transitioned over a duration of 0.3 seconds with an easing function */
88+
transition: transform 0.3s ease-in-out;
89+
}
90+
91+
.search-result:hover img {
92+
transform: scale(1.05);
93+
/* The transform property scales the image by 1.05, making it 5% larger than its original size. This creates a zoom effect when the user hovers over the image. */
94+
}
95+
96+
.search-result a {
97+
display: block; /* sets the display type to block */
98+
padding: 10px; /* adds padding to the top and bottom of the element */
99+
color: #333; /* sets the text color to dark gray */
100+
text-decoration: none; /* removes any text decoration */
101+
transition: background-color 0.3s ease-in-out; /* sets a transition effect when the background color changes */
102+
}
103+
104+
.search-result a:hover {
105+
background-color: rgba(
106+
0,
107+
0,
108+
0,
109+
0.1
110+
); /* changes the background color to a light gray when the element is hovered over */
111+
}
112+
113+
#show-more-button {
114+
background-color: #008cba; /* Sets the background color of the button to a shade of blue */
115+
border: none; /* Removes the border around the button */
116+
color: white; /* Sets the font color of the button text to white */
117+
padding: 10px 20px; /* Sets the padding of the button to 10px on the top and bottom, and 20px on the left and right */
118+
text-align: center; /* Centers the button text horizontally */
119+
text-decoration: none; /* Removes any text decoration such as underlining */
120+
display: inline-block; /* Displays the button as an inline-level block container */
121+
font-size: 16px; /* Sets the font size of the button text to 16px */
122+
border-radius: 5px; /* Rounds the corners of the button to 5px */
123+
margin-top: 20px; /* Adds a 20px margin on the top of the button */
124+
transition: background-color 0.3s ease; /* Specifies a transition effect for the background color when hovering over the button */
125+
display: none; /* Hides the button */
126+
margin: 0 auto; /* Centers the button horizontally */
127+
margin-bottom: 40px; /* Adds a 40px margin on the bottom of the button */
128+
cursor: pointer; /* Sets the cursor to a pointer when hovering over the button */
129+
}
130+
131+
#show-more-button:hover {
132+
background-color: #0077b5; /* Changes the background color of the button to a darker shade of blue when hovering over it */
133+
}
134+
135+
/* This is a CSS media query, which applies different styles based on the size of the screen.
136+
137+
The first media query applies when the screen width is a maximum of 768px. In this case, it changes the justify-content property of #search-results to center the search results horizontally. It also changes the width of .search-result to 45%.
138+
139+
The second media query applies when the screen width is a maximum of 480px. In this case, it changes the flex-direction property of #search-form to column, which stacks the search input and button vertically. It also adds a margin bottom to #search-input and changes the width of .search-result to 100%, making each search result take up the full width of the screen. */
140+
141+
/* The following styles will apply when the screen size is 768px or smaller */
142+
@media screen and (max-width: 768px) {
143+
/* Centers the search result items */
144+
#search-results {
145+
justify-content: center;
146+
}
147+
148+
/* Decreases the width of each search result item */
149+
.search-result {
150+
width: 45%;
151+
}
152+
}
153+
154+
/* The following styles will apply when the screen size is 480px or smaller */
155+
@media screen and (max-width: 480px) {
156+
/* Changes the direction of the search form to be vertical */
157+
#search-form {
158+
flex-direction: column;
159+
}
160+
161+
/* Adds margin to the bottom of the search input */
162+
#search-input {
163+
margin-bottom: 20px;
164+
}
165+
166+
/* Makes each search result item full width */
167+
.search-result {
168+
width: 100%;
169+
}
170+
}

‎projects/music-player/index.html

Lines changed: 34 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,34 @@
1+
<!DOCTYPE html>
2+
<html>
3+
<head>
4+
<title>Music Player</title>
5+
<link rel="stylesheet" href="style.css" />
6+
</head>
7+
<body>
8+
<div class="container">
9+
<h1 class="title">Music Player</h1>
10+
<div class="player">
11+
<audio id="player" src="" controls></audio>
12+
<div class="player__controls">
13+
<button class="player__button player__button--play"></button>
14+
<button class="player__button player__button--pause"></button>
15+
</div>
16+
<div class="player__progress">
17+
<div class="player__progress-bar"></div>
18+
</div>
19+
</div>
20+
<ul class="playlist">
21+
<li class="playlist__item">
22+
<a href="#" data-src="songs/song1.m4a">Song 1</a>
23+
</li>
24+
<li class="playlist__item">
25+
<a href="#" data-src="songs/song2.m4a">Song 2</a>
26+
</li>
27+
<li class="playlist__item">
28+
<a href="#" data-src="songs/song3.m4a">Song 3</a>
29+
</li>
30+
</ul>
31+
</div>
32+
<script src="script.js"></script>
33+
</body>
34+
</html>

‎projects/music-player/pause.png

10.2 KB
Loading

‎projects/music-player/play.png

4.64 KB
Loading

‎projects/music-player/script.js

Lines changed: 90 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,90 @@
1+
const playlist = [
2+
{ title: "Song 1", src: "songs/song1.m4a" },
3+
{ title: "Song 2", src: "songs/song2.m4a" },
4+
{ title: "Song 3", src: "songs/song3.m4a" },
5+
];
6+
7+
const links = document.querySelectorAll(".playlist__item a");
8+
9+
links.forEach((link) => {
10+
link.addEventListener("click", function (e) {
11+
e.preventDefault();
12+
const source = this.getAttribute("data-src");
13+
document.querySelector("#player").setAttribute("src", source);
14+
playSong();
15+
16+
// Remove active class from all links
17+
links.forEach((link) => {
18+
link.classList.remove("active-song");
19+
});
20+
21+
// Add active class to clicked link
22+
this.classList.add("active-song");
23+
});
24+
});
25+
26+
function playSong() {
27+
const player = document.querySelector("#player");
28+
const playButton = document.querySelector(".player__button--play");
29+
const pauseButton = document.querySelector(".player__button--pause");
30+
const progressBar = document.querySelector(".player__progress-bar");
31+
32+
if (player.paused) {
33+
player.play();
34+
playButton.classList.remove("active");
35+
pauseButton.classList.add("active");
36+
} else {
37+
player.pause();
38+
playButton.classList.add("active");
39+
pauseButton.classList.remove("active");
40+
}
41+
42+
player.addEventListener("timeupdate", function () {
43+
const progress = (player.currentTime / player.duration) * 100;
44+
progressBar.style.width = `${progress}%`;
45+
});
46+
47+
progressBar.addEventListener("click", function (e) {
48+
const progressWidth = this.offsetWidth;
49+
const clickedWidth = e.offsetX;
50+
const percent = (clickedWidth / progressWidth) * 100;
51+
player.currentTime = (player.duration / 100) * percent;
52+
progressBar.style.width = `${percent}%`;
53+
});
54+
}
55+
56+
function playFirstSong() {
57+
const firstSong = playlist[0].src;
58+
document.querySelector("#player").setAttribute("src", firstSong);
59+
playSong();
60+
}
61+
62+
const playButton = document.querySelector(".player__button--play");
63+
const pauseButton = document.querySelector(".player__button--pause");
64+
65+
playButton.addEventListener("click", function () {
66+
const player = document.querySelector("#player");
67+
player.play();
68+
playButton.classList.remove("active");
69+
pauseButton.classList.add("active");
70+
});
71+
72+
pauseButton.addEventListener("click", function () {
73+
const player = document.querySelector("#player");
74+
player.pause();
75+
playButton.classList.add("active");
76+
pauseButton.classList.remove("active");
77+
});
78+
79+
const player = document.querySelector("#player");
80+
player.addEventListener("play", function () {
81+
playButton.classList.remove("active");
82+
pauseButton.classList.add("active");
83+
});
84+
85+
player.addEventListener("pause", function () {
86+
playButton.classList.add("active");
87+
pauseButton.classList.remove("active");
88+
});
89+
90+
playFirstSong();

‎projects/music-player/songs/song1.m4a

392 KB
Binary file not shown.

‎projects/music-player/songs/song2.m4a

392 KB
Binary file not shown.

‎projects/music-player/songs/song3.m4a

368 KB
Binary file not shown.

‎projects/music-player/style.css

Lines changed: 90 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,90 @@
1+
* {
2+
box-sizing: border-box;
3+
margin: 0;
4+
padding: 0;
5+
}
6+
7+
body {
8+
font-family: Arial, sans-serif;
9+
background-color: #f2f2f2;
10+
}
11+
12+
.container {
13+
max-width: 600px;
14+
margin: 0 auto;
15+
padding: 0 20px;
16+
}
17+
18+
.title {
19+
text-align: center;
20+
margin-top: 50px;
21+
margin-bottom: 50px;
22+
}
23+
24+
.player {
25+
margin-bottom: 50px;
26+
}
27+
28+
.player__controls {
29+
display: flex;
30+
justify-content: center;
31+
margin-bottom: 20px;
32+
}
33+
34+
.player__button {
35+
width: 50px;
36+
height: 50px;
37+
background-color: #fff;
38+
border: none;
39+
cursor: pointer;
40+
margin-right: 10px;
41+
background-image: url("play.png");
42+
background-repeat: no-repeat;
43+
background-position: center;
44+
background-size: 60%;
45+
}
46+
47+
.player__button--pause {
48+
background-image: url("pause.png");
49+
}
50+
51+
.player__button.active {
52+
background-color: #0074d9;
53+
color: #fff;
54+
}
55+
56+
.player__progress {
57+
height: 5px;
58+
background-color: #f5f5f5;
59+
position: relative;
60+
}
61+
62+
.player__progress-bar {
63+
position: absolute;
64+
top: 0;
65+
left: 0;
66+
height: 100%;
67+
background-color: #0074d9;
68+
width: 0%;
69+
}
70+
71+
.playlist__item {
72+
margin-bottom: 10px;
73+
}
74+
75+
.playlist__item a {
76+
display: block;
77+
padding: 10px;
78+
background-color: #fff;
79+
color: #333;
80+
text-decoration: none;
81+
}
82+
83+
.playlist__item a:hover {
84+
background-color: #f5f5f5;
85+
}
86+
87+
.playlist__item a.active-song {
88+
background-color: #0074d9;
89+
color: #fff;
90+
}

‎projects/simple-stopwatch/index.html

Lines changed: 16 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,16 @@
1+
<!DOCTYPE html>
2+
<html>
3+
<head>
4+
<title>Stopwatch</title>
5+
<link rel="stylesheet" type="text/css" href="style.css" />
6+
</head>
7+
<body>
8+
<div id="timer">00:00:00</div>
9+
<div id="buttons">
10+
<button id="start">Start</button>
11+
<button id="stop">Stop</button>
12+
<button id="reset">Reset</button>
13+
</div>
14+
<script src="stopwatch.js"></script>
15+
</body>
16+
</html>
Lines changed: 78 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,78 @@
1+
// Get references to the timer and button elements
2+
var timer = document.getElementById("timer");
3+
var startButton = document.getElementById("start");
4+
var stopButton = document.getElementById("stop");
5+
var resetButton = document.getElementById("reset");
6+
7+
// Initialize variables for tracking the start time, elapsed time, and timer interval
8+
var startTime,
9+
elapsedTime = 0,
10+
timerInterval;
11+
12+
// Function to start the timer
13+
function startTimer() {
14+
// Calculate the start time by subtracting the elapsed time from the current time
15+
startTime = Date.now() - elapsedTime;
16+
17+
// Start an interval that updates the timer display every 10 milliseconds
18+
timerInterval = setInterval(function printTime() {
19+
// Calculate the elapsed time by subtracting the start time from the current time
20+
elapsedTime = Date.now() - startTime;
21+
22+
// Update the timer display with the formatted elapsed time
23+
timer.textContent = formatTime(elapsedTime);
24+
}, 10);
25+
26+
// Disable the start button and enable the stop button
27+
startButton.disabled = true;
28+
stopButton.disabled = false;
29+
}
30+
31+
// Function to stop the timer
32+
function stopTimer() {
33+
// Clear the interval that updates the timer display
34+
clearInterval(timerInterval);
35+
36+
// Enable the start button and disable the stop button
37+
startButton.disabled = false;
38+
stopButton.disabled = true;
39+
}
40+
41+
// Function to reset the timer
42+
function resetTimer() {
43+
// Clear the interval that updates the timer display
44+
clearInterval(timerInterval);
45+
46+
// Reset the elapsed time to 0 and update the timer display
47+
elapsedTime = 0;
48+
timer.textContent = "00:00:00";
49+
50+
// Enable the start button and disable the stop button
51+
startButton.disabled = false;
52+
stopButton.disabled = true;
53+
}
54+
55+
// Function to format the elapsed time as a string
56+
function formatTime(time) {
57+
var hours = Math.floor(time / (1000 * 60 * 60));
58+
var minutes = Math.floor((time % (1000 * 60 * 60)) / (1000 * 60));
59+
var seconds = Math.floor((time % (1000 * 60)) / 1000);
60+
var milliseconds = Math.floor((time % 1000) / 10);
61+
// The ternary operator hours ? (hours > 9 ? hours : "0" + hours) : "00" checks if the hours variable has a value greater than zero. If it does, it checks if it is greater than 9. If it is, it returns the value of hours. If it is less than or equal to 9, it adds a leading zero to the hours value and returns it. If hours is zero, it returns the string "00".
62+
63+
// The same logic is applied to format the minutes and seconds values.
64+
return (
65+
(hours ? (hours > 9 ? hours : "0" + hours) : "00") +
66+
":" +
67+
(minutes ? (minutes > 9 ? minutes : "0" + minutes) : "00") +
68+
":" +
69+
(seconds ? (seconds > 9 ? seconds : "0" + seconds) : "00") +
70+
"." +
71+
(milliseconds > 9 ? milliseconds : "0" + milliseconds)
72+
);
73+
}
74+
75+
// Add event listeners to the button elements to trigger the timer functions
76+
startButton.addEventListener("click", startTimer);
77+
stopButton.addEventListener("click", stopTimer);
78+
resetButton.addEventListener("click", resetTimer);

‎projects/simple-stopwatch/style.css

Lines changed: 56 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,56 @@
1+
body {
2+
background-color: #f0f0f0;
3+
font-family: "Poppins", sans-serif;
4+
display: flex;
5+
flex-direction: column;
6+
justify-content: center;
7+
align-items: center;
8+
height: 100vh;
9+
overflow: hidden;
10+
}
11+
12+
#timer {
13+
font-size: 7rem;
14+
font-weight: 700;
15+
color: #f92672;
16+
text-shadow: 2px 2px #f8a5c2;
17+
/* In the current code, the value 2px 2px #f8a5c2 sets a shadow that is 2 pixels to the right and 2 pixels down of the text, with a blur radius of 0 (no blur), and a color of #f8a5c2. */
18+
width: 600px;
19+
text-align: center;
20+
margin: 40px auto;
21+
}
22+
23+
#buttons {
24+
display: flex;
25+
justify-content: center;
26+
}
27+
28+
button {
29+
background-color: #f92672;
30+
color: white;
31+
border: none;
32+
border-radius: 30px;
33+
font-size: 2rem;
34+
font-weight: bold;
35+
padding: 1.5rem 4rem;
36+
/* In the current code, the value 1.5rem 4rem sets a padding of 1.5rem (24px) for the top and bottom sides of the buttons, and 4rem (64px) for the left and right sides of the buttons. */
37+
margin: 1rem;
38+
cursor: pointer;
39+
transition: background-color 0.2s;
40+
box-shadow: 2px 2px 10px rgba(0, 0, 0, 0.3);
41+
}
42+
43+
button:hover {
44+
background-color: #f44583;
45+
box-shadow: 2px 2px 10px rgba(0, 0, 0, 0.5);
46+
}
47+
48+
button:active {
49+
background-color: #f34282;
50+
box-shadow: none;
51+
}
52+
53+
button[disabled] {
54+
opacity: 0.5;
55+
cursor: default;
56+
}

0 commit comments

Comments
 (0)
Please sign in to comment.