nycki.net/static/papermod/index.html
nycki eec62d6724
All checks were successful
/ build (push) Successful in 41s
link back to blogette
2025-11-15 12:15:06 -08:00

385 lines
No EOL
14 KiB
HTML

<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="utf-8">
<title>Nycki's Papermod</title>
<style>
html {
background-color: #929591; /*xkcd-grey*/
font-family: Arial, Helvetica, sans-serif;
}
body {
margin: 0;
/* break after fourth page on large monitors */
max-width: calc((74mm + 8mm) * 4);
}
#settings {
width: calc(100% - 12mm);
margin: 4mm;
padding: 4mm;
background-color: white;
}
#settings * {
margin: 2mm 0;
}
#settings :first-child {
margin: 0;
}
#document {
display: flex;
flex-wrap: wrap;
}
.page {
background-color: white;
box-sizing: border-box;
width: 74mm;
height: 105mm;
margin: 4mm;
padding: 4mm;
position: relative;
text-align: center;
display: flex;
flex-direction: column;
}
.page :first-child {
margin-top: 0;
}
@media print {
html {
background-color: white;
}
#settings {
display: none;
}
.page {
max-height: 100%;
margin: 0;
break-inside: avoid;
break-after: page;
}
}
@page {
size: 74mm 105mm;
}
/* page 1 */
.week {
font-weight: bold;
font-size: 14mm;
}
.date {
font-size: 8mm;
}
.return-addr {
font-weight: bold;
margin: 8mm;
}
.footer {
font-style: italic;
font-size: smaller;
position: absolute;
left: 0;
bottom: 4mm;
width: 100%;
}
/* page 2-3 */
.month .landscape {
width: calc(105mm - 8mm);
height: calc(74mm - 8mm);
transform-origin: 0mm 0mm;
transform: rotate(-90deg) translateX(-100%);
}
.month table {
height: 100%;
width: 100%;
table-layout: fixed;
border-collapse: collapse;
}
.month thead {
height: 0.01%;
}
.month td {
border: thin solid black;
}
.month tbody td {
font-size: small;
text-align: left;
vertical-align: top;
}
/* page 4-5 */
.week table {
height: 100%;
width: 100%;
border: thin dashed black;
border-collapse: collapse;
}
.week tr {
border: thin solid black;
}
.week tr:nth-child(odd) td {
text-align: left;
padding-left: 2mm;
font-size: 4mm;
height: 4mm;
}
/* page 6-7 */
.page:has(img) {
padding: 0;
}
/* page 8 */
.sudoku table:has(table) {
width: fit-content;
margin: auto;
padding-top: 12mm;
border-collapse: separate;
}
.sudoku table table {
border-collapse: collapse;
}
.sudoku table table td {
width: 5mm;
height: 5mm;
border: thin solid black;
}
</style>
</head>
<body>
<div id="settings">
<h1>PaperMod</h1>
<h2>the analog organizer</h2>
<p>I <a href="/blogette/1/#2025-11-14-bullent-journal">used to use</a> this thing called PocketMod to lay out my paper organizer every week. It's <a href="https://pocketmod.com/v2/">defunct</a> unless you can get Silverlight running somehow, so I made my own version with HTML and CSS.</p>
<p>Just fill out the form, click "generate", and use your browser's "print" function to get an 8 page document. To convert it into a booklet, I recommend using <a href="https://nashhigh.itch.io/zinearranger">The Zine Arranger</a> by Nash High or <a href="https://pocketverter.pages.dev/">Pocketverter</a> by <a href="https://github.com/Laur401/pocketverter">Laur401</a>.</p>
<div>
<label for="date">start date:</label>
<input id="settings-date" type="date" name="date">
</div>
<div>
<label for="settings-has-week">show week number</label>
<input id="settings-has-week" type="checkbox" name="settings-has-week" checked>
</div>
<div>
<label for="settings-start-monday">always start on monday</label>
<input id="settings-start-monday" type="checkbox" name="settings-start-monday" checked>
</div>
<div>
<label for="name">name:</label>
<input id="settings-name" type="text" name="name">
</div>
<div>
<label for="contact">contact (email, phone, etc):</label>
<input id="settings-contact" type="text" name="contact">
</div>
<button id="settings-update">generate</button>
<button id="settings-clear">clear all</button>
</div>
<div id="document">
<div class="page">
<div class="week" contenteditable> </div>
<div class="date" contenteditable> </div>
<div class="return-addr" contenteditable>
<p id="user-name"> </p>
<p id="user-contact"> </p>
</div>
<div class="footer">nycki.net/papermod</div>
</div>
<div class="page month">
<div class="landscape">
<table contenteditable>
<thead><td>mon</td><td>tue</td><td>wed</td><td>thu</td><td>fri</td><td>sat</td><td>sun</td></thead>
<tr><td></td><td></td><td></td><td></td><td></td><td></td><td></td></tr>
<tr><td></td><td></td><td></td><td></td><td></td><td></td><td></td></tr>
<tr><td></td><td></td><td></td><td></td><td></td><td></td><td></td></tr>
<tr><td></td><td></td><td></td><td></td><td></td><td></td><td></td></tr>
</table>
</div>
</div>
<div class="page month">
<div class="landscape">
<table contenteditable>
<thead><td>mon</td><td>tue</td><td>wed</td><td>thu</td><td>fri</td><td>sat</td><td>sun</td></thead>
<tr><td></td><td></td><td></td><td></td><td></td><td></td><td></td></tr>
<tr><td></td><td></td><td></td><td></td><td></td><td></td><td></td></tr>
<tr><td></td><td></td><td></td><td></td><td></td><td></td><td></td></tr>
<tr><td></td><td></td><td></td><td></td><td></td><td></td><td></td></tr>
</table>
</div>
</div>
<div class="page week">
<table>
<tr><td>monday</td></tr>
<tr><td></td></tr>
<tr><td>tuesday</td></tr>
<tr><td></td></tr>
<tr><td>wednesday</td></tr>
<tr><td></td></tr>
<tr><td>thursday</td></tr>
<tr><td></td></tr>
</table>
</div>
<div class="page week">
<table>
<tr><td>friday</td></tr>
<tr><td></td></tr>
<tr><td>saturday</td></tr>
<tr><td></td></tr>
<tr><td>sunday</td></tr>
<tr><td></td></tr>
</table>
</div>
<div class="page">
<img src="dots.svg">
</div>
<div class="page">
<img src="dots.svg">
</div>
<div class="page">
<div class="sudoku">
<table>
<tr>
<td>
<table>
<tr><td></td><td></td><td></td></tr>
<tr><td></td><td></td><td></td></tr>
<tr><td></td><td></td><td></td></tr>
</table>
</td>
<td>
<table>
<tr><td></td><td></td><td></td></tr>
<tr><td></td><td></td><td></td></tr>
<tr><td></td><td></td><td></td></tr>
</table>
</td>
<td>
<table>
<tr><td></td><td></td><td></td></tr>
<tr><td></td><td></td><td></td></tr>
<tr><td></td><td></td><td></td></tr>
</table>
</td>
</tr>
<tr>
<td>
<table>
<tr><td></td><td></td><td></td></tr>
<tr><td></td><td></td><td></td></tr>
<tr><td></td><td></td><td></td></tr>
</table>
</td>
<td>
<table>
<tr><td></td><td></td><td></td></tr>
<tr><td></td><td></td><td></td></tr>
<tr><td></td><td></td><td></td></tr>
</table>
</td>
<td>
<table>
<tr><td></td><td></td><td></td></tr>
<tr><td></td><td></td><td></td></tr>
<tr><td></td><td></td><td></td></tr>
</table>
</td>
</tr>
<tr>
<td>
<table>
<tr><td></td><td></td><td></td></tr>
<tr><td></td><td></td><td></td></tr>
<tr><td></td><td></td><td></td></tr>
</table>
</td>
<td>
<table>
<tr><td></td><td></td><td></td></tr>
<tr><td></td><td></td><td></td></tr>
<tr><td></td><td></td><td></td></tr>
</table>
</td>
<td>
<table>
<tr><td></td><td></td><td></td></tr>
<tr><td></td><td></td><td></td></tr>
<tr><td></td><td></td><td></td></tr>
</table>
</td>
</tr>
</table>
</div>
</div>
</div>
<script>
const elDate = document.querySelector('#settings-date');
const weekday = [
'sunday', 'monday', 'tuesday', 'wednesday', 'thursday', 'friday', 'saturday',
];
function getWeek(date) {
const januaryFirst = new Date(date.getFullYear(), 0, 1);
return Math.ceil((((date - januaryFirst) / 86_400_000) + januaryFirst.getDay()+1) / 7);
}
function update() {
document.querySelector('#user-name').textContent = document.querySelector('#settings-name').value;
document.querySelector('#user-contact').textContent = document.querySelector('#settings-contact').value;
let startDate = new Date(elDate.value);
if (isNaN(startDate)) startDate = new Date();
if (document.querySelector('#settings-start-monday').checked) {
startDate.setDate(startDate.getDate() - startDate.getDay() + 1);
}
let d;
startDate.setHours(12); // I don't care about the time zone
document.querySelector('.week').textContent = startDate.getFullYear();
if (document.querySelector('#settings-has-week').checked) {
document.querySelector('.week').textContent += `W${getWeek(startDate)}`;
}
const mm1 = startDate.getMonth() + 1;
const dd1 = startDate.getDate();
d = new Date(startDate);
d.setDate(d.getDate() + 6);
const mm2 = d.getMonth() + 1;
const dd2 = d.getDate();
document.querySelector('.date').textContent = `${mm1}-${dd1}${mm2}-${dd2}`
/* set up month */
const startDay = startDate.getDay();
for (const [i, el] of document.querySelectorAll('.month thead td').entries()) {
el.textContent = weekday[(startDay + i) % 7].slice(0,3);
}
d = new Date(startDate);
for (const el of document.querySelectorAll('.month tbody td')) {
el.textContent = d.getDate();
d.setDate(d.getDate() + 1);
}
/* set up week */
d = new Date(startDate);
for (const [i, el] of document.querySelectorAll('.week tr:nth-child(odd) td').entries()) {
el.textContent = `${d.getMonth()+1}-${d.getDate()} ${weekday[d.getDay()]}`
d.setDate(d.getDate() + 1);
}
}
function clear() {
document.querySelector('.week').textContent = '';
document.querySelector('.date').textContent = '';
document.querySelectorAll('.month td').forEach(el => el.innerHTML = '&nbsp;');
document.querySelectorAll('.week td').forEach(el => el.innerHTML = '&nbsp;');
}
document.querySelector('#settings-update').onclick = update;
document.querySelector('#settings-clear').onclick = clear;
update();
</script>
</body>
</html>