PageSourceSearch

https://www.doh.go.th/layouts/theme1/js/flipbook-custom.js

js doh.go.th collected 2026-09-24 09:46:23 UTC 11,388 bytes, 381 lines download raw bytes

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.