1/** 2 * ê¸°ì¬ ë·° íì´ì§(articleView.html) ìì ì´ë¯¸ì§ í´ë¦ ì, í´ë¹ ì´ë¯¸ì§ì ëí lightbox를 ì ê³µ. 3 * ì¬ì©ìê° ì¤ì í ìµì ëë¹ë¥¼ 충족íë ì´ë¯¸ì§ë§ íì. default 0 4 */ 5class ImageViewer { 6 #CURRENT_INDEX = 0; // íì¬ ë³´ê³ ìë ì´ë¯¸ì§ì ì¸ë±ì¤ 7 #SELECTOR; 8 #SOURCE = []; // lightboxìì ë³´ì¬ì¤ ì´ë¯¸ì§ì src ë°°ì´ 9 #CAPTION = []; // ê° ì´ë¯¸ì§ì ëí 캡ì ë°°ì´ 10 #ELEMENTS = {}; 11 #MIN_WIDTH = 0; // ImageViewerì í¬í¨ë ì´ë¯¸ì§ì ìµì ëë¹. 기본 ê° 0 12 #MODAL = null; // lightbox ëª¨ë¬ DOM ìì 13 #FIGURES = []; // lightboxì í¬í¨ë figure ììë¤ì ë°°ì´ 14 #FLAG = false; 15 #ISMODALOPEN = false; 16 constructor(selector, minWidth = 0) { 17 this.#SELECTOR = selector; 18 this.#MIN_WIDTH = minWidth; 19 this.init(); 20 } 21 22 init() { 23 const figures = document.querySelectorAll(this.#SELECTOR); 24 let validIndex = 0; 25 figures.forEach(figure => { 26 const imgElement = figure.querySelector("picture img") || figure.querySelector("img"); 27 if(imgElement.naturalWidth < this.#MIN_WIDTH || !imgElement) return; 28 this.#FIGURES.push(figure); 29 figure.setAttribute("data-current-index", validIndex++); 30 31 imgElement.addEventListener("click", () => this.initModal(figure)); 32 }); 33 34 } 35 36 // í´ë¦ë ì´ë¯¸ì§ì ëí 모ë¬ì ì¼. 모ë¬ì´ ì¡´ì¬íì§ ìì¼ë©´ ìì± 37 initModal(target) { 38 const _this = this; 39 if(!this.#MODAL) { 40 this.createModal(); 41 this.initElements(); 42 } 43 const { lightBoxImage, prevBtn, nextBtn, caption, number} = this.#ELEMENTS; 44 const index = parseInt(target.getAttribute("data-current-index", 10)); 45 46 this.#MODAL.setAttribute("data-current-index", index); 47 48 // ì´ë²¤í¸ê° ì¶ê°ëì§ ììë¤ë©´ ì¶ê° 49 if (!this.#FLAG) { 50 $(this.#MODAL).on("open.zf.reveal", (e) => { 51 this.#FIGURES.forEach(figure => this.getActiveSource(figure)); 52 this.#CURRENT_INDEX = parseInt(this.#MODAL.getAttribute("data-current-index"), 10); 53 lightBoxImage.onload = () => { 54 caption.textContent = this.#CAPTION[this.#CURRENT_INDEX]; 55 number.textContent = `${this.#CURRENT_INDEX + 1} / ${this.#SOURCE.length}`; 56 this.changeBtnState(); 57 }; 58 lightBoxImage.src = this.#SOURCE[this.#CURRENT_INDEX]; 59 }); 60 61 62 $(this.#MODAL).on("closed.zf.reveal", (e) => { 63 _this.#ISMODALOPEN = false; 64 _this.#SOURCE = []; 65 _this.#CAPTION = []; 66 }); 67 68 $(this.#MODAL).on("click", ".btn-close", function(e) { 69 $('#edit-image-viewer').foundation('close'); 70 }); 71 72 document.addEventListener("keydown", (e) => { 73 if (this.#ISMODALOPEN == false || !["ArrowRight", "ArrowLeft", "Escape"].includes(e.code)) return false; 74 switch (e.code) { 75 case "ArrowRight": 76 this.next(); 77 break; 78 case "ArrowLeft": 79 this.prev(); 80 break; 81 } 82 }); 83 84 prevBtn.addEventListener("click", () => this.prev()); 85 nextBtn.addEventListener("click", () => this.next()); 86 this.#FLAG = true; 87 } 88 89 $(this.#MODAL).foundation("open"); 90 this.#ISMODALOPEN = true; 91 } 92 93 // ëª¨ë¬ ìì±íê³ foundation íì±í 94 createModal() { 95 const htmlContent = ` 96 <div id="edit-image-viewer" class="reveal lightbox-reveal" data-reveal="" data-v-offset="0" data-h-offset="0" data-close-on-click="false" data-close-on-esc="true" data-animation-in="fade-in" data-animation-out="fade-out" data-additional-overlay-classes="lightbox-overlay"> 97 <div class="lightbox-container"> 98 <article class="lightbox"> 99 <section class="lightbox-body"> 100 <button class="btn-close"></button> 101 <img class="lightbox-image" alt="viewer Image"> 102 <div class="lightbox-text"> 103 <div class="lightbox-caption"></div> 104 <div class="lightbox-number"></div> 105 </div> 106 <button class="lightbox-btn lightbox-prev"></button> 107 <button class="lightbox-btn lightbox-next"></button> 108 </section> 109 </article> 110 </div> 111 </div>`; 112 113 document.body.insertAdjacentHTML('beforeend', htmlContent); 114 $('#edit-image-viewer').css("outline", "none"); 115 $('#edit-image-viewer').foundation(); 116 this.#MODAL = document.querySelector("#edit-image-viewer"); 117 } 118 119 initElements() { 120 this.#ELEMENTS = { 121 lightBox: this.#MODAL.querySelector(".lightbox"), 122 lightBoxImage: this.#MODAL.querySelector(".lightbox-image"), 123 prevBtn: this.#MODAL.querySelector(".lightbox-prev"), 124 nextBtn: this.#MODAL.querySelector(".lightbox-next"), 125 caption: this.#MODAL.querySelector(".lightbox-caption"), 126 number: this.#MODAL.querySelector(".lightbox-number"), 127 ...this.#ELEMENTS, 128 }; 129 } 130 131 // src,caption ë°°ì´ ì ë°ì´í¸ 132 getActiveSource(figure) { 133 const imgElement = figure.querySelector("picture img") || figure.querySelector("img"), 134 imgSrc = imgElement.src, 135 sources = figure.querySelectorAll("picture source"); 136 const caption = figure.querySelector("figcaption"); 137 138 for (let source of sources) { 139 if (source.srcset === imgSrc) { 140 this.#SOURCE.push(source.srcset); 141 this.#CAPTION.push(caption.textContent || ""); 142 return; 143 } 144 } 145 this.#SOURCE.push(imgSrc); 146 this.#CAPTION.push(caption.textContent); 147 } 148 149 // ì´ë¯¸ì§ë¥¼ ë³ê²½íë ë©ìë 150 changeImage(direction) { 151 this.#CURRENT_INDEX += direction; 152 if (this.#CURRENT_INDEX < 0 || this.#CURRENT_INDEX > this.#SOURCE.length - 1) { 153 this.#CURRENT_INDEX = Math.min(Math.max(0, this.#CURRENT_INDEX), this.#SOURCE.length - 1) 154 return false; 155 } 156 const { lightBox, lightBoxImage, caption, number } = this.#ELEMENTS; 157 lightBox.style.opacity = 0; 158 setTimeout(() => { 159 lightBoxImage.onload = () => { 160 caption.textContent = this.#CAPTION[this.#CURRENT_INDEX]; 161 this.changeBtnState(); 162 number.textContent = `${this.#CURRENT_INDEX + 1} / ${this.#SOURCE.length}`; 163 lightBox.style.opacity = 1; 164 }; 165 lightBoxImage.src = this.#SOURCE[this.#CURRENT_INDEX]; 166 }, 100); 167 } 168 169 // ë²í¼ ìí를 ë³ê²½ 170 changeBtnState() { 171 this.#ELEMENTS.prevBtn.classList.toggle("is-hidden", this.#CURRENT_INDEX === 0); 172 this.#ELEMENTS.nextBtn.classList.toggle("is-hidden", this.#CURRENT_INDEX === this.#SOURCE.length - 1); 173 // this.#ELEMENTS.prevBtn.classList.toggle("disabled", this.#CURRENT_INDEX === 0); 174 // this.#ELEMENTS.nextBtn.classList.toggle("disabled", this.#CURRENT_INDEX === this.#SOURCE.length - 1); 175 } 176 177 // 178 checkState() { 179 } 180 181 // ì´ì ì´ë¯¸ì§ë¡ ë기ë ë©ìë 182 prev() { 183 this.changeImage(-1); 184 } 185 186 // ë¤ì ì´ë¯¸ì§ë¡ ë기ë ë©ìë 187 next() { 188 this.changeImage(1); 189 } 190}
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.