Skip to content

Commit

Permalink
Stopwatch Web Application
Browse files Browse the repository at this point in the history
  • Loading branch information
maddoxcypher committed Sep 5, 2024
1 parent f606947 commit b2bd0fc
Show file tree
Hide file tree
Showing 5 changed files with 306 additions and 2 deletions.
23 changes: 21 additions & 2 deletions README.md
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
Binary file added images/janos-venczak-3HCYzSVQ5K4-unsplash.jpg
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
36 changes: 36 additions & 0 deletions index.html
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>
97 changes: 97 additions & 0 deletions script.js
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();
}
});
152 changes: 152 additions & 0 deletions styles.css
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;
}
}

0 comments on commit b2bd0fc

Please sign in to comment.