Import tajmcal

This commit is contained in:
Anders Englöf Ytterström 2026-07-21 20:09:22 +02:00
parent d4923adf6e
commit 542005e7af
3 changed files with 805 additions and 0 deletions

532
2026.tajmcal.css Normal file
View file

@ -0,0 +1,532 @@
body {
font-size: small;
font-family: sans-serif;
margin: 0;
}
article {
background: red;
color: white;
padding: 0.5em;
border: 2px solid transparent;
}
article:not(.break, .holiday):hover {
background-color: #f44;
}
article:focus {
border-color: #300;
}
.break {
background-color: #f0f;
background-image: repeating-linear-gradient(
-45deg,
transparent,
transparent 10px,
rgba(255, 255, 255, 0.5) 10px,
rgba(255, 255, 255, 0.5) 20px
);
color: #fff;
}
.holiday {
background-color: #0f0;
background-image: repeating-linear-gradient(
-45deg,
transparent,
transparent 10px,
rgba(255, 255, 255, 0.5) 10px,
rgba(255, 255, 255, 0.5) 20px
);
color: #080;
}
header {
background-color: #d70000;
color: #fff;
padding: 0 1em;
display: flex;
gap: 1em;
b {
text-transform: uppercase;
padding: 5px 0;
font-size: 1.4em;
}
}
nav {
flex: 1;
align-self: flex-end;
display: flex;
gap: 0.33em;
justify-content: flex-end;
a,
strong {
padding: 0.5em;
}
a {
background-color: #a00;
color: #fff;
}
strong {
background-color: #fff;
color: #000;
font-weight: normal;
}
}
[data-draggable],
[data-resizeable] {
position: relative;
}
[data-draggable]::before,
[data-resizeable]::after {
position: absolute;
padding: 0.1em 0.25em;
}
[data-draggable]::before {
content: "↕";
top: 0;
right: 0;
cursor: move;
}
[data-resizeable]::after {
content: "⥙";
bottom: 0;
left: 0;
right: 0;
text-align: center;
cursor: s-resize;
}
.calendar {
border: 1px solid #aaa;
background: #eee;
display: grid;
gap: 2px;
grid-template-columns: auto repeat(5, 1fr);
grid-template-rows: auto repeat(52, 25px);
.nt {
background-color: #fff;
}
.wh {
display: grid;
grid-template-columns: subgrid;
grid-template-rows: subgrid;
grid-column: span 5 / span 5;
grid-column-start: 2;
grid-row: span 1 / span 1;
grid-row-start: 1;
text-align: center;
> b {
font-weight: normal;
font-size: smaller;
padding: 0.25em;
background-color: #000;
color: #fff;
}
}
.ts {
display: grid;
grid-template-columns: subgrid;
grid-template-rows: subgrid;
grid-column: span 1 / span 1;
grid-column-start: 1;
grid-row: span 52 / span 52;
grid-row-start: 2;
text-align: right;
> b {
font-weight: normal;
background-color: #fef9c2;
font-size: smaller;
border-bottom: 2px solid #aaa;
padding: 0.25em;
grid-row: span 4 / span 4;
}
}
.log {
display: grid;
grid-template-columns: subgrid;
grid-template-rows: subgrid;
grid-column: span 5 / span 5;
grid-column-start: 2;
grid-row: span 52 / span 52;
grid-column-start: 2;
}
}
i {
background-color: #fff;
&.pressed {
background-color: #ff0;
}
}
.panel {
background: #333;
color: #fff;
position: fixed;
top: 0;
bottom: 0;
width: 0;
overflow: hidden;
&.left {
border-left: 5px solid #000;
left: 0;
}
}
/*
Day
*/
[data-day="mon"] {
grid-column: 1;
}
[data-day="tue"] {
grid-column: 2;
}
[data-day="wed"] {
grid-column: 3;
}
[data-day="thu"] {
grid-column: 4;
}
[data-day="fri"] {
grid-column: 5;
}
/*
Timestamps
*/
[data-start="0600"] {
grid-row-start: 1;
}
[data-start="0615"] {
grid-row-start: 2;
}
[data-start="0630"] {
grid-row-start: 3;
}
[data-start="0645"] {
grid-row-start: 4;
}
[data-start="0700"] {
grid-row-start: 5;
}
[data-start="0715"] {
grid-row-start: 6;
}
[data-start="0730"] {
grid-row-start: 7;
}
[data-start="0745"] {
grid-row-start: 8;
}
[data-start="0800"] {
grid-row-start: 9;
}
[data-start="0815"] {
grid-row-start: 10;
}
[data-start="0830"] {
grid-row-start: 11;
}
[data-start="0845"] {
grid-row-start: 12;
}
[data-start="0900"] {
grid-row-start: 13;
}
[data-start="0915"] {
grid-row-start: 14;
}
[data-start="0930"] {
grid-row-start: 15;
}
[data-start="0945"] {
grid-row-start: 16;
}
[data-start="1000"] {
grid-row-start: 17;
}
[data-start="1015"] {
grid-row-start: 18;
}
[data-start="1030"] {
grid-row-start: 19;
}
[data-start="1045"] {
grid-row-start: 20;
}
[data-start="1100"] {
grid-row-start: 21;
}
[data-start="1115"] {
grid-row-start: 22;
}
[data-start="1130"] {
grid-row-start: 23;
}
[data-start="1145"] {
grid-row-start: 24;
}
[data-start="1200"] {
grid-row-start: 25;
}
[data-start="1215"] {
grid-row-start: 26;
}
[data-start="1230"] {
grid-row-start: 27;
}
[data-start="1245"] {
grid-row-start: 28;
}
[data-start="1300"] {
grid-row-start: 29;
}
[data-start="1315"] {
grid-row-start: 30;
}
[data-start="1330"] {
grid-row-start: 31;
}
[data-start="1345"] {
grid-row-start: 32;
}
[data-start="1400"] {
grid-row-start: 33;
}
[data-start="1415"] {
grid-row-start: 34;
}
[data-start="1430"] {
grid-row-start: 35;
}
[data-start="1445"] {
grid-row-start: 36;
}
[data-start="1500"] {
grid-row-start: 37;
}
[data-start="1515"] {
grid-row-start: 38;
}
[data-start="1530"] {
grid-row-start: 39;
}
[data-start="1545"] {
grid-row-start: 40;
}
[data-start="1600"] {
grid-row-start: 41;
}
[data-start="1615"] {
grid-row-start: 42;
}
[data-start="1630"] {
grid-row-start: 43;
}
[data-start="1645"] {
grid-row-start: 44;
}
[data-start="1700"] {
grid-row-start: 45;
}
[data-start="1715"] {
grid-row-start: 46;
}
[data-start="1730"] {
grid-row-start: 47;
}
[data-start="1745"] {
grid-row-start: 48;
}
[data-start="1800"] {
grid-row-start: 49;
}
[data-start="1815"] {
grid-row-start: 50;
}
[data-start="1830"] {
grid-row-start: 51;
}
[data-start="1845"] {
grid-row-start: 52;
}
[data-end="0615"] {
grid-row-end: 2;
}
[data-end="0630"] {
grid-row-end: 3;
}
[data-end="0645"] {
grid-row-end: 4;
}
[data-end="0700"] {
grid-row-end: 5;
}
[data-end="0715"] {
grid-row-end: 6;
}
[data-end="0730"] {
grid-row-end: 7;
}
[data-end="0745"] {
grid-row-end: 8;
}
[data-end="0800"] {
grid-row-end: 9;
}
[data-end="0815"] {
grid-row-end: 10;
}
[data-end="0830"] {
grid-row-end: 11;
}
[data-end="0845"] {
grid-row-end: 12;
}
[data-end="0900"] {
grid-row-end: 13;
}
[data-end="0915"] {
grid-row-end: 14;
}
[data-end="0930"] {
grid-row-end: 15;
}
[data-end="0945"] {
grid-row-end: 16;
}
[data-end="1000"] {
grid-row-end: 17;
}
[data-end="1015"] {
grid-row-end: 18;
}
[data-end="1030"] {
grid-row-end: 19;
}
[data-end="1045"] {
grid-row-end: 20;
}
[data-end="1100"] {
grid-row-end: 21;
}
[data-end="1115"] {
grid-row-end: 22;
}
[data-end="1130"] {
grid-row-end: 23;
}
[data-end="1145"] {
grid-row-end: 24;
}
[data-end="1200"] {
grid-row-end: 25;
}
[data-end="1215"] {
grid-row-end: 26;
}
[data-end="1230"] {
grid-row-end: 27;
}
[data-end="1245"] {
grid-row-end: 28;
}
[data-end="1300"] {
grid-row-end: 29;
}
[data-end="1315"] {
grid-row-end: 30;
}
[data-end="1330"] {
grid-row-end: 31;
}
[data-end="1345"] {
grid-row-end: 32;
}
[data-end="1400"] {
grid-row-end: 33;
}
[data-end="1415"] {
grid-row-end: 34;
}
[data-end="1430"] {
grid-row-end: 35;
}
[data-end="1445"] {
grid-row-end: 36;
}
[data-end="1500"] {
grid-row-end: 37;
}
[data-end="1515"] {
grid-row-end: 38;
}
[data-end="1530"] {
grid-row-end: 39;
}
[data-end="1545"] {
grid-row-end: 40;
}
[data-end="1600"] {
grid-row-end: 41;
}
[data-end="1615"] {
grid-row-end: 42;
}
[data-end="1630"] {
grid-row-end: 43;
}
[data-end="1645"] {
grid-row-end: 44;
}
[data-end="1700"] {
grid-row-end: 45;
}
[data-end="1715"] {
grid-row-end: 46;
}
[data-end="1730"] {
grid-row-end: 47;
}
[data-end="1745"] {
grid-row-end: 48;
}
[data-end="1800"] {
grid-row-end: 49;
}
[data-end="1815"] {
grid-row-end: 50;
}
[data-end="1830"] {
grid-row-end: 51;
}
[data-end="1845"] {
grid-row-end: 52;
}
[data-end="1900"] {
grid-row-end: 53;
}

