Skip to main content

max / makenotwork

2.3 KB · 76 lines History Blame Raw
1 // Click-through carousel. Generic: wires every `.carousel` on the page from
2 // the markup emitted by `partials/carousel.html`. No autoplay, no animation,
3 // no per-surface config -- the viewer drives it with prev/next, the dots, or
4 // the arrow keys. Progressive enhancement: until this runs, the first frame is
5 // shown and the controls are inert.
6 (function () {
7 "use strict";
8
9 function initCarousel(root) {
10 var frames = Array.prototype.slice.call(
11 root.querySelectorAll(".carousel-frame")
12 );
13 if (frames.length < 2) return; // nothing to navigate
14
15 var dots = Array.prototype.slice.call(
16 root.querySelectorAll("[data-carousel-dot]")
17 );
18
19 var index = frames.findIndex(function (f) {
20 return f.classList.contains("is-active");
21 });
22 if (index < 0) index = 0;
23
24 function show(next) {
25 index = (next + frames.length) % frames.length; // wrap both ends
26 frames.forEach(function (f, i) {
27 var active = i === index;
28 f.classList.toggle("is-active", active);
29 if (active) {
30 f.removeAttribute("aria-hidden");
31 } else {
32 f.setAttribute("aria-hidden", "true");
33 }
34 });
35 dots.forEach(function (d, i) {
36 var active = i === index;
37 d.classList.toggle("is-active", active);
38 d.setAttribute("aria-selected", active ? "true" : "false");
39 });
40 }
41
42 var prev = root.querySelector("[data-carousel-prev]");
43 var next = root.querySelector("[data-carousel-next]");
44 if (prev) prev.addEventListener("click", function () { show(index - 1); });
45 if (next) next.addEventListener("click", function () { show(index + 1); });
46
47 dots.forEach(function (d) {
48 d.addEventListener("click", function () {
49 show(parseInt(d.getAttribute("data-carousel-dot"), 10) || 0);
50 });
51 });
52
53 root.addEventListener("keydown", function (e) {
54 if (e.key === "ArrowLeft") {
55 show(index - 1);
56 e.preventDefault();
57 } else if (e.key === "ArrowRight") {
58 show(index + 1);
59 e.preventDefault();
60 }
61 });
62
63 root.setAttribute("data-ready", ""); // CSS hook: controls become live
64 }
65
66 function initAll() {
67 document.querySelectorAll(".carousel").forEach(initCarousel);
68 }
69
70 if (document.readyState === "loading") {
71 document.addEventListener("DOMContentLoaded", initAll);
72 } else {
73 initAll();
74 }
75 })();
76