-
Notifications
You must be signed in to change notification settings - Fork 0
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
- Loading branch information
1 parent
f606947
commit b2bd0fc
Showing
5 changed files
with
306 additions
and
2 deletions.
There are no files selected for viewing
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -1,2 +1,21 @@ | ||
# PRODIGY_WD_2 | ||
PRODIGY_WD_2 Task StopWatch Web Application | ||
# Interactive Stopwatch Web Application | ||
|
||
## PRODIGY_WD_2 | ||
|
||
This project is an interactive stopwatch web application created as part of the PRODIGY_WD_2 task. | ||
|
||
### Features | ||
|
||
- Start, pause, and reset functionality | ||
- Lap time recording | ||
- Millisecond precision | ||
- Responsive design | ||
- Keyboard shortcuts for easy control | ||
|
||
### Technologies Used | ||
|
||
- HTML5 | ||
- CSS3 | ||
- JavaScript (ES6+) | ||
- Font Awesome for icons | ||
- Google Material Icons |
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,36 @@ | ||
<!DOCTYPE html> | ||
<html lang="en"> | ||
<head> | ||
<meta charset="UTF-8"> | ||
<meta name="viewport" content="width=device-width, initial-scale=1.0"> | ||
<title>Interactive Stopwatch</title> | ||
<link rel="stylesheet" href="styles.css"> | ||
<link href="https://fonts.googleapis.com/icon?family=Material+Icons" rel="stylesheet"> | ||
<link rel="stylesheet" href="https://cdnjs.cloudflare.com/ajax/libs/font-awesome/6.4.0/css/all.min.css"> | ||
</head> | ||
<body> | ||
<div class="stopwatch-container"> | ||
<div class="stopwatch-header"> | ||
<i class="fa-solid fa-stopwatch"></i> | ||
<h1>Stopwatch</h1> | ||
</div> | ||
<div class="time-display"> | ||
<span id="hours">00</span>: | ||
<span id="minutes">00</span>: | ||
<span id="seconds">00</span>: | ||
<span id="milliseconds">000</span> | ||
</div> | ||
<div class="controls"> | ||
<button id="startBtn"><i class="material-icons">play_arrow</i> Start</button> | ||
<button id="pauseBtn" disabled><i class="material-icons">pause</i> Pause</button> | ||
<button id="resetBtn" disabled><i class="material-icons">replay</i> Reset</button> | ||
<button id="lapBtn" disabled><i class="material-icons">flag</i> Lap</button> | ||
</div> | ||
<div class="lap-times"> | ||
<h3>Lap Times</h3> | ||
<ul id="lapList"></ul> | ||
</div> | ||
</div> | ||
<script src="script.js"></script> | ||
</body> | ||
</html> |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,97 @@ | ||
let startTime; | ||
let elapsedTime = 0; | ||
let timerInterval; | ||
let isRunning = false; | ||
let lapCount = 0; | ||
|
||
const timeDisplay = document.querySelector('.time-display'); | ||
const startBtn = document.getElementById('startBtn'); | ||
const pauseBtn = document.getElementById('pauseBtn'); | ||
const resetBtn = document.getElementById('resetBtn'); | ||
const lapBtn = document.getElementById('lapBtn'); | ||
const lapList = document.getElementById('lapList'); | ||
|
||
function startTimer() { | ||
if (!isRunning) { | ||
startTime = Date.now() - elapsedTime; | ||
timerInterval = setInterval(updateTime, 10); | ||
isRunning = true; | ||
startBtn.disabled = true; | ||
pauseBtn.disabled = false; | ||
resetBtn.disabled = false; | ||
lapBtn.disabled = false; | ||
} | ||
} | ||
|
||
function pauseTimer() { | ||
if (isRunning) { | ||
clearInterval(timerInterval); | ||
isRunning = false; | ||
startBtn.innerHTML = '<i class="material-icons">play_arrow</i> Resume'; | ||
startBtn.disabled = false; | ||
pauseBtn.disabled = true; | ||
} | ||
} | ||
|
||
function resetTimer() { | ||
clearInterval(timerInterval); | ||
isRunning = false; | ||
elapsedTime = 0; | ||
lapCount = 0; | ||
updateDisplay(); | ||
startBtn.innerHTML = '<i class="material-icons">play_arrow</i> Start'; | ||
startBtn.disabled = false; | ||
pauseBtn.disabled = true; | ||
resetBtn.disabled = true; | ||
lapBtn.disabled = true; | ||
lapList.innerHTML = ''; | ||
} | ||
|
||
function recordLap() { | ||
if (isRunning) { | ||
lapCount++; | ||
const lapTime = formatTime(elapsedTime); | ||
const lapItem = document.createElement('li'); | ||
lapItem.textContent = `Lap ${lapCount}: ${lapTime}`; | ||
lapList.prepend(lapItem); | ||
} | ||
} | ||
|
||
function updateTime() { | ||
elapsedTime = Date.now() - startTime; | ||
updateDisplay(); | ||
} | ||
|
||
function updateDisplay() { | ||
const time = formatTime(elapsedTime); | ||
timeDisplay.textContent = time; | ||
} | ||
|
||
function formatTime(time) { | ||
const date = new Date(time); | ||
const hours = date.getUTCHours().toString().padStart(2, '0'); | ||
const minutes = date.getUTCMinutes().toString().padStart(2, '0'); | ||
const seconds = date.getUTCSeconds().toString().padStart(2, '0'); | ||
const milliseconds = date.getUTCMilliseconds().toString().padStart(3, '0'); | ||
return `${hours}:${minutes}:${seconds}:${milliseconds}`; | ||
} | ||
|
||
startBtn.addEventListener('click', startTimer); | ||
pauseBtn.addEventListener('click', pauseTimer); | ||
resetBtn.addEventListener('click', resetTimer); | ||
lapBtn.addEventListener('click', recordLap); | ||
|
||
document.addEventListener('keydown', (e) => { | ||
if (e.code === 'Space') { | ||
e.preventDefault(); | ||
if (isRunning) { | ||
pauseTimer(); | ||
} else { | ||
startTimer(); | ||
} | ||
} else if (e.code === 'KeyR') { | ||
resetTimer(); | ||
} else if (e.code === 'KeyL') { | ||
recordLap(); | ||
} | ||
}); |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,152 @@ | ||
body { | ||
font-family: 'Roboto', Arial, sans-serif; | ||
display: flex; | ||
justify-content: center; | ||
align-items: center; | ||
min-height: 100vh; | ||
margin: 0; | ||
background-image: url('images/janos-venczak-3HCYzSVQ5K4-unsplash.jpg'); | ||
background-size: cover; | ||
background-position: center; | ||
background-repeat: no-repeat; | ||
background-attachment: fixed; | ||
} | ||
|
||
.stopwatch-container { | ||
background-color: rgba(255, 255, 255, 0.85); | ||
border-radius: 20px; | ||
padding: 40px; | ||
box-shadow: 0 15px 30px rgba(0, 0, 0, 0.2); | ||
backdrop-filter: blur(10px); | ||
max-width: 450px; | ||
width: 100%; | ||
} | ||
|
||
.stopwatch-header { | ||
display: flex; | ||
align-items: center; | ||
justify-content: center; | ||
margin-bottom: 30px; | ||
} | ||
|
||
.stopwatch-header i { | ||
font-size: 42px; | ||
color: #3498db; | ||
margin-right: 20px; | ||
} | ||
|
||
.stopwatch-header h1 { | ||
font-size: 32px; | ||
color: #2c3e50; | ||
margin: 0; | ||
font-weight: 700; | ||
} | ||
|
||
.time-display { | ||
font-size: 56px; | ||
text-align: center; | ||
margin-bottom: 40px; | ||
color: #2c3e50; | ||
font-weight: 700; | ||
text-shadow: 2px 2px 4px rgba(0,0,0,0.1); | ||
letter-spacing: 2px; | ||
} | ||
|
||
.controls { | ||
display: grid; | ||
grid-template-columns: repeat(2, 1fr); | ||
gap: 20px; | ||
margin-bottom: 40px; | ||
} | ||
|
||
button { | ||
padding: 15px 25px; | ||
font-size: 18px; | ||
font-weight: 600; | ||
cursor: pointer; | ||
background-color: #3498db; | ||
color: white; | ||
border: none; | ||
border-radius: 10px; | ||
transition: all 0.3s ease; | ||
display: flex; | ||
align-items: center; | ||
justify-content: center; | ||
box-shadow: 0 4px 6px rgba(0,0,0,0.1); | ||
} | ||
|
||
button:hover { | ||
background-color: #2980b9; | ||
transform: translateY(-3px); | ||
box-shadow: 0 6px 8px rgba(0,0,0,0.15); | ||
} | ||
|
||
button:disabled { | ||
background-color: #bdc3c7; | ||
color: #7f8c8d; | ||
cursor: not-allowed; | ||
box-shadow: none; | ||
transform: none; | ||
} | ||
|
||
.material-icons { | ||
font-size: 24px; | ||
margin-right: 10px; | ||
} | ||
|
||
.lap-times { | ||
max-height: 250px; | ||
overflow-y: auto; | ||
background-color: rgba(255, 255, 255, 0.9); | ||
border-radius: 10px; | ||
padding: 20px; | ||
box-shadow: inset 0 2px 4px rgba(0,0,0,0.1); | ||
} | ||
|
||
.lap-times h3 { | ||
text-align: center; | ||
color: #2c3e50; | ||
margin-top: 0; | ||
margin-bottom: 15px; | ||
font-size: 24px; | ||
font-weight: 600; | ||
} | ||
|
||
#lapList { | ||
list-style-type: none; | ||
padding: 0; | ||
} | ||
|
||
#lapList li { | ||
padding: 10px 0; | ||
border-bottom: 1px solid #ecf0f1; | ||
color: #34495e; | ||
font-size: 16px; | ||
} | ||
|
||
#lapList li:last-child { | ||
border-bottom: none; | ||
} | ||
|
||
@media (max-width: 480px) { | ||
.stopwatch-container { | ||
padding: 30px; | ||
margin: 20px; | ||
} | ||
|
||
.time-display { | ||
font-size: 48px; | ||
} | ||
|
||
.controls { | ||
grid-template-columns: 1fr; | ||
} | ||
|
||
.stopwatch-header i { | ||
font-size: 36px; | ||
} | ||
|
||
.stopwatch-header h1 { | ||
font-size: 28px; | ||
} | ||
} |