/* ========================================================= DeepFake Detection System - script.js Upload tabs, drag & drop, preview, client validation, and the scanning overlay shown while the model runs. ========================================================= */ (function () { "use strict"; const IMAGE_ACCEPT = ".png,.jpg,.jpeg,.webp,.bmp"; const VIDEO_ACCEPT = ".mp4,.mov,.avi,.mkv,.webm"; const IMAGE_MAX_MB = 10; const VIDEO_MAX_MB = 100; const form = document.getElementById("detectForm"); if (!form) return; const mediaTypeInput = document.getElementById("mediaType"); const fileInput = document.getElementById("fileInput"); const dropzone = document.getElementById("dropzone"); const dzTitle = document.getElementById("dzTitle"); const dzSub = document.getElementById("dzSub"); const preview = document.getElementById("preview"); const previewImg = document.getElementById("previewImg"); const previewVideo = document.getElementById("previewVideo"); const previewName = document.getElementById("previewName"); const previewSize = document.getElementById("previewSize"); const removeBtn = document.getElementById("removeFile"); const overlay = document.getElementById("scanningOverlay"); const scanStatus = document.getElementById("scanStatus"); const detectBtn = document.getElementById("detectBtn"); let currentMaxMb = IMAGE_MAX_MB; /* ---------------- Tabs ---------------- */ document.querySelectorAll(".tab").forEach((tab) => { tab.addEventListener("click", () => { document.querySelectorAll(".tab").forEach((t) => { t.classList.remove("active"); t.setAttribute("aria-selected", "false"); }); tab.classList.add("active"); tab.setAttribute("aria-selected", "true"); const type = tab.dataset.type; mediaTypeInput.value = type; clearSelection(); if (type === "image") { fileInput.accept = IMAGE_ACCEPT; currentMaxMb = IMAGE_MAX_MB; dzTitle.textContent = "Drag & drop an image here"; dzSub.textContent = "PNG / JPG / WEBP / BMP \u00b7 max " + IMAGE_MAX_MB + " MB \u2014 or click to browse"; } else { fileInput.accept = VIDEO_ACCEPT; currentMaxMb = VIDEO_MAX_MB; dzTitle.textContent = "Drag & drop a video here"; dzSub.textContent = "MP4 / MOV / AVI / MKV / WEBM \u00b7 max " + VIDEO_MAX_MB + " MB \u2014 or click to browse"; } }); }); /* ---------------- Drag & drop ---------------- */ ["dragenter", "dragover"].forEach((evt) => { dropzone.addEventListener(evt, (e) => { e.preventDefault(); dropzone.classList.add("dragover"); }); }); ["dragleave", "drop"].forEach((evt) => { dropzone.addEventListener(evt, (e) => { e.preventDefault(); dropzone.classList.remove("dragover"); }); }); dropzone.addEventListener("drop", (e) => { if (e.dataTransfer && e.dataTransfer.files.length) { fileInput.files = e.dataTransfer.files; showPreview(fileInput.files[0]); } }); fileInput.addEventListener("change", () => { if (fileInput.files.length) showPreview(fileInput.files[0]); else clearPreview(); }); removeBtn.addEventListener("click", (e) => { e.preventDefault(); e.stopPropagation(); clearSelection(); }); function clearSelection() { fileInput.value = ""; clearPreview(); } function clearPreview() { preview.hidden = true; previewImg.hidden = true; previewVideo.hidden = true; previewImg.src = ""; previewVideo.pause(); previewVideo.src = ""; } function formatSize(bytes) { if (bytes >= 1024 * 1024) return (bytes / (1024 * 1024)).toFixed(1) + " MB"; return Math.max(1, Math.round(bytes / 1024)) + " KB"; } function showPreview(file) { clearPreview(); if (file.size > currentMaxMb * 1024 * 1024) { alert( 'File "' + file.name + '" is too large (' + formatSize(file.size) + "). The limit is " + currentMaxMb + " MB." ); clearSelection(); return; } previewName.textContent = file.name; previewSize.textContent = formatSize(file.size); const isImage = /\.(png|jpe?g|webp|bmp)$/i.test(file.name); const url = URL.createObjectURL(file); if (isImage) { previewImg.src = url; previewImg.hidden = false; } else { previewVideo.src = url; previewVideo.hidden = false; } preview.hidden = false; } /* ---------------- Scanning overlay on submit ---------------- */ const statusMessages = [ "Scanning for faces\u2026", "Extracting frames\u2026", "Running neural network\u2026", "Comparing against deepfake signatures\u2026", "Almost done\u2026" ]; let statusTimer = null; form.addEventListener("submit", (e) => { if (!fileInput.files.length) { e.preventDefault(); alert("Please choose a file to analyze first."); return; } detectBtn.disabled = true; overlay.hidden = false; let i = 0; scanStatus.textContent = statusMessages[0]; statusTimer = setInterval(() => { i = (i + 1) % statusMessages.length; scanStatus.textContent = statusMessages[i]; }, 1400); }); window.addEventListener("pageshow", () => { // Re-enable the UI if the user navigates back to this page. if (statusTimer) clearInterval(statusTimer); if (overlay) overlay.hidden = true; if (detectBtn) detectBtn.disabled = false; }); /* ---------------- Auto-dismiss flash messages ---------------- */ document.querySelectorAll(".flash").forEach((el) => { setTimeout(() => { el.style.transition = "opacity .5s ease"; el.style.opacity = "0"; setTimeout(() => el.remove(), 550); }, 6000); }); })();