/** * papar_dokumen.js * Handles document list -> preview rendering (PDF + images) on canvas * Requires: jQuery, pdfjsLib (global), Bootstrap * * Note: Ensure pdfjsLib global is available (use non-module CDN). */ (function ($, window, document, undefined) { 'use strict'; $(function () { const $canvas = $('#pdf-canvas'); const canvas = $canvas.length ? $canvas[0] : null; const ctx = canvas ? canvas.getContext('2d') : null; const $container = $('#preview-container'); let currentUrl = null; let zoom = 1.0; if (!canvas || !ctx) { console.warn('Canvas not found for dokumen preview.'); return; } // init event bindings $(document).on('click', '.dokumen-item', function () { const url = $(this).data('url'); if (!url) return; currentUrl = url; loadFile(url); }); $('#btn-zoom-in').on('click', function (e) { e.preventDefault(); zoom = Math.min(3, zoom + 0.2); if (currentUrl) loadFile(currentUrl); }); $('#btn-zoom-out').on('click', function (e) { e.preventDefault(); zoom = Math.max(0.2, zoom - 0.2); if (currentUrl) loadFile(currentUrl); }); function loadFile(url) { const ext = (url.split('.').pop() || '').toLowerCase(); if (['pdf'].includes(ext)) { renderPDF(url); } else if (['jpg','jpeg','png','gif','webp'].includes(ext)) { renderImage(url); } else { toast('Format tidak disokong untuk preview', 'error'); } } // Render first page of PDF function renderPDF(url) { // ensure pdfjsLib exists if (typeof pdfjsLib === 'undefined') { console.error('pdfjsLib not found. Include PDF.js (non-module) before papar_dokumen.js'); return; } // disable workers to avoid CORS/worker issues, or set workerSrc if available if (pdfjsLib.GlobalWorkerOptions && !pdfjsLib.GlobalWorkerOptions.workerSrc) { // try use CDN worker (same version assumed) pdfjsLib.GlobalWorkerOptions.workerSrc = 'https://cdnjs.cloudflare.com/ajax/libs/pdf.js/2.16.105/pdf.worker.min.js'; } pdfjsLib.getDocument(url).promise.then(function (pdf) { return pdf.getPage(1).then(function (page) { const containerWidth = $container.width(); const viewport = page.getViewport({ scale: 1 }); const scale = (containerWidth / viewport.width) * zoom; const scaledViewport = page.getViewport({ scale: scale }); const outputScale = window.devicePixelRatio || 1; canvas.width = Math.floor(scaledViewport.width * outputScale); canvas.height = Math.floor(scaledViewport.height * outputScale); canvas.style.width = Math.floor(scaledViewport.width) + "px"; canvas.style.height = Math.floor(scaledViewport.height) + "px"; const renderContext = { canvasContext: ctx, viewport: scaledViewport, transform: [outputScale, 0, 0, outputScale, 0, 0], }; ctx.clearRect(0, 0, canvas.width, canvas.height); page.render(renderContext); }); }).catch(function (err) { console.error('Error rendering PDF', err); toast('Gagal memaparkan PDF.'); }); } // Render image to canvas, fit to container and support zoom function renderImage(url) { const img = new Image(); img.crossOrigin = 'anonymous'; img.onload = function () { const containerW = $container.width(); const containerH = $container.height(); const fitScale = Math.min(containerW / img.width, containerH / img.height); const finalW = Math.max(1, Math.floor(img.width * fitScale * zoom)); const finalH = Math.max(1, Math.floor(img.height * fitScale * zoom)); canvas.width = finalW; canvas.height = finalH; canvas.style.width = finalW + 'px'; canvas.style.height = finalH + 'px'; ctx.clearRect(0, 0, canvas.width, canvas.height); ctx.drawImage(img, 0, 0, finalW, finalH); }; img.onerror = function () { console.error('Error loading image', url); toast('Imej gagal dimuatkan.'); }; img.src = url; } function toast(msg, lvl = 'info') { if ($('#globalToast').length) { $('#globalToast .toast-body').text(msg); new bootstrap.Toast($('#globalToast')[0]).show(); } else { console[lvl === 'error' ? 'error' : 'log'](msg); } } }); })(jQuery, window, document);