Files
Crochet/script.js
T
2025-11-15 18:45:58 +01:00

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();
}
}
});