1document.addEventListener('DOMContentLoaded', () => { 2 3 if (!window.PDF_URL) { 4 console.error('PDF_URL not found'); 5 return; 6 } 7 8 const container = document.getElementById('flipbook'); 9 const loadingEl = document.getElementById('ebook-loading'); 10 const percentEl = document.getElementById('loadingPercent'); 11 12 let pageFlip; 13 let scale = 1.3; 14 let currentPdfUrl = window.PDF_URL; 15 let isBookLoaded = false; 16 let pdfTotalPages = 0; 17 let cachedCanvases = []; 18 let isDragging = false; 19 let hasDragged = false; 20 let startX = 0; 21 let startY = 0; 22 let translateX = 0; 23 let translateY = 0; 24 let isZooming = false; 25 26 function isMobile(){ 27 return window.innerWidth < 768; 28 } 29 /* ===== Init FlipBook (à¸à¸£à¸±à¹à¸à¹à¸à¸µà¸¢à¸§) ===== */ 30 pageFlip = new St.PageFlip(container, { 31 width: 600, 32 height: 800, 33 minWidth: 315, 34 maxWidth: 900, 35 size: "stretch", 36 showCover: true, 37 maxShadowOpacity: 0.5, 38 mobileScrollSupport: true, 39 usePortrait: true, 40 disableFlipByDrag:true, 41 }); 42 43 loadPdf(currentPdfUrl); 44 45 /* ===== Load PDF ===== */ 46 function loadPdf(pdfUrl) { 47 loadingEl.style.display = 'flex'; 48 percentEl.textContent = '0%'; 49 50 if (isBookLoaded) { 51 pageFlip.clear(); 52 } 53 54 pdfjsLib.getDocument(pdfUrl).promise.then(pdf => { 55 56 pdfTotalPages = pdf.numPages; 57 document.getElementById('totalPages').textContent = pdfTotalPages; 58 59 let rendered = 0; 60 const pages = []; 61 62 for (let i = 1; i <= pdfTotalPages; i++) { 63 pages.push( 64 pdf.getPage(i).then(page => { 65 const viewport = page.getViewport({ scale }); 66 const canvas = document.createElement('canvas'); 67 const ctx = canvas.getContext('2d'); 68 69 canvas.width = viewport.width; 70 canvas.height = viewport.height; 71 72 return page.render({ 73 canvasContext: ctx, 74 viewport 75 }).promise.then(() => { 76 rendered++; 77 const percent = Math.round((rendered / pdfTotalPages) * 100); 78 percentEl.textContent = percent + '%'; 79 return canvas; 80 }); 81 }) 82 ); 83 } 84 85 Promise.all(pages).then(canvases => { 86 cachedCanvases = canvases; 87 pageFlip.loadFromHTML(canvases); 88 89 pageFlip.off('flip'); 90 pageFlip.on('flip', updatePage); 91 92 loadingEl.style.display = 'none'; 93 updatePage(); 94 isBookLoaded = true; 95 }); 96 }); 97 } 98 99 function cloneCanvases(canvases) { 100 return canvases.map(src => { 101 const c = document.createElement('canvas'); 102 c.width = src.width; 103 c.height = src.height; 104 c.getContext('2d').drawImage(src, 0, 0); 105 return c; 106 }); 107 } 108 /* ===== Page Indicator ===== */ 109 function updatePage() { 110 document.getElementById('currentPage').textContent = 111 pageFlip.getCurrentPageIndex() + 1; 112 } 113 114 /* ===== Controls ===== */ 115 document.getElementById('nextBtn').onclick = () => pageFlip.flipNext(); 116 document.getElementById('prevBtn').onclick = () => pageFlip.flipPrev(); 117 118 document.getElementById('firstBtn').onclick = () => { 119 pageFlip.turnToPage(0); 120 setTimeout(updatePage, 0); 121 }; 122 123 document.getElementById('lastBtn').onclick = () => { 124 pageFlip.turnToPage(pdfTotalPages - 1); 125 setTimeout(updatePage, 0); 126 }; 127 128 let zoomScale = 1; 129 const ZOOM_MIN = 0.8; 130 const ZOOM_MAX = 2.5; 131 132 const wrapper = document.querySelector('.flipbook-wrapper'); 133 134 document.getElementById('zoomIn').onclick = () => zoomBook(0.1); 135 document.getElementById('zoomOut').onclick = () => zoomBook(-0.1); 136 137 function zoomBook(delta) { 138 zoomScale = Math.max(ZOOM_MIN, Math.min(ZOOM_MAX, zoomScale + delta)); 139 wrapper.style.setProperty('--zoom', zoomScale); 140 if (zoomScale > 1) { 141 142 isZooming = true; 143 144 flipbookEl.style.cursor = 'grab'; 145 146 } else { 147 148 isZooming = false;
149 150 translateX = 0; 151 translateY = 0; 152 153 wrapper.style.setProperty('--tx','0px'); 154 wrapper.style.setProperty('--ty','0px'); 155 156 flipbookEl.style.cursor = 'default'; 157 } 158 159 } 160 161 const flipbookEl = document.getElementById('flipbook'); 162 163 if(!isMobile()){ 164 flipbookEl.addEventListener('mousedown', (e) => { 165 166 if (zoomScale <= 1) return; // zoom à¸à¹à¸à¸à¸à¸¶à¸à¸à¸°à¸¥à¸²à¸à¹à¸à¹ 167 168 isDragging = true; 169 flipbookEl.classList.add('dragging'); 170 171 startX = e.clientX - translateX; 172 startY = e.clientY - translateY; 173 }); 174 175 document.addEventListener('mousemove', (e) => { 176 177 if (!isDragging) return; 178 179 translateX = e.clientX - startX; 180 translateY = e.clientY - startY; 181 182 wrapper.style.setProperty('--tx', translateX + 'px'); 183 wrapper.style.setProperty('--ty', translateY + 'px'); 184 }); 185 186 document.addEventListener('mouseup', () => { 187 188 isDragging = false; 189 flipbookEl.classList.remove('dragging'); 190 }); 191 } 192 193 if(isMobile()){ 194 195 196 // ลาà¸à¹à¸¡à¹à¸²à¸ªà¹à¹à¸à¸à¸à¹à¸¥à¹à¸ 197 flipbookEl.addEventListener("pointerdown",(e)=>{ 198 console.log('pointerdown'); 199 200 if(zoomScale <= 1) return; 201 flipbookEl.classList.add('dragging'); 202 203 isDragging = true; 204 hasDragged = false; 205 206 startX = e.clientX - translateX; 207 startY = e.clientY - translateY; 208 209 if(isZooming){ 210 e.stopPropagation(); 211 e.preventDefault(); 212 } 213 214 }); 215 216 // ระหวà¹à¸²à¸à¸¥à¸²à¸ 217 document.addEventListener("pointermove",(e)=>{ 218 console.log('pointermove'); 219 220 221 if(!isDragging) return; 222 hasDragged = true; 223 224 if(isDragging && hasDragged){ 225 console.log('isDragging ;',hasDragged); 226 e.stopPropagation(); 227 e.preventDefault(); 228 } 229 230 translateX = e.clientX - startX; 231 translateY = e.clientY - startY; 232 233 wrapper.style.setProperty('--tx', translateX + 'px'); 234 wrapper.style.setProperty('--ty', translateY + 'px'); 235 236 }); 237 238 // à¸à¸¥à¹à¸à¸¢ 239 document.addEventListener("pointerup",()=>{ 240 console.log('pointerup'); 241 console.log('isDragging ;',isDragging); 242 243 isDragging = false; 244 flipbookEl.classList.remove('dragging'); 245 }); 246 247 // flipbookEl.addEventListener("click",(e)=>{ 248 // if(hasDragged){ 249 // e.preventDefault(); 250 // e.stopPropagation(); 251 // hasDragged = false; 252 // } 253 // }); 254 } 255 256 /* ===== Fullscreen / Download / Print ===== */ 257 const fullscreenBtn = document.getElementById('fullscreenBtn'); 258 const flipbookWrapper = document.getElementById('flipbookWrapper'); 259 const ebookControls = document.getElementById('ebookControls'); 260 261 const controlsParent = ebookControls.parentElement; 262 263 fullscreenBtn.onclick = () => { 264 if (!document.fullscreenElement) { 265 flipbookWrapper.requestFullscreen(); 266 } else { 267 document.exitFullscreen(); 268 } 269 }; 270 271 document.addEventListener('fullscreenchange', () => { 272 273 const isFullscreen = document.fullscreenElement === flipbookWrapper; 274 const currentPage = pageFlip?.getCurrentPageIndex() ?? 0; 275 276 if (isFullscreen) { 277 /* ===== à¹à¸à¹à¸² fullscreen ===== */ 278 flipbookWrapper.appendChild(ebookControls); 279 flipbookWrapper.classList.add('is-fullscreen'); 280 281 // à¹à¸à¹ PageFlip à¹à¸à¸´à¸¡ (stretch) 282 requestAnimationFrame(() => { 283 pageFlip.update(); 284 pageFlip.resize?.(); 285 }); 286 287 } else { 288 /* ===== à¸à¸à¸ fullscreen ===== */ 289 controlsParent.appendChild(ebookControls); 290 flipbookWrapper.classList.remove('is-fullscreen'); 291 292 // ð¥ FIX à¸à¸µà¹à¸à¸¹à¸à¸à¹à¸à¸: destroy + init à¹à¸«à¸¡à¹ 293 // pageFlip.destroy(); 294 container.innerHTML = ''; 295 console.log('xxx'); 296 297 pageFlip = new St.PageFlip(container, { 298 width: 600, 299 height: 800, 300 minWidth: 315, 301 maxWidth: 900, 302 size: "stretch", 303 showCover: true, 304 maxShadowOpacity: 0.5, 305 mobileScrollSupport: true, 306 usePortrait: true, 307 disableFlipByDrag:true, 308 }); 309 310 pageFlip.loadFromHTML(cloneCanvases(cachedCanvases)); 311 pageFlip.on('flip', updatePage); 312 313 // รภDOM stable à¹à¸¥à¹à¸§à¸à¹à¸à¸¢à¸à¸¥à¸±à¸à¸«à¸à¹à¸²à¸à¸µà¹à¸à¹à¸²à¸ 314 requestAnimationFrame(() => { 315 requestAnimationFrame(() => { 316 pageFlip.turnToPage(currentPage); 317 updatePage(); 318 }); 319 }); 320 } 321 }); 322 323 324 function hardResetPageFlip() { 325 if (!window.pageFlip) return; 326 327 requestAnimationFrame(() => { 328 pageFlip.update(); 329 pageFlip.resize?.(); 330 331 setTimeout(() => { 332 pageFlip.update(); 333 pageFlip.resize?.(); 334 }, 120); 335 }); 336 } 337 338 document.getElementById('downloadBtn').onclick = function (e) { 339 e.preventDefault(); 340 341 window.location.href = currentDownloadUrl; 342 // const a = document.createElement('a'); 343 // a.href = currentPdfUrl; 344 // a.download = ''; // à¸à¸¥à¹à¸à¸¢à¸§à¹à¸²à¸ = à¹à¸à¹à¸à¸·à¹à¸à¹à¸à¸¥à¹à¹à¸à¸´à¸¡ 345 // document.body.appendChild(a); 346 // a.click(); 347 // document.body.removeChild(a); 348 }; 349 350 document.getElementById('printBtn').onclick = () => { 351 // ลภiframe à¹à¸à¹à¸² (à¸à¹à¸²à¸¡à¸µ) 352 let iframe = document.getElementById('pdf-print-iframe'); 353 if (iframe) iframe.remove(); 354 355 iframe = document.createElement('iframe'); 356 iframe.id = 'pdf-print-iframe'; 357 iframe.style.display = 'none'; 358 iframe.src = currentPdfUrl; 359 360 document.body.appendChild(iframe); 361 362 iframe.onload = () => { 363 iframe.contentWindow.focus(); 364 iframe.contentWindow.print(); 365 }; 366 }; 367 368 document.getElementById('resetZoom').onclick = resetZoom; 369 370 function resetZoom(){ 371 372 zoomScale = 1; 373 374 wrapper.style.setProperty('--zoom',1); 375 wrapper.style.setProperty('--tx','0px'); 376 wrapper.style.setProperty('--ty','0px'); 377 378 translateX = 0; 379 translateY = 0; 380 } 381});
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.