167 lines
5.2 KiB
JavaScript
167 lines
5.2 KiB
JavaScript
const MAX_HISTORY_LENGTH = 32;
|
|
const PIP_WINDOW_SIZE = { width: 280, height: 140 };
|
|
|
|
class Counter {
|
|
constructor(elementId, storageKey) {
|
|
this.el = document.getElementById(elementId);
|
|
this.key = storageKey;
|
|
this.count = parseInt(localStorage.getItem(this.key)) || 0;
|
|
this.history = [];
|
|
this.render();
|
|
}
|
|
|
|
render = () => {
|
|
this.el.textContent = this.count;
|
|
}
|
|
|
|
set = (val) => {
|
|
this.history.push(this.count);
|
|
if (this.history.length > MAX_HISTORY_LENGTH) this.history.shift();
|
|
this.count = val;
|
|
localStorage.setItem(this.key, this.count);
|
|
this.render();
|
|
}
|
|
|
|
increase = () => {
|
|
this.set(this.count + 1);
|
|
}
|
|
|
|
undo = () => {
|
|
if (this.history.length > 0) {
|
|
this.count = this.history.pop();
|
|
localStorage.setItem(this.key, this.count);
|
|
this.render();
|
|
}
|
|
}
|
|
}
|
|
|
|
const stitches = new Counter("stitches-counter", "stitches");
|
|
const rows = new Counter("rows-counter", "rows");
|
|
|
|
const inputAuto = document.getElementById("input-autoincrease");
|
|
const inputStitchMax = document.getElementById("input-stitches");
|
|
|
|
inputAuto.checked = localStorage.getItem("input_autoincrease") === "true";
|
|
inputStitchMax.value = localStorage.getItem("input_stitches") || "10";
|
|
|
|
inputAuto.addEventListener("change", () => {
|
|
localStorage.setItem("input_autoincrease", inputAuto.checked);
|
|
});
|
|
|
|
inputStitchMax.addEventListener("change", () => {
|
|
localStorage.setItem("input_stitches", inputStitchMax.value);
|
|
});
|
|
|
|
document.getElementById("button-stitch").addEventListener("click", () => {
|
|
const max = parseInt(inputStitchMax.value);
|
|
if (inputAuto.checked && stitches.count + 1 >= max) {
|
|
rows.increase();
|
|
stitches.set(0);
|
|
} else {
|
|
stitches.increase();
|
|
}
|
|
});
|
|
|
|
document.getElementById("button-row").addEventListener("click", () => {
|
|
rows.increase();
|
|
stitches.set(0);
|
|
});
|
|
|
|
document.getElementById("button-undo").addEventListener("click", () => {
|
|
stitches.undo();
|
|
rows.undo();
|
|
});
|
|
|
|
document.getElementById("button-reset").addEventListener("click", () => {
|
|
stitches.set(0);
|
|
rows.set(0);
|
|
});
|
|
|
|
class PipManager {
|
|
constructor(pipElement, pipContainer, pipButton) {
|
|
this.el = pipElement;
|
|
this.container = pipContainer;
|
|
this.button = pipButton;
|
|
this.pipWindow = null;
|
|
|
|
this.button.addEventListener("click", this.start);
|
|
}
|
|
|
|
start = async () => {
|
|
if (this.pipWindow && !this.pipWindow.closed) return;
|
|
|
|
this.pipWindow = await documentPictureInPicture.requestWindow(PIP_WINDOW_SIZE);
|
|
|
|
for (const styleSheet of document.styleSheets) {
|
|
try {
|
|
const style = document.createElement("style");
|
|
const rules = Array.from(styleSheet.cssRules).map(r => r.cssText).join("");
|
|
style.textContent = rules;
|
|
this.pipWindow.document.head.appendChild(style);
|
|
} catch {
|
|
if (styleSheet.href) {
|
|
const link = document.createElement("link");
|
|
link.rel = "stylesheet";
|
|
link.href = styleSheet.href;
|
|
this.pipWindow.document.head.appendChild(link);
|
|
}
|
|
}
|
|
}
|
|
|
|
this.pipWindow.document.body.appendChild(this.el);
|
|
|
|
// Add keydown listener inside PiP window
|
|
this.pipWindow.addEventListener("keydown", (event) => {
|
|
// Ignore if focused on input or textarea in PiP window
|
|
const active = this.pipWindow.document.activeElement;
|
|
if (active && (active.tagName === "INPUT" || active.tagName === "TEXTAREA")) return;
|
|
|
|
if (event.code === "Space") {
|
|
event.preventDefault();
|
|
const max = parseInt(inputStitchMax.value);
|
|
if (inputAuto.checked && stitches.count + 1 >= max) {
|
|
rows.increase();
|
|
stitches.set(0);
|
|
} else {
|
|
stitches.increase();
|
|
}
|
|
}
|
|
});
|
|
|
|
this.pipWindow.addEventListener("pagehide", () => this.stop());
|
|
}
|
|
|
|
stop = () => {
|
|
this.container.appendChild(this.el);
|
|
this.pipWindow = null;
|
|
}
|
|
}
|
|
|
|
new PipManager(
|
|
document.getElementById("div-pip-element"),
|
|
document.getElementById("div-pip-container"),
|
|
document.getElementById("button-start-pip")
|
|
);
|
|
|
|
const notesField = document.getElementById("notes");
|
|
notesField.value = localStorage.getItem("notes") || "";
|
|
notesField.addEventListener("input", () => {
|
|
localStorage.setItem("notes", notesField.value);
|
|
});
|
|
|
|
window.addEventListener("keydown", (event) => {
|
|
// Ignore if focused on input or textarea, so typing space doesn't increment stitches accidentally
|
|
const active = document.activeElement;
|
|
if (active && (active.tagName === "INPUT" || active.tagName === "TEXTAREA")) return;
|
|
|
|
if (event.code === "Space") {
|
|
event.preventDefault(); // prevent page scroll on space key
|
|
const max = parseInt(inputStitchMax.value);
|
|
if (inputAuto.checked && stitches.count + 1 >= max) {
|
|
rows.increase();
|
|
stitches.set(0);
|
|
} else {
|
|
stitches.increase();
|
|
}
|
|
}
|
|
}); |