|
|
@ -165,7 +165,8 @@ main > * { |
|
|
|
border: 1px solid #722CA2;
|
|
|
|
margin: -1px; |
|
|
|
} |
|
|
|
:checked + label { |
|
|
|
:checked + label:not(.unselecting), |
|
|
|
.selecting { |
|
|
|
background: #f1cc37;
|
|
|
|
} |
|
|
|
.invalid { |
|
|
@ -248,38 +249,6 @@ main > * { |
|
|
|
} |
|
|
|
|
|
|
|
</style> |
|
|
|
<script> |
|
|
|
let checking = null |
|
|
|
addEventListener("selectstart", (event) => { |
|
|
|
let target = event.target |
|
|
|
if (target.nodeType == 3) target = target.parentNode |
|
|
|
if (target.tagName == "LABEL") { |
|
|
|
const checkbox = document.getElementById(target.htmlFor) |
|
|
|
checking = !checkbox.checked |
|
|
|
checkbox.checked = checking |
|
|
|
} else checking = null |
|
|
|
}); |
|
|
|
document.addEventListener('selectionchange', () => { |
|
|
|
if (checking !== null) { |
|
|
|
const range = document.getSelection().getRangeAt(0) |
|
|
|
const treeWalker = document.createTreeWalker( |
|
|
|
range.commonAncestorContainer, |
|
|
|
NodeFilter.SHOW_ELEMENT, |
|
|
|
{ acceptNode: (node) => node.nodeName.toLowerCase() === 'input' ? NodeFilter.FILTER_ACCEPT : NodeFilter.FILTER_SKIP } |
|
|
|
) |
|
|
|
while (currentNode = treeWalker.nextNode()) { |
|
|
|
if (range.intersectsNode(currentNode)) currentNode.checked = checking; |
|
|
|
} |
|
|
|
} |
|
|
|
}); |
|
|
|
|
|
|
|
document.addEventListener('pointerup', () => { |
|
|
|
if (checking !== null) { |
|
|
|
checking = null |
|
|
|
document.getSelection().empty() |
|
|
|
} |
|
|
|
}) |
|
|
|
</script> |
|
|
|
|
|
|
|
<header> |
|
|
|
<h1>Soli-Bus-Fahrten von Berlin nach Lützerath</h1> |
|
|
@ -296,6 +265,7 @@ Zur groben Einordnung: Eine Fahrt dauert rund 9 Stunden und kostet pro Person mi |
|
|
|
|
|
|
|
<h2>Termine</h2> |
|
|
|
<p>Bitte markier alle Tage im Kalender, an denen du mit dem Soli-Bus nach Lützerath fahren könntest (also nur die Hinfahrt). </p> |
|
|
|
<div id=months> |
|
|
|
<?php |
|
|
|
|
|
|
|
$start = (new DateTimeImmutable())->setTimestamp(mktime(0, 0, 0, $START_DATE[1], $START_DATE[2], $START_DATE[0])); |
|
|
@ -306,6 +276,95 @@ $month_end = (new DateTimeImmutable())->setTimestamp(strtotime("first day of nex |
|
|
|
print_month($month_end); |
|
|
|
|
|
|
|
?>
|
|
|
|
</div> |
|
|
|
<script> |
|
|
|
(function() { |
|
|
|
"use strict" |
|
|
|
|
|
|
|
const months = document.getElementById('months') |
|
|
|
let selecting = null // { origin, className, range }
|
|
|
|
let is_select = false |
|
|
|
|
|
|
|
months.addEventListener("pointerdown", event => { |
|
|
|
selecting = null |
|
|
|
is_select = false |
|
|
|
for (const elem of document.querySelectorAll(".selecting, .unselecting")) { |
|
|
|
elem.className = "" |
|
|
|
} |
|
|
|
|
|
|
|
if (event.buttons !== 1) return |
|
|
|
let target = event.target |
|
|
|
if (target.nodeType == 3) target = target.parentNode |
|
|
|
if (target.tagName !== "LABEL") return |
|
|
|
|
|
|
|
event.preventDefault() |
|
|
|
|
|
|
|
const className = target.className = document.getElementById(target.htmlFor).checked ? "unselecting" : "selecting" |
|
|
|
selecting = { |
|
|
|
origin: target, |
|
|
|
className, |
|
|
|
range: [ target ] |
|
|
|
} |
|
|
|
}) |
|
|
|
|
|
|
|
months.addEventListener('pointermove', event => { |
|
|
|
if (selecting === null) return |
|
|
|
event.preventDefault() |
|
|
|
is_select = true |
|
|
|
|
|
|
|
const range = document.createRange() |
|
|
|
range.selectNode(selecting.origin) |
|
|
|
if (range.comparePoint(event.target, 0) > 0) range.setEndAfter(event.target) |
|
|
|
else range.setStartBefore(event.target) |
|
|
|
|
|
|
|
const treeWalker = document.createTreeWalker( |
|
|
|
range.commonAncestorContainer, |
|
|
|
NodeFilter.SHOW_ELEMENT, |
|
|
|
{ acceptNode: (node) => node.nodeName.toLowerCase() === 'label' ? NodeFilter.FILTER_ACCEPT : NodeFilter.FILTER_SKIP } |
|
|
|
) |
|
|
|
|
|
|
|
const new_range = [] |
|
|
|
let currentNode |
|
|
|
while (currentNode = treeWalker.nextNode()) { |
|
|
|
if (range.intersectsNode(currentNode)) { |
|
|
|
new_range.push(currentNode) |
|
|
|
const idx = selecting.range.indexOf(currentNode) |
|
|
|
if (idx !== -1) selecting.range.splice(idx, 1) |
|
|
|
else currentNode.className = selecting.className |
|
|
|
} |
|
|
|
} |
|
|
|
for (const elem of selecting.range) { |
|
|
|
elem.className = "" |
|
|
|
} |
|
|
|
selecting.range = new_range |
|
|
|
}) |
|
|
|
|
|
|
|
document.addEventListener('pointercancel', event => { |
|
|
|
if (selecting === null) return |
|
|
|
for (const elem of selecting.range) { |
|
|
|
elem.className = "" |
|
|
|
} |
|
|
|
selecting = null |
|
|
|
is_select = false |
|
|
|
}) |
|
|
|
|
|
|
|
document.addEventListener('pointerup', event => { |
|
|
|
if (selecting === null) return |
|
|
|
event.preventDefault() |
|
|
|
for (const elem of selecting.range) { |
|
|
|
if (is_select) document.getElementById(elem.htmlFor).checked = selecting.className == "selecting" |
|
|
|
elem.className = "" |
|
|
|
} |
|
|
|
selecting = null |
|
|
|
}) |
|
|
|
months.addEventListener('click', event => { |
|
|
|
if (is_select) { |
|
|
|
event.preventDefault() |
|
|
|
is_select = false |
|
|
|
} |
|
|
|
}) |
|
|
|
})() |
|
|
|
</script> |
|
|
|
<h3>Tag X</h3> |
|
|
|
<label><input type=checkbox name=tagx>Ich möchte im Fall eines Räumungsversuchs mit dem Solibus nach Lützerath fahren.</label> |
|
|
|
<h2>Kontaktmöglichkeiten</h2> |
|
|
|