Skip to content

Commit

Permalink
Merge pull request #91 from basic-experimental/timer
Browse files Browse the repository at this point in the history
Create Timer/Stopwatch app
  • Loading branch information
Wolfyxon authored Aug 28, 2024
2 parents 9e3f250 + 32fb5c4 commit cbe9885
Show file tree
Hide file tree
Showing 3 changed files with 372 additions and 0 deletions.
29 changes: 29 additions & 0 deletions other/timer/index.html
Original file line number Diff line number Diff line change
@@ -0,0 +1,29 @@
<!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.01 Transitional//EN"
"http://www.w3.org/TR/html4/loose.dtd">
<html lang="en">
<head>
<title>Timer</title>
<meta charset="UTF-8">
<meta name="viewport" content="width=device-width, initial-scale=1.0, maximum-scale=1.0, user-scalable=0">
<meta name="description" content="Timer for the 3DS.">
<link rel="stylesheet" href="../../styles/global.css">
<link rel="stylesheet" href="timer.css">

<script src="../../scripts/global.js" type="text/javascript"></script>
<script src="timer.js" type="text/javascript"></script>
</head>
<body>
<div id="screens">
<div id="top-screen">
<div id="time-display">00:00:00</div>
</div>
<div id="bottom-screen">
<div id="app-controls"></div>
<div id="tabs">
<div id="tab-timer" class="tab" data-selected="true">Timer</div>
<div id="tab-stopwatch" class="tab" data-selected="false">Stopwatch</div>
</div>
</div>
</div>
</body>
</html>
96 changes: 96 additions & 0 deletions other/timer/timer.css
Original file line number Diff line number Diff line change
@@ -0,0 +1,96 @@
#top-screen, #bottom-screen {
background-color: #2B2B2B;
}

#time-display {
width: 400px;
height 240px;
text-align: center;
color: #E0E0E0;
font-size: 50px;
line-height: 240px;
}

#app-controls {
width: 320px;
height: 200px;
}

#tabs {
width: 320px;
height: 40px;
font-size: 0;
}

.tab {
width: 160px;
height: 40px;
display: inline-block;
text-align: center;
color: #E0E0E0;
font-size: 20px;
line-height: 40px;
outline: 3px solid #808080;
outline-offset: -3px;
}

.tab[data-selected="true"] {
background-color: #606060;
}
#time-select {
text-align: center;
height: 150px;
line-height: 150px;
}
#time-select > div {
display: inline-block;
color: #E0E0E0;
font-weight: bold;
font-size: 30px;
margin-left: 3px;
margin-right: 3px;
}

#time-select > select {
height: 40px;
width: 80px;
-webkit-appearance: none;
text-indent: 1px;
border: 0px;
text-align: center;
font-size: 30px;
color: #E0E0E0;
background-color: #404040;
border-radius: 10px;
}

#stopwatch-laps {
height: 140px;
overflow-y: scroll;
margin-bottom: 10px;
}

#stopwatch-laps > table > tr > td {
width: 107px;
font-size: 20px;
color: #E0E0E0;
}

#control-buttons {
height: 50px;
line-height: 50px;
text-align: center;
}