171
2026.tajmcal.html Normal file
View file

@ -0,0 +1,171 @@
<!doctype html>
<html>
<head>
<meta charset="utf-8" />
<title>Tidrapportering</title>
<meta name="viewport" content="width=device-width" />
<link rel="stylesheet" href="./app.css" />
</head>
<body>
<header>
<b>Tajm <sup>0.1</sup></b>
<nav>
<strong>Vecka</strong>
<a href="flexsaldo.html">Flexsaldo</a>
</nav>
<span>
<button>AEY</button>
</span>
</header>
<aside class="collapsed left panel">
<h2>Hinkar</h2>
<form method="get">
<fieldset>
<label
><input type="checkbox" value="DD" />API - API
Gateway</label
>
<label
><input type="checkbox" value="API" />DD -
Filutbyte</label
>
<label
><input type="checkbox" value="NCI" />NCI - Nya
CI</label
>
</fieldset>
</form>
</aside>
<main>
<h1>Vecka 5</h1>
<div class="calendar" data-calendar>
<i></i>
<div class="wh">
<b>5 jan</b>
<b>6 jan</b>
<b>7 jan</b>
<b>8 jan</b>
<b>9 jan</b>
</div>
<div class="ts">
<b>6</b>
<b>7</b>
<b class="nt">8</b>
<b class="nt">9</b>
<b class="nt">10</b>
<b class="nt">11</b>
<b class="nt">12</b>
<b class="nt">13</b>
<b class="nt">14</b>
<b class="nt">15</b>
<b class="nt">16</b>
<b>17</b>
<b>18</b>
</div>
<div class="log" data-log>
<article
data-draggable
data-resizeable
tabindex="1"
data-day="mon"
data-start="0730"
data-end="0800"
>
Installerar Zed
</article>
<article
data-draggable
data-resizeable
tabindex="1"
data-day="mon"
data-start="0800"
data-end="1000"
>
Skapar en HTML-mockup
</article>
<article
data-draggable
data-resizeable
tabindex="1"
data-day="mon"
data-start="1000"
data-end="1100"
>
Subgrid experiment
</article>
<article
data-draggable
data-resizeable
tabindex="1"
data-day="mon"
class="break"
data-start="1200"
data-end="1230"
>
Lunch
</article>
<article
data-draggable
data-resizeable
tabindex="1"
data-day="tue"
class="holiday"
data-start="0800"
data-end="1630"
>
Trettondagen
</article>
<article
data-draggable
data-resizeable
tabindex="1"
data-day="wed"
data-start="0730"
data-end="0800"
>
Installerar Zed
</article>
<article
data-draggable
data-resizeable
tabindex="1"
class="break"
data-start="1200"
data-end="1230"
>
Lunch
</article>
<article
data-draggable
data-resizeable
tabindex="1"
data-day="thu"
data-start="0800"
data-end="1000"
>
Skapar en HTML-mockup
</article>
<article
data-draggable
data-resizeable
tabindex="1"
data-day="fri"
data-start="1000"
data-end="1100"
>
Subgrid experiment
</article>
</div>
</div>
</main>
<script src="app.js"></script>
</body>
</html>

