1class HeroGallery { 2 3 constructor(selector) { 4 5 this.container = document.querySelector(selector); 6 this.images = JSON.parse(this.container.dataset.gallery); 7 this.thumbs = this.container.querySelectorAll("img"); 8 9 this.index = 0; 10 11 this.startX = 0; 12 this.deltaX = 0; 13 14 this.createViewer(); 15 this.bind(); 16 } 17 18 createViewer() { 19 20 this.viewer = document.createElement("div"); 21 this.viewer.className = "gallery-viewer hidden"; 22 23 this.track = document.createElement("div"); 24 this.track.className = "gallery-track"; 25 26 this.images.forEach(img => { 27 28 const slide = document.createElement("div"); 29 slide.className = "gallery-slide"; 30 31 const clone = new Image(); 32 clone.src = "./galery/" + img; 33 34 slide.append(clone); 35 this.track.append(slide); 36 37 }); 38 39 this.prev = document.createElement("button"); 40 this.prev.className = "gallery-nav gallery-prev"; 41 this.prev.innerHTML = "â¹"; 42 43 this.next = document.createElement("button"); 44 this.next.className = "gallery-nav gallery-next"; 45 this.next.innerHTML = "âº"; 46 47 this.closeBtn = document.createElement("button"); 48 this.closeBtn.className = "gallery-close"; 49 this.closeBtn.innerHTML = "Ã"; 50 51 this.viewer.append(this.track, this.prev, this.next, this.closeBtn); 52 53 document.body.append(this.viewer); 54 } 55 56 bind() { 57 58 this.thumbs.forEach((img, i) => { 59 img.addEventListener("click", () => this.open(i)); 60 }); 61 62 this.prev.addEventListener("click", () => this.move(-1)); 63 this.next.addEventListener("click", () => this.move(1)); 64 65 this.viewer.addEventListener("click", e => { 66 if (e.target === this.viewer) this.close(); 67 }); 68 69 document.addEventListener("keydown", e => { 70 71 if (this.viewer.classList.contains("hidden")) return; 72 73 if (e.key === "Escape") this.close(); 74 if (e.key === "ArrowRight") this.move(1); 75 if (e.key === "ArrowLeft") this.move(-1); 76 77 }); 78 79 /* pointer swipe */ 80 81 this.viewer.addEventListener("pointerdown", e => { 82 83 this.startX = e.clientX; 84 this.track.style.transition = "none"; 85 86 }); 87 88 this.viewer.addEventListener("pointermove", e => { 89 90 if (!this.startX) return; 91 92 this.deltaX = e.clientX - this.startX; 93 94 const w = this.viewer.clientWidth; 95 96 this.track.style.transform = 97 `translateX(${ -this.index * w + this.deltaX }px)`; 98 99 }); 100 101 this.viewer.addEventListener("pointerup", () => { 102 103 this.track.style.transition = ""; 104 105 if (Math.abs(this.deltaX) > 80) { 106 107 if (this.deltaX < 0) this.move(1); 108 else this.move(-1); 109 110 } else { 111 this.update(); 112 } 113 114 this.startX = 0; 115 this.deltaX = 0; 116 117 }); 118 119 this.viewer.addEventListener("pointercancel", () => { 120 this.startX = 0; 121 this.deltaX = 0; 122 }); 123 124 this.closeBtn.addEventListener("click", () => this.close()); 125 126 } 127 128 open(i) { 129 130 this.index = i; 131 132 this.viewer.classList.remove("hidden"); 133 134 this.update(); 135 136 } 137 138 close() { 139 140 this.viewer.classList.add("hidden"); 141 142 } 143 144 move(dir) { 145 146 this.index += dir; 147 148 if (this.index < 0) this.index = this.images.length - 1; 149 if (this.index >= this.images.length) this.index = 0; 150 151 this.update(); 152 153 } 154 155 update() { 156 157 const w = this.viewer.clientWidth; 158 159 this.track.style.transform = 160 `translateX(-${this.index * w}px)`; 161 162 } 163 164}
Line numbers count LF bytes from the start of the resource, as the search results do. Vendor segments are library code the classifier recognised; they are stored but not indexed. Bytes are shown as Latin1 characters, one per byte.