#control-buttons > button {
width: 100px;
height: 40px;
border: 3px outset #555555;
border-radius: 5px;
margin: 0 20px 0 20px;
font-size: 24px;
font-weight: bold;
letter-spacing: 1px;
color: #E0E0E0;
background-color: #404040;
}
247 changes: 247 additions & 0 deletions other/timer/timer.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,247 @@
window.addEventListener("load", function() {
Element.prototype.appendNew = function(tagname, attributes1, attributes2) {
/* Examples:
myElem.appendNew("div") -> myElem.innerHTML == "<div></div>"
myElem.appendNew("div", "Hello, world!") -> myElem.innerHTML == "<div>Hello, world!</div>"
myElem.appendNew("div", {id: "foo"}) -> myElem.innerHTML == "<div id='foo'></div>"
myElem.appendNew("div", {id: "foo"}, "Hello, world!"); -> myElem.innerHTML == "<div id='foo'>Hello, world!</div>"
*/
attributes1 = attributes1 || "";
attributes2 = attributes2 || "";
var content,
attributes;
if(typeof attributes1 === "object") {
attributes = attributes1;
content = attributes2;
} else {
attributes = {};
content = attributes1;
}

var elem = document.createElement(tagname);
if (tagname !== 'input') elem.innerHTML = content;
for (var attribute in attributes) {
if (attributes.hasOwnProperty(attribute)) {
elem[attribute] = attributes[attribute];
elem.setAttribute(attribute, attributes[attribute]);
}
}
this.appendChild(elem);
return elem;
};

Element.prototype.prependNew = function(tagname, attributes1, attributes2) {
/* Examples:
myElem.prependNew("div") -> myElem.innerHTML == "<div></div>"
myElem.prependNew("div", "Hello, world!") -> myElem.innerHTML == "<div>Hello, world!</div>"
myElem.prependNew("div", {id: "foo"}) -> myElem.innerHTML == "<div id='foo'></div>"
myElem.prependNew("div", {id: "foo"}, "Hello, world!"); -> myElem.innerHTML == "<div id='foo'>Hello, world!</div>"
*/
attributes1 = attributes1 || "";
attributes2 = attributes2 || "";
var content,
attributes;
if(typeof attributes1 === "object") {
attributes = attributes1;
content = attributes2;
} else {
attributes = {};
content = attributes1;
}

var elem = document.createElement(tagname);
if (tagname !== 'input') elem.innerHTML = content;
for (var attribute in attributes) {
if (attributes.hasOwnProperty(attribute)) {
elem[attribute] = attributes[attribute];
elem.setAttribute(attribute, attributes[attribute]);
}
}
this.insertBefore(elem, this.childNodes[0]);
return elem;
};

const timeDisplay = document.getElementById("time-display"),
appControls = document.getElementById("app-controls"),
tabTimer = document.getElementById("tab-timer"),
tabStopwatch = document.getElementById("tab-stopwatch");
// Elements
var timeSelect, hourSelect, minuteSelect, secondSelect, timerButtons, timerStartButton, timerStopButton, stopwatchButtons, stopwatchStartButton, stopwatchLapButton, stopwatchStopButton, stopwatchLapTable;
// Misc variables
var activeTab, timerInterval, flashInterval, stopwatchInterval, stopwatchStartTime, stopwatchPausedTime, stopwatchLapTime, stopwatchLapNumber;
openTab("timer");

tabTimer.addEventListener("click", function() {
tabTimer.setAttribute("data-selected", "true");
tabStopwatch.setAttribute("data-selected", "false");
openTab("timer");
}, false);

tabStopwatch.addEventListener("click", function() {
tabStopwatch.setAttribute("data-selected", "true");
tabTimer.setAttribute("data-selected", "false");
stopTimer(false);
openTab("stopwatch");
}, false);

function openTab(tabName) {
if(tabName == activeTab) return;
activeTab = tabName;
if(tabName == "timer") {
clearInterval(stopwatchInterval);
appControls.innerHTML = "";
timeDisplay.innerHTML = "";
timeDisplay.innerText = timerTime(0, 0, 0);
timeSelect = appControls.appendNew("div", {"id": "time-select"});
hourSelect = timeSelect.appendNew("select");
for(var i = 0; i < 24; i++) {
hourSelect.appendNew("option", {"value": i.toString()}, i.toString());
}

timeSelect.appendNew("div", ":");

minuteSelect = timeSelect.appendNew("select");
for(var i = 0; i < 60; i++) {
minuteSelect.appendNew("option", {"value": i.toString()}, ("0" + i).slice(-2));
}

timeSelect.appendNew("div", ":");

secondSelect = timeSelect.appendNew("select");
for(var i = 0; i < 60; i++) {
secondSelect.appendNew("option", {"value": i.toString()}, ("0" + i).slice(-2));
}

timerButtons = appControls.appendNew("div", {"id": "control-buttons"});

timerStartButton = timerButtons.appendNew("button", "Start");
timerStartButton.addEventListener("click", startTimer, false);
} else if(tabName == "stopwatch") {
resetStopwatch();
}
}

function startTimer() {
var hourValue = hourSelect.value,
minuteValue = minuteSelect.value,
secondValue = secondSelect.value;
timerButtons.innerHTML = "";
timerStopButton = timerButtons.appendNew("button", "Stop");
timerStopButton.addEventListener("click", function() {stopTimer(false)}, false);
timeDisplay.innerText = timerTime(hourValue, minuteValue, secondValue);
timerInterval = setInterval(function() {
if(secondValue == 0 && minuteValue == 0 && hourValue == 0) {
stopTimer(true);
return;
}
secondValue -= 1;
if(secondValue < 0) {
minuteValue -= 1;
secondValue = 59;
}
if(minuteValue < 0) {
hourValue -= 1;
minuteValue = 59;
}
timeDisplay.innerText = timerTime(hourValue, minuteValue, secondValue);
}, 1000);
}

function timerTime(hours, minutes, seconds) {
if(hours > 0) {
return hours + ":" + ("0" + minutes).slice(-2) + ":" + ("0" + seconds).slice(-2);
}else if(minutes > 0) {
return minutes + ":" + ("0" + seconds).slice(-2);
} else {
return seconds.toString();
}
}

function stopTimer(alarm) {
clearInterval(timerInterval);
timeDisplay.innerText = timerTime(0, 0, 0);
if(alarm) {
flashInterval = setInterval(function () {
if(timeDisplay.innerText === timerTime(0, 0, 0)) {
timeDisplay.innerHTML = "";
timeDisplay.appendNew("div", {"style": "width: 400px; height: 240px; background-color: #FFFFFF"});
} else {
timeDisplay.innerText = timerTime(0, 0, 0);
}
}, 500);
} else {
if(timerButtons.contains(timerStopButton)) {
timerButtons.innerHTML = "";
timerStartButton = timerButtons.appendNew("button", "Start");
timerStartButton.addEventListener("click", startTimer, false);
}
clearInterval(flashInterval);
}
}

function startStopwatch() {
stopwatchStartTime = new Date().getTime();
stopwatchPausedTime = 0;
stopwatchLapTime = 0;
stopwatchLapNumber = 1;
resumeStopwatch();
}

function lapStopwatch() {
const stopwatchEllapsedTime = stopwatchPausedTime + (new Date().getTime() - stopwatchStartTime),
lapTime = stopwatchEllapsedTime - stopwatchLapTime;
stopwatchLapTime = stopwatchEllapsedTime;
const lapRow = stopwatchLapTable.prependNew("tr");
lapRow.appendNew("td", "Lap " + stopwatchLapNumber);
lapRow.appendNew("td", stopwatchTime(lapTime));
lapRow.appendNew("td", stopwatchTime(stopwatchEllapsedTime));
stopwatchLapNumber++;
}

function stopStopwatch() {
stopwatchPausedTime += new Date().getTime() - stopwatchStartTime;
clearInterval(stopwatchInterval);
stopwatchButtons.innerHTML = "";
stopwatchResetButton = stopwatchButtons.appendNew("button", "Reset");
stopwatchResetButton.addEventListener("click", resetStopwatch, false);
stopwatchResumeButton = stopwatchButtons.appendNew("button", {"style": "font-size: 21px; letter-spacing: 0px;"}, "Resume");
stopwatchResumeButton.addEventListener("click", resumeStopwatch, false);
}

function resetStopwatch() {
appControls.innerHTML = "";
timeDisplay.innerHTML = stopwatchTime(0);
stopwatchLapTable = appControls.appendNew("div", {"id": "stopwatch-laps"}).appendNew("table");
stopwatchButtons = appControls.appendNew("div", {"id": "control-buttons"});

stopwatchStartButton = stopwatchButtons.appendNew("button", "Start");
stopwatchStartButton.addEventListener("click", startStopwatch, false);
}

function resumeStopwatch() {
stopwatchStartTime = new Date().getTime();
stopwatchButtons.innerHTML = "";
stopwatchLapButton = stopwatchButtons.appendNew("button", "Lap");
stopwatchLapButton.addEventListener("click", lapStopwatch, false);
stopwatchStopButton = stopwatchButtons.appendNew("button", "Stop");
stopwatchStopButton.addEventListener("click", stopStopwatch, false);
stopwatchInterval = setInterval(updateStopwatch);
}

function updateStopwatch() {
const stopwatchEllapsedTime = stopwatchPausedTime + (new Date().getTime() - stopwatchStartTime);
timeDisplay.innerText = stopwatchTime(stopwatchEllapsedTime);
}

function stopwatchTime(stopwatchEllapsedTime) {
const centiseconds = Math.floor(stopwatchEllapsedTime / 10) % 100,
seconds = Math.floor(stopwatchEllapsedTime / 1000) % 60,
minutes = Math.floor(stopwatchEllapsedTime / 60000);

if(minutes > 0) {
return minutes + ":" + ("0" + seconds).slice(-2) + "." + (centiseconds + "0").substring(0, 2);
} else {
return seconds + "." + (centiseconds + "0").substring(0, 2);
}
}
}, false);

0 comments on commit cbe9885

Please sign in to comment.