Initial commit
This commit is contained in:
commit
5f0724e283
37
README.md
Normal file
37
README.md
Normal file
@ -0,0 +1,37 @@
|
||||
Welcome to Glitch
|
||||
=================
|
||||
|
||||
Click `Show` in the header to see your app live. Updates to your code will instantly deploy and update live.
|
||||
|
||||
**Glitch** is the friendly community where you'll build the app of your dreams. Glitch lets you instantly create, remix, edit, and host an app, bot or site, and you can invite collaborators or helpers to simultaneously edit code with you.
|
||||
|
||||
Find out more [about Glitch](https://glitch.com/about).
|
||||
|
||||
|
||||
Your Project
|
||||
------------
|
||||
|
||||
### ← README.md
|
||||
|
||||
That's this file, where you can tell people what your cool website does and how you built it.
|
||||
|
||||
### ← index.html
|
||||
|
||||
Where you'll write the content of your website.
|
||||
|
||||
### ← style.css
|
||||
|
||||
CSS files add styling rules to your content.
|
||||
|
||||
### ← script.js
|
||||
|
||||
If you're feeling fancy you can add interactivity to your site with JavaScript.
|
||||
|
||||
### ← assets
|
||||
|
||||
Drag in `assets`, like images or music, to add them to your project
|
||||
|
||||
Made by [Glitch](https://glitch.com/)
|
||||
-------------------
|
||||
|
||||
\ ゜o゜)ノ
|
BIN
assets/JetBrainsMono-Regular.ttf
Normal file
BIN
assets/JetBrainsMono-Regular.ttf
Normal file
Binary file not shown.
BIN
assets/JetBrainsMono-Regular.woff2
Normal file
BIN
assets/JetBrainsMono-Regular.woff2
Normal file
Binary file not shown.
BIN
assets/fa-solid-900.eot
Normal file
BIN
assets/fa-solid-900.eot
Normal file
Binary file not shown.
1015
assets/fa-solid-900.svg
Normal file
1015
assets/fa-solid-900.svg
Normal file
File diff suppressed because one or more lines are too long
After Width: | Height: | Size: 890 KiB |
BIN
assets/fa-solid-900.ttf
Normal file
BIN
assets/fa-solid-900.ttf
Normal file
Binary file not shown.
BIN
assets/fa-solid-900.woff
Normal file
BIN
assets/fa-solid-900.woff
Normal file
Binary file not shown.
BIN
assets/fa-solid-900.woff2
Normal file
BIN
assets/fa-solid-900.woff2
Normal file
Binary file not shown.
5
assets/fa-solid.min.css
vendored
Normal file
5
assets/fa-solid.min.css
vendored
Normal file
@ -0,0 +1,5 @@
|
||||
/*!
|
||||
* Font Awesome Free 5.15.2 by @fontawesome - https://fontawesome.com
|
||||
* License - https://fontawesome.com/license/free (Icons: CC BY 4.0, Fonts: SIL OFL 1.1, Code: MIT License)
|
||||
*/
|
||||
@font-face{font-family:"Font Awesome 5 Free";font-style:normal;font-weight:900;font-display:block;src:url(/assets/fa-solid-900.eot);src:url(/assets/fa-solid-900.eot?#iefix) format("embedded-opentype"),url(/assets/fa-solid-900.woff2) format("woff2"),url(/assets/fa-solid-900.woff) format("woff"),url(/assets/fa-solid-900.ttf) format("truetype"),url(/assets/fa-solid-900.svg#fontawesome) format("svg")}.fa,.fas{font-family:"Font Awesome 5 Free";font-weight:900}
|
5
assets/fontawesome-solid.min.css
vendored
Normal file
5
assets/fontawesome-solid.min.css
vendored
Normal file
@ -0,0 +1,5 @@
|
||||
/*!
|
||||
* Font Awesome Free 5.15.2 by @fontawesome - https://fontawesome.com
|
||||
* License - https://fontawesome.com/license/free (Icons: CC BY 4.0, Fonts: SIL OFL 1.1, Code: MIT License)
|
||||
*/
|
||||
@font-face{font-family:"Font Awesome 5 Free";font-style:normal;font-weight:900;font-display:block;src:url(../webfonts/fa-solid-900.eot);src:url(../webfonts/fa-solid-900.eot?#iefix) format("embedded-opentype"),url(../webfonts/fa-solid-900.woff2) format("woff2"),url(../webfonts/fa-solid-900.woff) format("woff"),url(../webfonts/fa-solid-900.ttf) format("truetype"),url(../webfonts/fa-solid-900.svg#fontawesome) format("svg")}.fa,.fas{font-family:"Font Awesome 5 Free";font-weight:900}
|
16
bookmark/index.html
Normal file
16
bookmark/index.html
Normal file
@ -0,0 +1,16 @@
|
||||
<!DOCTYPE html>
|
||||
<html lang="en">
|
||||
<head>
|
||||
<meta charset="utf-8">
|
||||
<meta http-equiv="X-UA-Compatible" content="IE=edge">
|
||||
<meta name="viewport" content="width=device-width, initial-scale=1">
|
||||
<link rel="stylesheet" href="/bookmark/style.css">
|
||||
<link rel="shortcut icon" href="/favicon.ico" />
|
||||
<script src="/bookmark/script.js" defer></script>
|
||||
</head>
|
||||
<body>
|
||||
Press <b>CTRL + D / CMD + D</b> or click the <b>Star Icon</b> to add this to your bookmarks.
|
||||
<br><br>
|
||||
<a href="/">Back</a> <a id="open-popup" href="javascript:void(0);">Open Popup Now</a>
|
||||
</body>
|
||||
</html>
|
28
bookmark/script.js
Normal file
28
bookmark/script.js
Normal file
@ -0,0 +1,28 @@
|
||||
var link = location.protocol + "//" + location.host + "/link" + location.search;
|
||||
var popupLink = location.protocol + "//" + location.host + "/popup" + location.search;
|
||||
|
||||
history.replaceState(null, "", link);
|
||||
document.title = parseQueryParams().name + " - Popup Timer";
|
||||
|
||||
document.getElementById("open-popup").onclick = function() {
|
||||
|
||||
window.open(
|
||||
popupLink,
|
||||
"PopupTimer" + Date.now(),
|
||||
"width=250,height=100,menubar=no,toolbar=no,location=no,status=no,resizable=no,scrollbars=no"
|
||||
);
|
||||
|
||||
}
|
||||
|
||||
function parseQueryParams() {
|
||||
if (location.search === "" || location.search.indexOf("?") !== 0) return {};
|
||||
var result = {};
|
||||
location.search.substr(1).split("&").forEach(function(str) {
|
||||
var key = str.split("=")[0];
|
||||
var value;
|
||||
if (str.split("=").length > 1) value = str.split("=")[1];
|
||||
else value = null;
|
||||
result[key] = value;
|
||||
});
|
||||
return result
|
||||
}
|
13
bookmark/style.css
Normal file
13
bookmark/style.css
Normal file
@ -0,0 +1,13 @@
|
||||
body {
|
||||
margin: 1em;
|
||||
font-family: helvetica, arial, sans-serif;
|
||||
font-size: 18px;
|
||||
text-align: center;
|
||||
}
|
||||
a, a:visited {
|
||||
color: #43A047;
|
||||
outline: none;
|
||||
}
|
||||
a:hover {
|
||||
text-decoration: none;
|
||||
}
|
BIN
favicon.ico
Normal file
BIN
favicon.ico
Normal file
Binary file not shown.
After Width: | Height: | Size: 237 B |
70
index.html
Normal file
70
index.html
Normal file
@ -0,0 +1,70 @@
|
||||
<!DOCTYPE html>
|
||||
<html lang="en">
|
||||
<head>
|
||||
<meta charset="utf-8">
|
||||
<meta http-equiv="X-UA-Compatible" content="IE=edge">
|
||||
<meta name="viewport" content="width=device-width, initial-scale=1">
|
||||
<title>Popup Timer</title>
|
||||
<!-- FontAwesome -->
|
||||
<script src="https://kit.fontawesome.com/b3a602c8a0.js" crossorigin="anonymous"></script>
|
||||
<link rel="stylesheet" href="/style.css">
|
||||
<link rel="shortcut icon" href="/favicon.ico" />
|
||||
<script src="/script.js" defer></script>
|
||||
</head>
|
||||
<body>
|
||||
|
||||
<h1>Popup Timer</h1>
|
||||
|
||||
<main>
|
||||
|
||||
<h4>Create new</h4>
|
||||
|
||||
<table id="popup-type">
|
||||
<tr>
|
||||
<td id="timer">Timer</td>
|
||||
<td id="stopwatch">Stopwatch</td>
|
||||
</tr>
|
||||
</table>
|
||||
|
||||
<br><br>
|
||||
|
||||
<div id="input-timer">
|
||||
<label style="float: left;">Time:</label>
|
||||
<div id="time-input-container">
|
||||
<input id="hours" class="time-input" type="number" min="0" step="1" value="0"> h
|
||||
<input id="minutes" class="time-input" type="number" min="0" max="60" step="1" value="0"> m
|
||||
<input id="seconds" class="time-input" type="number" min="0" max="60" step="1" value="0"> s
|
||||
</div>
|
||||
<br>
|
||||
<label>
|
||||
<input id="beep" type="checkbox" checked>Beep when finished
|
||||
</label>
|
||||
<br>
|
||||
<br>
|
||||
</div>
|
||||
|
||||
<div id="input-common">
|
||||
<div style="display:flex;">
|
||||
<label>Name: </label>
|
||||
<input id="name" style="flex: 2;">
|
||||
</div>
|
||||
<br>
|
||||
<label>
|
||||
<input id="autostart" type="checkbox" checked>Start automatically
|
||||
</label>
|
||||
<br><br>
|
||||
<button id="create">Create</button>
|
||||
<br>
|
||||
<span id="bookmark" title="Adds a shortcut for creating the popup to your bookmarks - Shift + Click if it doesn't work">Create Bookmark</span>
|
||||
</div>
|
||||
|
||||
</main>
|
||||
|
||||
<br><br>
|
||||
<span id="link" title="Click to copy"></span>
|
||||
|
||||
<div class="glitchButton" style="position:fixed; top:2em; right:2em;"></div>
|
||||
<script src="https://button.glitch.me/button.js" defer></script>
|
||||
|
||||
</body>
|
||||
</html>
|
20
link/index.html
Normal file
20
link/index.html
Normal file
@ -0,0 +1,20 @@
|
||||
<!DOCTYPE html>
|
||||
<html lang="en">
|
||||
<head>
|
||||
<meta charset="utf-8">
|
||||
<meta http-equiv="X-UA-Compatible" content="IE=edge">
|
||||
<meta name="viewport" content="width=device-width, initial-scale=1">
|
||||
<link rel="stylesheet" href="/link/style.css">
|
||||
<link rel="shortcut icon" href="/favicon.ico" />
|
||||
<script src="/link/script.js" defer></script>
|
||||
</head>
|
||||
<body>
|
||||
|
||||
<div id="popup-warning">
|
||||
<b>Your browser blocked the popup from showing!</b>
|
||||
<br>
|
||||
Please disable your popup blocker and <span id="refresh">try again</span>.
|
||||
</div>
|
||||
|
||||
</body>
|
||||
</html>
|
20
link/script.js
Normal file
20
link/script.js
Normal file
@ -0,0 +1,20 @@
|
||||
// Open timer popup
|
||||
var result = window.open(
|
||||
location.protocol + "//" + location.host + "/popup" + location.search,
|
||||
"PopupTimer" + Date.now(),
|
||||
"width=250,height=100,menubar=no,toolbar=no,location=no,status=no,resizable=no,scrollbars=no"
|
||||
);
|
||||
|
||||
// Show warning if it didn't work
|
||||
if (!result) {
|
||||
|
||||
document.getElementById("popup-warning").style.display = "block";
|
||||
document.getElementById("refresh").onclick = function() {
|
||||
location.reload();
|
||||
}
|
||||
|
||||
} else {
|
||||
window.onfocus = function() {
|
||||
history.back();
|
||||
}
|
||||
}
|
25
link/style.css
Normal file
25
link/style.css
Normal file
@ -0,0 +1,25 @@
|
||||
::selection, ::-moz-selection {
|
||||
color: white;
|
||||
background-color: #F57F17;
|
||||
}
|
||||
#popup-warning {
|
||||
font-family: helvetica, arial, sans-serif;
|
||||
margin: auto;
|
||||
margin-top: 50px;
|
||||
width: 100%;
|
||||
max-width: 400px;
|
||||
display: none;
|
||||
background-color: #FFEE58;
|
||||
color: #F57F17;
|
||||
border-left: 2px solid #F57F17;
|
||||
font-size: 14px;
|
||||
text-align: left;
|
||||
padding: 10px;
|
||||
}
|
||||
#refresh {
|
||||
text-decoration: underline;
|
||||
}
|
||||
#refresh:hover {
|
||||
text-decoration: none;
|
||||
cursor: pointer;
|
||||
}
|
31
popup/index.html
Normal file
31
popup/index.html
Normal file
@ -0,0 +1,31 @@
|
||||
<!DOCTYPE html>
|
||||
<html lang="en">
|
||||
<head>
|
||||
<meta charset="utf-8">
|
||||
<meta http-equiv="X-UA-Compatible" content="IE=edge">
|
||||
<meta name="viewport" content="width=device-width, initial-scale=1">
|
||||
<title>Popup Timer</title>
|
||||
<!-- FontAwesome -->
|
||||
<script src="https://kit.fontawesome.com/b3a602c8a0.js" crossorigin="anonymous"></script>
|
||||
<link rel="stylesheet" href="/popup/style.css">
|
||||
<link rel="shortcut icon" href="/favicon.ico" />
|
||||
<script src="/popup/script.js" defer></script>
|
||||
</head>
|
||||
<!-- This might just trick some really old browser to stay focused all the time -->
|
||||
<body onblur="self.focus();">
|
||||
|
||||
<main>
|
||||
|
||||
<span id="hours">00h</span> <span id="minutes">00m</span> <span id="seconds">00s</span>
|
||||
|
||||
<br>
|
||||
|
||||
<i id="play" class="fas fa-play"></i> <i id="restart" class="fas fa-redo"></i>
|
||||
|
||||
</main>
|
||||
|
||||
<div id="progress-bg" class="progress"></div>
|
||||
<div id="progress-fg" class="progress"></div>
|
||||
|
||||
</body>
|
||||
</html>
|
303
popup/script.js
Normal file
303
popup/script.js
Normal file
@ -0,0 +1,303 @@
|
||||
var params = parseQueryParams();
|
||||
|
||||
// Set window title
|
||||
if (params.name) document.title = params.name + " - Popup Timer";
|
||||
|
||||
var hours, minutes, seconds;
|
||||
var secondsElem = document.getElementById("seconds");
|
||||
var minutesElem = document.getElementById("minutes");
|
||||
var hoursElem = document.getElementById("hours");
|
||||
var playBtn = document.getElementById("play");
|
||||
var progressBar = document.getElementById("progress-fg");
|
||||
var timeout;
|
||||
var timesUpStr = "[ TIME'S UP! ] ";
|
||||
var lastPaused = -1;
|
||||
|
||||
// Init audio
|
||||
var oscillator, audioContext;
|
||||
if (params.beep === "true") {
|
||||
try {
|
||||
audioContext = new (window.AudioContext || window.webkitAudioContext);
|
||||
} catch(e) {}
|
||||
}
|
||||
|
||||
// Autostart
|
||||
if (params.autostart === "true") {
|
||||
|
||||
switch (params.type) {
|
||||
|
||||
case "timer":
|
||||
initTimer();
|
||||
startTimer(1000);
|
||||
break;
|
||||
|
||||
case "stopwatch":
|
||||
initStopwatch();
|
||||
startStopwatch(1000);
|
||||
break;
|
||||
|
||||
default:
|
||||
location.href = "/";
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
// Reset timer/stopwatch
|
||||
document.getElementById("restart").onclick = function() {
|
||||
|
||||
if (timeout) clearTimeout(timeout);
|
||||
|
||||
var paused = playBtn.classList.contains("fa-play");
|
||||
|
||||
switch (params.type) {
|
||||
case "timer":
|
||||
|
||||
// Reset progress bar
|
||||
// TODO
|
||||
progressBar.animationName = "";
|
||||
progressBar.animationName = "progress";
|
||||
|
||||
initTimer();
|
||||
if (!paused) startTimer(1000);
|
||||
|
||||
break;
|
||||
case "stopwatch":
|
||||
|
||||
// Reset displayed time
|
||||
secondsElem.innerText = "00s";
|
||||
secondsElem.classList.remove("highlighted");
|
||||
minutesElem.innerText = "00m";
|
||||
minutesElem.classList.remove("highlighted");
|
||||
hoursElem.innerText = "00h";
|
||||
hoursElem.classList.remove("highlighted");
|
||||
|
||||
initStopwatch();
|
||||
if (!paused) startStopwatch(1000);
|
||||
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
// Pause / Resume
|
||||
playBtn.onclick = function() {
|
||||
|
||||
if (!timeout) return;
|
||||
|
||||
// Pause
|
||||
if (playBtn.classList.contains("fa-pause")) {
|
||||
|
||||
lastPaused = Date.now();
|
||||
if (params.type === "timer") progressBar.style.animationPlayState = "paused";
|
||||
clearTimeout(timeout);
|
||||
|
||||
// Change icon
|
||||
playBtn.classList.remove("fa-pause");
|
||||
playBtn.classList.add("fa-play");
|
||||
|
||||
// Resume
|
||||
} else {
|
||||
|
||||
var startOffset = lastPaused % 1000;
|
||||
|
||||
switch (params.type) {
|
||||
case "timer":
|
||||
if (hours === 0 && minutes == 0 && seconds === 0) return;
|
||||
progressBar.style.animationPlayState = "running";
|
||||
startTimer(startOffset);
|
||||
break;
|
||||
case "stopwatch":
|
||||
startStopwatch(startOffset);
|
||||
break;
|
||||
}
|
||||
|
||||
// Change icon
|
||||
playBtn.classList.remove("fa-play");
|
||||
playBtn.classList.add("fa-pause");
|
||||
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
function initTimer() {
|
||||
|
||||
hours = parseInt(params.h);
|
||||
minutes = parseInt(params.m);
|
||||
seconds = parseInt(params.s);
|
||||
|
||||
if (hours === 0 && minutes === 0 && seconds === 0) return;
|
||||
|
||||
// Only highlight relevant parts
|
||||
if (hours > 0) {
|
||||
hoursElem.classList.add("highlighted");
|
||||
minutesElem.classList.add("highlighted");
|
||||
secondsElem.classList.add("highlighted");
|
||||
} else if (minutes > 0) {
|
||||
minutesElem.classList.add("highlighted");
|
||||
secondsElem.classList.add("highlighted");
|
||||
} else {
|
||||
secondsElem.classList.add("highlighted");
|
||||
}
|
||||
|
||||
// Print initial time
|
||||
hoursElem.innerText = pad(hours) + "h";
|
||||
minutesElem.innerText = pad(minutes) + "m";
|
||||
secondsElem.innerText = pad(seconds) + "s";
|
||||
|
||||
// Animate progress bar
|
||||
var totalSeconds = (hours * 60 * 60) + (minutes * 60) + seconds;
|
||||
progressBar.style.animationDuration = totalSeconds + "s";
|
||||
progressBar.style.animationName = "progress";
|
||||
|
||||
}
|
||||
|
||||
function startTimer(startOffset) {
|
||||
|
||||
playBtn.classList.remove("fa-play");
|
||||
playBtn.classList.add("fa-pause");
|
||||
|
||||
// Wait the starting offset
|
||||
timeout = setTimeout(updateTimer, startOffset);
|
||||
|
||||
document.getElementById("progress-fg").style.animationPlayState = "running";
|
||||
|
||||
}
|
||||
|
||||
function updateTimer() {
|
||||
|
||||
seconds--;
|
||||
if (seconds === 0 && minutes === 0 && hours === 0) secondsElem.classList.remove("highlighted");
|
||||
if (seconds <= -1) {
|
||||
seconds = 59;
|
||||
|
||||
minutes--;
|
||||
if (minutes === 0 && hours === 0) minutesElem.classList.remove("highlighted");
|
||||
if (minutes <= -1) {
|
||||
minutes = 59;
|
||||
|
||||
hours--;
|
||||
if (hours === 0) hoursElem.classList.remove("highlighted");
|
||||
|
||||
hoursElem.innerText = pad(hours) + "h";
|
||||
}
|
||||
minutesElem.innerText = pad(minutes) + "m";
|
||||
}
|
||||
secondsElem.innerText = pad(seconds) + "s";
|
||||
|
||||
if (hours === 0 && minutes === 0 && seconds == 0) timeUp();
|
||||
else timeout = setTimeout(updateTimer, 1000);
|
||||
|
||||
}
|
||||
|
||||
// Makes the numbers blink red etc.
|
||||
function timeUp() {
|
||||
|
||||
var timeUpInterval = setInterval(function() {
|
||||
|
||||
// Blink red
|
||||
[].slice.call(document.querySelectorAll("main > span")).forEach(function(elem) {
|
||||
elem.classList.toggle("red");
|
||||
});
|
||||
//document.querySelector
|
||||
|
||||
// Blink title
|
||||
if (document.title.indexOf(timesUpStr) === -1) document.title = timesUpStr + document.title;
|
||||
else document.title = document.title.substr(timesUpStr.length);
|
||||
|
||||
// Play beep
|
||||
if (params.beep === "true" && audioContext) {
|
||||
try {
|
||||
oscillator = audioContext.createOscillator();
|
||||
oscillator.type = "sine";
|
||||
oscillator.frequency.value = 1000;
|
||||
oscillator.connect(audioContext.destination);
|
||||
oscillator.start();
|
||||
oscillator.stop(audioContext.currentTime + 0.25);
|
||||
} catch(e) {}
|
||||
}
|
||||
|
||||
}, 500);
|
||||
|
||||
// Stop when user clicks
|
||||
document.onclick = function() {
|
||||
|
||||
if (oscillator) oscillator.stop();
|
||||
|
||||
// Reset color
|
||||
[].slice.call(document.querySelectorAll("main > span")).forEach(function(elem) {
|
||||
elem.classList.remove("red");
|
||||
});
|
||||
|
||||
// Remove "TIME UP" from title
|
||||
if (document.title.indexOf(timesUpStr) !== -1) document.title = document.title.substr(timesUpStr.length);
|
||||
|
||||
// Clean up
|
||||
clearInterval(timeUpInterval);
|
||||
document.onclick = null;
|
||||
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
function initStopwatch() {
|
||||
hours = 0;
|
||||
minutes = 0;
|
||||
seconds = 0;
|
||||
}
|
||||
|
||||
function startStopwatch(startOffset) {
|
||||
|
||||
playBtn.classList.remove("fa-play");
|
||||
playBtn.classList.add("fa-pause");
|
||||
|
||||
timeout = setTimeout(updateStopwatch, startOffset);
|
||||
|
||||
}
|
||||
|
||||
function updateStopwatch() {
|
||||
|
||||
// Update seconds
|
||||
seconds++;
|
||||
if (hours === 0 && minutes === 0 && seconds === 1) secondsElem.classList.add("highlighted");
|
||||
if (seconds >= 60) {
|
||||
seconds = 0;
|
||||
|
||||
// Update minutes
|
||||
minutes++;
|
||||
if (hours === 0 && minutes === 1) minutesElem.classList.add("highlighted");
|
||||
if (minutes >= 60) {
|
||||
minutes = 0;
|
||||
|
||||
// Update hours
|
||||
hours++;
|
||||
if (hours === 1) hoursElem.classList.add("highlighted");
|
||||
hoursElem.innerText = pad(hours) + "h";
|
||||
|
||||
}
|
||||
// Minutes
|
||||
minutesElem.innerText = pad(minutes) + "m";
|
||||
|
||||
}
|
||||
// Seconds
|
||||
secondsElem.innerText = pad(seconds) + "s";
|
||||
|
||||
timeout = setTimeout(updateStopwatch, 1000);
|
||||
|
||||
}
|
||||
|
||||
function parseQueryParams() {
|
||||
if (location.search === "" || location.search.indexOf("?") !== 0) return {};
|
||||
var result = {};
|
||||
location.search.substr(1).split("&").forEach(function(str) {
|
||||
var key = str.split("=")[0];
|
||||
var value;
|
||||
if (str.split("=").length > 1) value = str.split("=")[1];
|
||||
else value = null;
|
||||
result[key] = value;
|
||||
});
|
||||
return result;
|
||||
}
|
||||
|
||||
// Adds one leading zero if necessary
|
||||
function pad(num) {
|
||||
return ("00" + num).substr(-2);
|
||||
}
|
63
popup/style.css
Normal file
63
popup/style.css
Normal file
@ -0,0 +1,63 @@
|
||||
@font-face {
|
||||
font-family: "Jetbrains Mono";
|
||||
src: url("/assets/JetBrainsMono-Regular.woff2") format("woff2"),
|
||||
url("/assets/JetBrainsMono-Regular.ttf") format("truetype");
|
||||
}
|
||||
body {
|
||||
margin: 0;
|
||||
padding: 0;
|
||||
overflow: hidden;
|
||||
background-color: #FAFAFA;
|
||||
color: #424242;
|
||||
font-family: "Jetbrains Mono", helvetica, arial, sans-serif;
|
||||
}
|
||||
main {
|
||||
position: absolute;
|
||||
width: 100vw;
|
||||
text-align: center;
|
||||
top: 50%;
|
||||
transform: translate(0, -50%);
|
||||
}
|
||||
main > span {
|
||||
font-size: 15vw; /* Browsers that don't support min() */
|
||||
font-size: min(15vw, 50vh);
|
||||
color: #9E9E9E;
|
||||
}
|
||||
main > span.highlighted {
|
||||
color: #424242;
|
||||
}
|
||||
main > span.red {
|
||||
color: #F4511E;
|
||||
}
|
||||
.progress {
|
||||
position: absolute;
|
||||
bottom: 0;
|
||||
left: 0;
|
||||
height: 5px;
|
||||
width: 0;
|
||||
}
|
||||
#progress-bg {
|
||||
background-color: #9E9E9E;
|
||||
}
|
||||
#progress-fg {
|
||||
background-color: #43A047;
|
||||
animation-timing-function: linear;
|
||||
animation-fill-mode: forwards;
|
||||
}
|
||||
@keyframes progress {
|
||||
from {
|
||||
width: 0;
|
||||
}
|
||||
to {
|
||||
width: 100vw;
|
||||
}
|
||||
}
|
||||
/* FontAwesome */
|
||||
i {
|
||||
font-size: 12px;
|
||||
color: #9E9E9E;
|
||||
}
|
||||
i:hover {
|
||||
cursor: pointer;
|
||||
color: #424242;
|
||||
}
|
213
script.js
Normal file
213
script.js
Normal file
@ -0,0 +1,213 @@
|
||||
// Make checkboxes green on Chrome
|
||||
/*if (navigator.vendor === "Google Inc.") {
|
||||
[].slice.call(document.querySelectorAll("input[type='checkbox']")).forEach(function(checkbox) {
|
||||
checkbox.style.filter = "invert(100%) hue-rotate(70deg) brightness(0.8)";
|
||||
});
|
||||
}*/
|
||||
|
||||
// Only show bookmark button if supported
|
||||
// Check if AddFavorite() exists, addPanel() exists or replaceState() exists which is used in /bookmark/script.js
|
||||
if ((window.external && typeof window.external.AddFavorite === "function") || (window.sidebar && typeof window.sidebar.addPanel === "function") || (history && typeof history.replaceState === "function")) {
|
||||
document.getElementById("bookmark").style.display = "inline-block";
|
||||
}
|
||||
|
||||
// Open new window when clicking create
|
||||
document.getElementById("create").onclick = function(event) {
|
||||
|
||||
var popup = window.open(
|
||||
createLink("popup"),
|
||||
"PopupTimer" + Date.now(),
|
||||
"popup,width=250,height=100,menubar=no,toolbar=no,location=no,status=no,resizable=no,scrollbars=no"
|
||||
);
|
||||
|
||||
// Probably not going to work on any modern browser but worth a try
|
||||
popup.onblur = function() {
|
||||
popup.focus();
|
||||
}
|
||||
|
||||
};
|
||||
|
||||
// When clicking Create bookmark
|
||||
document.getElementById("bookmark").onclick = function(event) {
|
||||
if (event.target.classList.contains("disabled")) return;
|
||||
|
||||
// Some older browsers include built-in functions for adding a bookmark, attempt to use this if user didn't perform shift click
|
||||
if (!event.shiftKey) {
|
||||
|
||||
var link = createLink("link");
|
||||
var title = document.getElementById("name").value;
|
||||
|
||||
// Internet explorer
|
||||
if (window.external && typeof window.external.AddFavorite === "function") {
|
||||
|
||||
window.external.AddFavorite(link, title);
|
||||
showBookmarkAdded();
|
||||
return;
|
||||
|
||||
// Old Firefox, SeaMonkey
|
||||
} else if (window.sidebar && typeof window.sidebar.addPanel === "function") {
|
||||
|
||||
window.sidebar.addPanel(title, link, "");
|
||||
showBookmarkAdded();
|
||||
return;
|
||||
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
// Show bookmark instructions in new tab
|
||||
window.open(
|
||||
createLink("bookmark"),
|
||||
"_blank",
|
||||
""
|
||||
);
|
||||
|
||||
}
|
||||
|
||||
// Show a green "Bookmark added" message for a second
|
||||
function showBookmarkAdded() {
|
||||
|
||||
var bookmarkBtn = document.getElementById("bookmark");
|
||||
bookmarkBtn.innerHTML = "<i class='fas fa-check'></i> <b>Bookmark added</b>";
|
||||
bookmarkBtn.style.color = "#66BB6A";
|
||||
bookmarkBtn.classList.add("disabled");
|
||||
|
||||
setTimeout(function() {
|
||||
|
||||
bookmarkBtn.innerText = "Create bookmark";
|
||||
bookmarkBtn.style.color = "inherit";
|
||||
bookmarkBtn.classList.remove("disabled");
|
||||
|
||||
}, 1000);
|
||||
|
||||
}
|
||||
|
||||
// When clicking Timer/Stopwatch
|
||||
[].slice.call(document.querySelectorAll("#popup-type td")).forEach(function(elem) {
|
||||
elem.onclick = function(event) {
|
||||
|
||||
var elem = event.target;
|
||||
if (elem.classList.contains("selected")) return;
|
||||
elem.classList.add("selected");
|
||||
|
||||
switch (elem.id) {
|
||||
case "timer":
|
||||
document.getElementById("stopwatch").classList.remove("selected");
|
||||
document.getElementById("input-timer").style.display = "block";
|
||||
document.getElementById("name").value = "Timer";
|
||||
break;
|
||||
case "stopwatch":
|
||||
document.getElementById("timer").classList.remove("selected");
|
||||
document.getElementById("input-timer").style.display = "none";
|
||||
document.getElementById("name").value = "Stopwatch";
|
||||
break;
|
||||
}
|
||||
|
||||
document.getElementById("input-common").style.display = "block";
|
||||
|
||||
var linkElem = document.getElementById("link");
|
||||
linkElem.innerText = createLink("link");
|
||||
linkElem.style.display = "inline-block";
|
||||
|
||||
}
|
||||
});
|
||||
|
||||
// Disable buttons on invalid input
|
||||
[].slice.call(document.getElementsByTagName("input")).forEach(function(input) {
|
||||
input.oninput = function(event) {
|
||||
|
||||
var createBtn = document.getElementById("create");
|
||||
var bookmarkBtn = document.getElementById("bookmark");
|
||||
var isInvalid = document.querySelectorAll("input:invalid").length > 0;
|
||||
|
||||
if (isInvalid) {
|
||||
createBtn.disabled = true;
|
||||
bookmarkBtn.classList.add("disabled");
|
||||
} else {
|
||||
createBtn.disabled = false;
|
||||
bookmarkBtn.classList.remove("disabled");
|
||||
document.getElementById("link").innerText = createLink("link");
|
||||
}
|
||||
|
||||
}
|
||||
});
|
||||
|
||||
// Copy link to clipboard when clicked
|
||||
document.getElementById("link").onclick = function() {
|
||||
|
||||
var link = createLink("link");
|
||||
var linkElem = document.getElementById("link");
|
||||
|
||||
// Catch is called both on promise rejection (insufficient permissons) and if the function doesn't exist
|
||||
try {
|
||||
|
||||
navigator.clipboard.writeText(link);
|
||||
linkShowMessage("Copied to clipboard!", "#66BB6A");
|
||||
|
||||
} catch(e) {
|
||||
try {
|
||||
|
||||
// Alternatively, just select the text and copy it
|
||||
var range = document.createRange();
|
||||
range.setStart(linkElem, 0);
|
||||
range.setEnd(linkElem, 1);
|
||||
|
||||
var selection = window.getSelection();
|
||||
selection.removeAllRanges();
|
||||
selection.addRange(range);
|
||||
|
||||
document.execCommand("copy");
|
||||
|
||||
linkShowMessage("Copied to clipboard!", "#66BB6A");
|
||||
|
||||
} catch(e) {
|
||||
// Browser doesn't support copying
|
||||
console.error(e);
|
||||
linkShowMessage("Couldn't copy link :(", "#EF5350");
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
// Displays a message where the link is for one second
|
||||
function linkShowMessage(message, color) {
|
||||
|
||||
var linkElem = document.getElementById("link");
|
||||
|
||||
linkElem.style.backgroundColor = color;
|
||||
linkElem.style.width = linkElem.offsetWidth + "px";
|
||||
linkElem.style.color = "white";
|
||||
linkElem.style.fontFamily = "helvetica, arial, sans-serif";
|
||||
linkElem.style.fontWeight = "bold";
|
||||
linkElem.innerText = message;
|
||||
|
||||
setTimeout(function() {
|
||||
linkElem.style.backgroundColor = "#E0E0E0";
|
||||
linkElem.style.color = "black";
|
||||
linkElem.style.fontFamily = "'Jetbrains Mono', monospace";
|
||||
linkElem.style.width = "auto";
|
||||
linkElem.style.fontWeight = "normal";
|
||||
linkElem.innerText = createLink("link");
|
||||
}, 1000);
|
||||
|
||||
}
|
||||
|
||||
function createLink(type) {
|
||||
|
||||
// Get user input
|
||||
var input = {};
|
||||
["hours", "minutes", "seconds", "name"].forEach(function(name) {
|
||||
input[name] = document.getElementById(name).value;
|
||||
});
|
||||
["autostart", "beep"].forEach(function(name) {
|
||||
input[name] = !!document.getElementById(name).checked;
|
||||
});
|
||||
if (document.getElementById("timer").classList.contains("selected")) input.type = "timer";
|
||||
else input.type = "stopwatch";
|
||||
|
||||
// Create URL
|
||||
var url = location.protocol + "//" + location.host + "/" + type + "?type=" + input.type + "&name=" + encodeURIComponent(input.name) + "&autostart=" + input.autostart;
|
||||
if (input.type === "timer") url += "&h=" + input.hours + "&m=" + input.minutes + "&s=" + input.seconds + "&beep=" + input.beep;
|
||||
return url;
|
||||
|
||||
}
|
125
style.css
Normal file
125
style.css
Normal file
@ -0,0 +1,125 @@
|
||||
@font-face {
|
||||
font-family: "Jetbrains Mono";
|
||||
src: url("/assets/JetBrainsMono-Regular.woff2") format("woff2"),
|
||||
url("/assets/JetBrainsMono-Regular.ttf") format("truetype");
|
||||
}
|
||||
body {
|
||||
margin: 2em;
|
||||
background-color: #FAFAFA;
|
||||
color: #424242;
|
||||
text-align: center;
|
||||
}
|
||||
::selection, ::-moz-selection {
|
||||
background-color: #43A047;
|
||||
color: white;
|
||||
}
|
||||
body, input, button {
|
||||
font-family: helvetica, arial, sans-serif;
|
||||
font-size: 18px;
|
||||
}
|
||||
main {
|
||||
display: block; /* IE */
|
||||
margin: auto;
|
||||
margin-top: 50px;
|
||||
width: 100%;
|
||||
max-width: 400px;
|
||||
}
|
||||
#popup-blocked::warning, #popup-warning *::selection, #popup-warning::-moz-selection, #popup-warning *::-moz-selection {
|
||||
background-color: #F57F17;
|
||||
}
|
||||
#popup-type {
|
||||
margin: auto;
|
||||
}
|
||||
#popup-type td {
|
||||
width: 50vw;
|
||||
color: #9E9E9E;
|
||||
border-bottom: 1px solid #9E9E9E;
|
||||
padding-top: 1px;
|
||||
padding-bottom: 5px;
|
||||
user-select: none;
|
||||
}
|
||||
#popup-type td:not(.selected):hover {
|
||||
padding-top: 0;
|
||||
color: #424242;
|
||||
border-bottom: 2px solid #424242;
|
||||
cursor: pointer;
|
||||
}
|
||||
#popup-type td.selected {
|
||||
padding-top: 0;
|
||||
color: #43A047;
|
||||
border-bottom: 2px solid #43A047;
|
||||
}
|
||||
#input-common, #input-timer {
|
||||
display: none;
|
||||
}
|
||||
input {
|
||||
background-color: white;
|
||||
border: none;
|
||||
outline: none;
|
||||
border-bottom: 1px solid #9E9E9E;
|
||||
transition-duration: 0.2s;
|
||||
}
|
||||
input:focus {
|
||||
border-bottom: 1px solid #43A047;
|
||||
}
|
||||
input:invalid {
|
||||
border-bottom: 1px solid #E53935;
|
||||
background-color: #FFCDD2;
|
||||
outline: none;
|
||||
box-shadow: none;
|
||||
}
|
||||
input[type=checkbox] {
|
||||
filter: hue-rotate(290deg);
|
||||
}
|
||||
#time-input-container {
|
||||
display: flex;
|
||||
}
|
||||
.time-input {
|
||||
width: 33%;
|
||||
text-align: right;
|
||||
flex: 1;
|
||||
min-width: 0; /* SeaMonkey */
|
||||
}
|
||||
#create {
|
||||
width: 100%;
|
||||
background-color: #43A047;
|
||||
color: white;
|
||||
padding: 10px;
|
||||
border: none;
|
||||
outline: none;
|
||||
transition-duration: 0.2s;
|
||||
cursor: default;
|
||||
}
|
||||
#create:not(:disabled):hover {
|
||||
cursor: pointer;
|
||||
box-shadow: 2px 2px 2px #BDBDBD;
|
||||
}
|
||||
#create:active {
|
||||
background-color: #2E7D32;
|
||||
}
|
||||
#create:disabled {
|
||||
background-color: #9E9E9E;
|
||||
}
|
||||
#bookmark {
|
||||
font-size: 15px;
|
||||
margin-top: 10px;
|
||||
display: none;
|
||||
color: inherit;
|
||||
text-decoration: inherit;
|
||||
cursor: default;
|
||||
border: none;
|
||||
outline: none;
|
||||
}
|
||||
#bookmark:not(.disabled):hover {
|
||||
text-decoration: underline;
|
||||
cursor: pointer;
|
||||
}
|
||||
#link {
|
||||
display: none;
|
||||
background-color: #E0E0E0;
|
||||
padding: 3px;
|
||||
font-family: "Jetbrains Mono", monospace;
|
||||
font-size: 12px;
|
||||
cursor: pointer;
|
||||
word-break: break-all;
|
||||
}
|
Loading…
Reference in New Issue
Block a user