summaryrefslogtreecommitdiffstats
path: root/content/assets/lightbox.js
diff options
context:
space:
mode:
Diffstat (limited to 'content/assets/lightbox.js')
-rw-r--r--content/assets/lightbox.js137
1 files changed, 137 insertions, 0 deletions
diff --git a/content/assets/lightbox.js b/content/assets/lightbox.js
new file mode 100644
index 0000000..39a5074
--- /dev/null
+++ b/content/assets/lightbox.js
@@ -0,0 +1,137 @@
1(() => {
2 const mainEl = document.querySelector("main");
3 const lightboxContainerEl = document.querySelector(".js-lightbox");
4 const lightboxEl = lightboxContainerEl.classList.contains("o-lightbox")
5 ? lightboxContainerEl
6 : lightboxContainerEl.querySelector(".o-lightbox");
7 const lightboxCloseEl = lightboxEl.querySelector(".o-lightbox__close-btn");
8 const lightboxPrevEl = lightboxEl.querySelector(".o-lightbox__nav-btn--prev");
9 const lightboxNextEl = lightboxEl.querySelector(".o-lightbox__nav-btn--next");
10 const lightboxImgEl = lightboxEl.querySelector(".o-lightbox__img");
11 const lightboxThumbnailsEl = lightboxEl.querySelector(".o-lightbox__thumbnails");
12 const figureEls = Array.from(mainEl.querySelectorAll(".js-lightbox__image"));
13
14 const standalone = lightboxContainerEl.classList.contains("js-lightbox--standalone");
15 let currentIndex = 0;
16 let visible = !lightboxContainerEl.classList.contains("u-d-none");
17 let mouseDown = false;
18
19 const show = () => {
20 visible = true;
21 lightboxContainerEl.classList.remove("u-d-none");
22 }
23
24 const hide = () => {
25 if (!standalone) {
26 visible = false;
27 lightboxContainerEl.classList.add("u-d-none");
28 }
29 }
30
31 const setIndex = (i) => {
32 if (i < 0 || i >= images.length) {
33 return;
34 }
35 images[currentIndex].thumbnailEl.classList.remove("is-selected");
36 currentIndex = i;
37 lightboxImgEl.src = figureEls[i].firstElementChild.href;
38 lightboxImgEl.alt = images[currentIndex].description;
39 images[i].thumbnailEl.classList.add("is-selected");
40 };
41
42 const prev = () => setIndex(currentIndex > 0 ? currentIndex - 1 : figureEls.length - 1);
43
44 const next = () => setIndex(currentIndex < figureEls.length - 1 ? currentIndex + 1 : 0);
45
46 lightboxCloseEl?.addEventListener("click", hide);
47 lightboxPrevEl.addEventListener("click", prev);
48 lightboxNextEl.addEventListener("click", next);
49
50 const images = figureEls.map((figureEl, i) => {
51 const go = e => {
52 e.preventDefault();
53 show();
54 setIndex(i);
55 };
56
57 const imgEl = figureEl.querySelector("img");
58 const captionEl = figureEl.querySelector("figcaption");
59
60 const src = imgEl.src;
61 const description = captionEl?.innerHTML ?? "";
62
63 const thumbnailButtonEl = document.createElement("button");
64 const thumbnailImgEl = document.createElement("img");
65
66 thumbnailImgEl.classList.add("o-lightbox__thumbnail-img");
67 thumbnailImgEl.src = src;
68
69 thumbnailButtonEl.classList.add("o-lightbox__thumbnail");
70 thumbnailButtonEl.appendChild(thumbnailImgEl);
71 thumbnailButtonEl.addEventListener("click", go);
72
73 lightboxThumbnailsEl.appendChild(thumbnailButtonEl);
74
75 if (!standalone) {
76 figureEl.firstElementChild.addEventListener("click", go);
77 }
78
79 return {
80 thumbnailEl: thumbnailButtonEl,
81 description,
82 };
83 });
84
85 setIndex(0);
86
87 if (figureEls.length <= 1) {
88 lightboxPrevEl.remove();
89 lightboxNextEl.remove();
90 lightboxThumbnailsEl.remove();
91 }
92
93 if (!standalone) {
94 document.addEventListener('mousedown', (e) => {
95 if (visible) {
96 mouseDown = !lightboxEl.contains(e.target) || lightboxEl === e.target;
97 }
98 });
99
100 document.addEventListener('click', (e) => {
101 if (visible && mouseDown) {
102 mouseDown = false;
103 e.preventDefault();
104 e.stopPropagation();
105 hide();
106 }
107 }, { capture: true });
108 }
109
110 window.addEventListener("keydown", e => {
111 if (e.defaultPrevented || !visible) {
112 return;
113 }
114
115 switch (e.key) {
116 case "Left":
117 case "ArrowLeft":
118 prev();
119 break;
120
121 case "Right":
122 case "ArrowRight":
123 next();
124 break;
125
126 case "Esc":
127 case "Escape":
128 hide();
129 break;
130
131 default:
132 return;
133 }
134
135 e.preventDefault();
136 }, true);
137})();