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.classList.add("bigsize"); 30 figure.setAttribute("data-current-index", validIndex++); 31 32 imgElement.addEventListener("click", () => this.initModal(figure)); 33 }); 34 35 } 36 37 // í´ë¦ë ì´ë¯¸ì§ì ëí 모ë¬ì ì¼. 모ë¬ì´ ì¡´ì¬íì§ ìì¼ë©´ ìì± 38 initModal(target) { 39 const _this = this; 40 if(!this.#MODAL) { 41 this.createModal(); 42 this.initElements(); 43 } 44 const { lightBoxImage, prevBtn, nextBtn, caption, number} = this.#ELEMENTS; 45 const index = parseInt(target.getAttribute("data-current-index", 10)); 46 47 this.#MODAL.setAttribute("data-current-index", index); 48 49 // ì´ë²¤í¸ê° ì¶ê°ëì§ ììë¤ë©´ ì¶ê° 50 if (!this.#FLAG) { 51 $(this.#MODAL).on("open.zf.reveal", (e) => { 52 this.#FIGURES.forEach(figure => this.getActiveSource(figure)); 53 this.#CURRENT_INDEX = parseInt(this.#MODAL.getAttribute("data-current-index"), 10); 54 lightBoxImage.onload = () => { 55 caption.textContent = this.#CAPTION[this.#CURRENT_INDEX]; 56 number.textContent = `${this.#CURRENT_INDEX + 1} / ${this.#SOURCE.length}`; 57 this.changeBtnState(); 58 59 // image size for first(캡ì ì ì´ë¯¸ì§ì í¬ê¸°ë¥¼ ë§ì¶ê¸° ìí ì¤ì ) 60 const _lightBox = this.#ELEMENTS.lightBox; 61 const _imageWidth = lightBoxImage.offsetWidth; 62 if(_imageWidth >= 400 && _imageWidth <= 1280) { 63 _lightBox.style.setProperty("--nd-lightbox-text-max-width", _imageWidth + "px"); 64 } else { 65 _lightBox.style.setProperty("--nd-lightbox-text-max-width", ""); 66 } 67 }; 68 lightBoxImage.src = this.#SOURCE[this.#CURRENT_INDEX]; 69 }); 70 71 72 $(this.#MODAL).on("closed.zf.reveal", (e) => { 73 _this.#ISMODALOPEN = false; 74 _this.#SOURCE = []; 75 _this.#CAPTION = []; 76 }); 77 78 $(this.#MODAL).on("click", ".btn-close", function(e) { 79 $('#edit-image-viewer').foundation('close'); 80 }); 81 82 document.addEventListener("keydown", (e) => { 83 if (this.#ISMODALOPEN == false || !["ArrowRight", "ArrowLeft", "Escape"].includes(e.code)) return false; 84 switch (e.code) { 85 case "ArrowRight": 86 this.next(); 87 break; 88 case "ArrowLeft": 89 this.prev(); 90 break; 91 } 92 }); 93 94 prevBtn.addEventListener("click", () => this.prev()); 95 nextBtn.addEventListener("click", () => this.next()); 96 this.#FLAG = true; 97 } 98 99 $(this.#MODAL).foundation("open"); 100 this.#ISMODALOPEN = true; 101 } 102 103 // ëª¨ë¬ ìì±íê³ foundation íì±í 104 createModal() { 105 const htmlContent = ` 106 <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"> 107 <div class="lightbox-container"> 108 <article class="lightbox"> 109 <section class="lightbox-body"> 110 <button class="btn-close"></button> 111 <img class="lightbox-image" alt="viewer Image"> 112 <div class="lightbox-text"> 113 <div class="lightbox-caption"></div> 114 <div class="lightbox-number"></div> 115 </div> 116 <button class="lightbox-btn lightbox-prev"></button> 117 <button class="lightbox-btn lightbox-next"></button> 118 </section> 119 </article> 120 </div> 121 </div>`; 122 123 document.body.insertAdjacentHTML('beforeend', htmlContent); 124 $('#edit-image-viewer').css("outline", "none"); 125 $('#edit-image-viewer').foundation(); 126 this.#MODAL = document.querySelector("#edit-image-viewer"); 127 } 128 129 initElements() { 130 this.#ELEMENTS = { 131 lightBox: this.#MODAL.querySelector(".lightbox"), 132 lightBoxImage: this.#MODAL.querySelector(".lightbox-image"), 133 prevBtn: this.#MODAL.querySelector(".lightbox-prev"), 134 nextBtn: this.#MODAL.querySelector(".lightbox-next"), 135 caption: this.#MODAL.querySelector(".lightbox-caption"), 136 number: this.#MODAL.querySelector(".lightbox-number"), 137 ...this.#ELEMENTS, 138 }; 139 } 140 141 // src,caption ë°°ì´ ì ë°ì´í¸ 142 getActiveSource(figure) { 143 const imgElement = figure.querySelector("picture img") || figure.querySelector("img"), 144 imgSrc = imgElement.src, 145 sources = figure.querySelectorAll("picture source"); 146 const caption = figure.querySelector("figcaption"); 147 148 for (let source of sources) { 149 if (source.srcset === imgSrc) { 150 this.#SOURCE.push(source.srcset); 151 this.#CAPTION.push(caption.textContent || ""); 152 return; 153 } 154 } 155 this.#SOURCE.push(imgSrc); 156 this.#CAPTION.push(caption.textContent); 157 } 158 159 // ì´ë¯¸ì§ë¥¼ ë³ê²½íë ë©ìë 160 changeImage(direction) { 161 this.#CURRENT_INDEX += direction; 162 if (this.#CURRENT_INDEX < 0 || this.#CURRENT_INDEX > this.#SOURCE.length - 1) { 163 this.#CURRENT_INDEX = Math.min(Math.max(0, this.#CURRENT_INDEX), this.#SOURCE.length - 1) 164 return false; 165 } 166 const { lightBox, lightBoxImage, caption, number } = this.#ELEMENTS; 167 lightBox.style.opacity = 0; 168 setTimeout(() => { 169 lightBoxImage.onload = () => { 170 caption.textContent = this.#CAPTION[this.#CURRENT_INDEX]; 171 this.changeBtnState(); 172 number.textContent = `${this.#CURRENT_INDEX + 1} / ${this.#SOURCE.length}`; 173 lightBox.style.opacity = 1; 174 175 // image size(캡ì ì ì´ë¯¸ì§ì í¬ê¸°ë¥¼ ë§ì¶ê¸° ìí ì¤ì ) 176 const _imageWidth = lightBoxImage.offsetWidth; 177 if(_imageWidth >= 400 && _imageWidth <= 1280) { 178 lightBox.style.setProperty("--nd-lightbox-text-max-width", _imageWidth + "px"); 179 } else { 180 lightBox.style.setProperty("--nd-lightbox-text-max-width", ""); 181 } 182 }; 183 lightBoxImage.src = this.#SOURCE[this.#CURRENT_INDEX]; 184 }, 100); 185 } 186 187 // ë²í¼ ìí를 ë³ê²½ 188 changeBtnState() { 189 this.#ELEMENTS.prevBtn.classList.toggle("is-hidden", this.#CURRENT_INDEX === 0); 190 this.#ELEMENTS.nextBtn.classList.toggle("is-hidden", this.#CURRENT_INDEX === this.#SOURCE.length - 1); 191 // this.#ELEMENTS.prevBtn.classList.toggle("disabled", this.#CURRENT_INDEX === 0); 192 // this.#ELEMENTS.nextBtn.classList.toggle("disabled", this.#CURRENT_INDEX === this.#SOURCE.length - 1); 193 } 194 195 // 196 checkState() { 197 } 198 199 // ì´ì ì´ë¯¸ì§ë¡ ë기ë ë©ìë 200 prev() { 201 this.changeImage(-1); 202 } 203 204 // ë¤ì ì´ë¯¸ì§ë¡ ë기ë ë©ìë 205 next() { 206 this.changeImage(1); 207 } 208}
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.