102
2026.tajmcal.js Normal file
View file

@ -0,0 +1,102 @@
(function (W) {
let lock, pressed;
const D = ["mon", "tue", "wed", "thu", "fri"];
const log = document.querySelector("[data-log]");
const cursor = document.createElement("i");
cursor.hidden = 1;
log.appendChild(cursor);
const { width, height, y, x } = log.getClientRects()[0];
const drag = (elm) => {
// copy node
// on mouse down:
// move node by grid
// on mouse up:
// re-render grid
};
const resize = (elm) => {
// copy node
// on mouse down:
// move node by grid
// on mouse up:
// re-render grid
};
const create = () => {
cursor.hidden = 1;
const a = document.createElement("article");
const f = document.createElement("form");
f.style.position = "absolute";
f.method = "post";
f.action = "";
const i = document.createElement("input");
i.addEventListener("keydown", ({ key: k }) => {
if (k == "Escape") {
i.blur();
a.parentNode.removeChild(a);
}
});
f.addEventListener("submit", (evt) => {
evt.preventDefault();
a.dataset.draggable = 1;
a.dataset.resizeable = 1;
a.insertAdjacentHTML("afterbegin", i.value);
i.blur();
f.parentNode.removeChild(f);
});
a.dataset.day = cursor.dataset.day;
a.dataset.start = cursor.dataset.start;
a.dataset.end = cursor.dataset.end;
f.appendChild(i);
a.appendChild(f);
log.appendChild(a);
i.focus();
return;
};
const updateCursorPos = ({ pageY, pageX }) => {
clearTimeout(lock);
lock = setTimeout(() => {
const r = Math.floor(((pageY - y) / height) * 52);
const c = Math.floor(((pageX - x) / width) * 5);
const p = ((r - (r % 4)) / 4 + 6) * 100 + (r % 4) * 15;
if (!pressed) {
cursor.dataset.day = D[c];
cursor.dataset.start = ("0000" + p).slice(-4);
}
cursor.dataset.end = (
"0000" + ((p % 100) % 45 == 0 ? p + 55 : p + 15)
).slice(-4);
}, 1);
};
log.onmousedown = (evt) => {
if (evt.target == cursor) {
evt.preventDefault();
cursor.classList.add("pressed");
pressed = true;
}
};
log.onmouseup = (evt) => {
if (evt.target == cursor) {
evt.preventDefault();
cursor.classList.remove("pressed");
pressed = false;
create();
}
};
log.onmouseover = ({ target: elm }) => {
if (elm == log) {
log.onmousemove = updateCursorPos;
cursor.hidden = 0;
} else if (elm != cursor) {
cursor.hidden = 1;
cursor.onmousemove = "";
}
};
})(this);