From ff5f60f765f1c1e3af0558981b64f56eb24a4348 Mon Sep 17 00:00:00 2001 From: Reimar Date: Wed, 6 Aug 2025 19:21:14 +0200 Subject: [PATCH] Add picture-in-picture mode --- index.html | 25 +++++++++++++++++++++++-- pip.js | 35 +++++++++++++++++++++++++++++++++++ script.js | 24 +++++++++++++++++------- style.css | 23 +++++++++++++++++++++++ 4 files changed, 98 insertions(+), 9 deletions(-) create mode 100644 pip.js diff --git a/index.html b/index.html index 48ced67..8746a0d 100644 --- a/index.html +++ b/index.html @@ -11,6 +11,7 @@ + @@ -70,8 +71,28 @@ -

- +
+ Advanced + +
+ +

+ Pasting this link in your browser will make the timer/stopwatch immediately pop up. +

+
+ +
+ + +
+ +

+ If enabled, the window will always stay on top, but requires that this tab stay open. +

+
+
diff --git a/pip.js b/pip.js new file mode 100644 index 0000000..6de7b71 --- /dev/null +++ b/pip.js @@ -0,0 +1,35 @@ +function pipSupported() { + return window.documentPictureInPicture && document.pictureInPictureEnabled; +} + +function pipEnabled() { + return pipSupported() && localStorage.getItem("pip-enabled") != 0; +} + +function setPipEnabled(enabled) { + localStorage.setItem("pip-enabled", +enabled); +} + +function openPipWindow(link, w, h) { + return new Promise(function(resolve) { + window.documentPictureInPicture.requestWindow({ width: w, height: h }).then(function(win) { + var iframe = document.createElement("iframe"); + iframe.src = link; + iframe.style.width = w + "px"; + iframe.style.height = h + "px"; + iframe.style.border = "none"; + + win.document.body.style.margin = "0"; + win.document.body.style.overflow = "hidden"; + + win.document.body.appendChild(iframe); + + win.onpagehide = resolve; + win.onresize = function() { + iframe.style.width = win.innerWidth + "px"; + iframe.style.height = win.innerHeight + "px"; + } + }); + }); +} + diff --git a/script.js b/script.js index 9df6d54..d5bcfe6 100644 --- a/script.js +++ b/script.js @@ -1,12 +1,20 @@ -// 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)"; - }); -}*/ +// Picture-in-picture +document.getElementById("pip-enabled").checked = pipEnabled(); +document.getElementById("pip-enabled").oninput = function(event) { + setPipEnabled(event.target.checked); +} // Open new window when clicking create document.getElementById("create").onclick = function(event) { + if (pipEnabled()) { + event.target.disabled = true; + + openPipWindow(createLink("popup"), 250, 100).then(function() { + event.target.disabled = false; + }); + + return; + } var popup = window.open( createLink("popup"), @@ -98,7 +106,9 @@ function showBookmarkAdded() { } document.getElementById("input-common").style.display = "block"; + document.getElementById("advanced").style.display = "block"; document.getElementById("welcome").style.display = "none"; + document.getElementById("pip").style.display = pipSupported() ? "block" : "none"; var linkElem = document.getElementById("link"); linkElem.innerText = createLink("link"); @@ -110,7 +120,7 @@ function showBookmarkAdded() { }); // Disable buttons on invalid input -[].slice.call(document.getElementsByTagName("input")).forEach(function(input) { +[].slice.call(document.getElementsByTagName("#input-timer input, #input-common input")).forEach(function(input) { input.oninput = function(event) { var createBtn = document.getElementById("create"); diff --git a/style.css b/style.css index 0a42ba9..c99e677 100644 --- a/style.css +++ b/style.css @@ -139,4 +139,27 @@ input[type=checkbox] { margin-bottom: 14px; margin-top: 0; } +#pip { + display: none; + font-size: 14px; + margin-top: 60px; +} +#advanced { + font-size: 14px; + display: none; + margin-top: 40px; +} +#advanced summary { + cursor: pointer; + color: #757575; + transition: color 200ms; +} +#advanced summary:hover { + color: black; +} +.desc { + margin: 8px 0; + color: #757575; + font-size: 12px; +}