Slider mit Autorotation, Beitragsliste mit Blaettern
Zwei Wuensche, zwei Bausteine. Die Autorotation ist Sekunden, kein Haekchen: 0 heisst aus, ab 3 laeuft sie. Sie braucht ein Skript - das zweite auf einer oeffentlichen Seite nach den Tabs - und es kommt nur auf Seiten mit einem solchen Slider, sonst bleibt script-src 'none'. Es laeuft nicht bei "weniger Bewegung", hoert beim ersten Tippen, Klicken, Wischen oder Scrollen endgueltig auf und pausiert bei Zeiger, Fokus, Hintergrundtab und ausserhalb des Bildes. Ohne Skript bleibt der Slider vollstaendig bedienbar. Die Beitragsliste kann blaettern statt abzuschneiden. Eine Auswahl auf der Startseite zeigt die neuesten und hoert auf; eine Uebersichtsseite blaettert und sagt, wie viele es sind. Das war die eigene Regel aus Arbeitspaket M, die fuer diesen Baustein noch nicht galt. Beim Bauen zweimal dieselbe Falle wie vorgestern: eine Variable war in der Schliessung nicht gebunden. Einmal das Sprungziel des Sliders (-78 statt 666), einmal die Seitenzahl - die zweite fiel sofort auf, weil die Seite mit 500 antwortete. Geprueft: 395 Tests unter PHP 8.2 und 8.4, 18 JS-Tests, Editortest, Browserpruefung, axe ohne Verstoss. Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
This commit is contained in:
1 parent
b2c4f45474
commit
5a5933f8cd
12 files changed
+229
-9
No files matched your search
@@ -65,9 +65,12 @@ final class PageController extends AbstractController
|
||||
'page' => $page,
|
||||
'canonical' => rtrim($this->siteOrigin, '/').$this->settings->publicPath($path, $home),
|
||||
'navigation' => $this->navigation($path),
|
||||
'postLists' => $this->postLists($page['document']),
|
||||
'postLists' => $this->postLists($page['document'], max(1, $request->query->getInt('seite', 1))),
|
||||
'postMeta' => 'post' === $page['type'] ? $this->posts->termsFor($page['id']) : null,
|
||||
'needsTabs' => $this->hasType($page['document'], 'tabs'),
|
||||
// Ein Slider mit automatischem Weiterblättern ist der zweite Baustein, der
|
||||
// dafür ein Skript braucht - nach demselben Muster wie die Tabs.
|
||||
'needsSlider' => $this->hasAutoplaySlider($page['document']),
|
||||
// Own scripts arrive as one file per page, never inline, so the policy can stay
|
||||
// hash based and no page without a script loses its strict setting.
|
||||
'pageScript' => [] === $this->code->scriptsOf($page['document']) ? null : '/assets/seite/'.$page['id'].'.js',
|
||||
@@ -83,7 +86,7 @@ final class PageController extends AbstractController
|
||||
]);
|
||||
}
|
||||
|
||||
$wantsScript = null !== $page && ($this->hasType($page['document'], 'tabs') || [] !== $this->code->scriptsOf($page['document']));
|
||||
$wantsScript = null !== $page && ($this->hasType($page['document'], 'tabs') || $this->hasAutoplaySlider($page['document']) || [] !== $this->code->scriptsOf($page['document']));
|
||||
$frames = null === $page ? [] : $this->frameHosts($request, $page['document'], ...array_values($areas), ...array_values($sections));
|
||||
|
||||
return $this->shell($response, $wantsScript, $styles, null !== $googleFonts, $frames);
|
||||
@@ -233,6 +236,23 @@ final class PageController extends AbstractController
|
||||
}
|
||||
|
||||
/** True when the stored document contains at least one block of that type. */
|
||||
/** True when a slider on this page asked to advance by itself. */
|
||||
private function hasAutoplaySlider(array $document): bool
|
||||
{
|
||||
$found = false;
|
||||
$walk = function (array $blocks) use (&$walk, &$found): void {
|
||||
foreach ($blocks as $block) {
|
||||
if ('slider' === ($block['type'] ?? null) && ($block['props']['autoplay'] ?? 0) >= 3) {
|
||||
$found = true;
|
||||
}
|
||||
$walk($block['children'] ?? []);
|
||||
}
|
||||
};
|
||||
$walk($document['blocks'] ?? []);
|
||||
|
||||
return $found;
|
||||
}
|
||||
|
||||
private function hasType(array $document, string $type): bool
|
||||
{
|
||||
$found = false;
|
||||
@@ -297,10 +317,10 @@ final class PageController extends AbstractController
|
||||
*
|
||||
* @return array<string, list<array>>
|
||||
*/
|
||||
private function postLists(array $document): array
|
||||
private function postLists(array $document, int $page = 1): array
|
||||
{
|
||||
$lists = [];
|
||||
$walk = function (array $blocks) use (&$walk, &$lists): void {
|
||||
$walk = function (array $blocks) use (&$walk, &$lists, $page): void {
|
||||
foreach ($blocks as $block) {
|
||||
if ('postlist' === ($block['type'] ?? null)) {
|
||||
$props = $block['props'] ?? [];
|
||||
@@ -310,7 +330,12 @@ final class PageController extends AbstractController
|
||||
$term = $this->posts->findTerm($kind, $props[$kind]);
|
||||
}
|
||||
}
|
||||
$lists[$block['id']] = $this->posts->published(1, $term['id'] ?? null, $props['count'])['posts'];
|
||||
// Eine blätternde Liste nimmt die Seite aus der Anfrage, eine Auswahl
|
||||
// immer die erste - sonst würden zwei Listen auf einer Seite einander
|
||||
// umblättern.
|
||||
$paginate = (bool) ($props['paginate'] ?? false);
|
||||
$result = $this->posts->published($paginate ? $page : 1, $term['id'] ?? null, $props['count']);
|
||||
$lists[$block['id']] = $paginate ? $result : $result['posts'];
|
||||
}
|
||||
$walk($block['children'] ?? []);
|
||||
}
|
||||
|
||||
Reference in new issue
Block a user