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