I'm learning OOP and the first exercise of the course was to made a Stopwatch class. I did it really fast and decided to make an interface for this little app.
I created the interface. Basically I want to know if the aproach that I used is fine, if I needed to create another class to control the ui, etc. I'm really lost with this OOP-UI integration thing.
The app is available in https://nacho-p5.github.io/
Here's the code:
Repo: https://github.com/nacho-p5/nacho-p5.github.io
index.html
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<meta http-equiv="X-UA-Compatible" content="ie=edge">
<link rel="stylesheet" href="normalize.css">
<link href="https://fonts.googleapis.com/css2?family=Lato:wght@100;300;700&display=swap" rel="stylesheet">
<link rel="stylesheet" href="style.css">
<title>Online Stopwatch</title>
</head>
<body>
<div id="sw">
<span id="sw-screen">0.00</span>
<div id="buttons">
<button type="submit" id="btnStart" class="btn">Start</button>
<button type="submit" id="btnStop" class="btn">Stop</button type="submit">
<button type="submit" id="btnReset" class="btn">Reset</button type="submit">
</div>
</div>
</body>
<script src="stopwatch.js"></script>
</html>
stopwatch.js
// SW class
function Stopwatch() {
let counter = 0;
let intervalID = 0;
const screen = document.getElementById('sw-screen');
const addMiliseconds = () => {
counter += 0.01
updateScreen();
};
const updateScreen = () => {
screen.innerHTML = counter.toFixed(2);
}
// start()
this.start = function() {
if (intervalID != 0) {
throw new Error('Stopwatch has already started.')
}
intervalID = setInterval(addMiliseconds, 10);
};
// stop()
this.stop = function() {
if (intervalID == 0) {
throw new Error('Stopwatch has already stoped.')
}
clearInterval(intervalID);
intervalID = 0;
};
// reset()
this.reset = () => {
if (intervalID != 0) {
this.stop();
};
counter = 0;
updateScreen();
};
// duration()
Object.defineProperty(this, 'duration', {
get: function() {
console.log(intervalID);
return counter
}
});
};
// UI class
function UI(arrayOfbuttons) {
this.toggleClass = function(elem) {
arrayOfbuttons.forEach(e => e.classList.remove('activeBtn'))
elem.classList.add('activeBtn');
};
this.removeClass = function() {
arrayOfbuttons.forEach(e => e.classList.remove('activeBtn'))
};
};
// HTML components
const screen = document.getElementById('sw-screen');
const btnStart = document.getElementById('btnStart');
const btnStop = document.getElementById('btnStop');
const btnReset = document.getElementById('btnReset');
// Initialize classes
const sw = new Stopwatch();
const ui = new UI([btnStart, btnStop]);
// Add event listeners
btnStart.addEventListener('click', function() {
sw.start();
ui.toggleClass(this);
});
btnStop.addEventListener('click', function() {
sw.stop();
ui.toggleClass(this);
});
btnReset.addEventListener('click', function() {
sw.reset();
ui.removeClass();
});