/* ========================================================================= Bangla Text Analyzer — frontend logic ========================================================================= */ const $ = (sel) => document.querySelector(sel); const textInput = $("#text-input"); const dropZone = $("#drop-zone"); const fileInput = $("#file-input"); const fileBtn = $("#file-btn"); const fileName = $("#file-name"); const charCount = $("#char-count"); const taskSelect = $("#task-select"); const modelWrap = $("#model-wrap"); const modelSelect = $("#model-select"); const runBtn = $("#run-btn"); const outputBody = $("#output-body"); const outputDot = $(".output-head__dot"); // Holds a dropped/selected file so we can send it instead of textarea text. let pendingFile = null; /* ---------------- character counter ---------------- */ function updateCount() { const n = textInput.value.length; charCount.textContent = `${n.toLocaleString("bn-BD")} অক্ষর`; } textInput.addEventListener("input", () => { // If the user types, we abandon any previously attached file. if (pendingFile && textInput.value.trim()) clearFile(); updateCount(); }); /* ---------------- file handling ---------------- */ function clearFile() { pendingFile = null; fileName.textContent = ""; fileInput.value = ""; } function attachFile(file) { pendingFile = file; fileName.textContent = "📎 " + file.name; // Show a preview of the file's text in the textarea. const reader = new FileReader(); reader.onload = (e) => { textInput.value = e.target.result; updateCount(); }; reader.readAsText(file, "utf-8"); } fileBtn.addEventListener("click", () => fileInput.click()); fileInput.addEventListener("change", (e) => { if (e.target.files.length) attachFile(e.target.files[0]); }); // Drag & drop onto the text area. ["dragenter", "dragover"].forEach((evt) => dropZone.addEventListener(evt, (e) => { e.preventDefault(); dropZone.classList.add("dragover"); }) ); ["dragleave", "drop"].forEach((evt) => dropZone.addEventListener(evt, (e) => { e.preventDefault(); if (evt === "dragleave" && dropZone.contains(e.relatedTarget)) return; dropZone.classList.remove("dragover"); }) ); dropZone.addEventListener("drop", (e) => { const file = e.dataTransfer.files[0]; if (file) attachFile(file); }); /* ---------------- running analysis ---------------- */ async function analyze() { const task = taskSelect.value; const text = textInput.value.trim(); // Only the hate-speech task offers a model choice; default otherwise. const model = task === "hate_speech" ? modelSelect.value : "banglabert"; if (!text) { renderError("দয়া করে কিছু টেক্সট লিখুন বা একটি ফাইল দিন।"); return; } setLoading(true); try { let response; if (pendingFile) { // Send the raw file via multipart form-data. const fd = new FormData(); fd.append("file", pendingFile); fd.append("task", task); fd.append("model", model); response = await fetch("/analyze", { method: "POST", body: fd }); } else { // Send typed text as JSON. response = await fetch("/analyze", { method: "POST", headers: { "Content-Type": "application/json" }, body: JSON.stringify({ text, task, model }), }); } const data = await response.json(); if (!response.ok) { renderError(data.error || "একটি ত্রুটি ঘটেছে।"); } else { renderResult(data); } } catch (err) { renderError("সার্ভারের সাথে সংযোগ ব্যর্থ হয়েছে: " + err.message); } finally { setLoading(false); } } function setLoading(on) { runBtn.disabled = on; outputDot.classList.toggle("live", on); if (on) { outputBody.className = "output-body"; outputBody.innerHTML = ' বিশ্লেষণ চলছে…'; } } /* ---------------- rendering ---------------- */ function renderError(msg) { outputBody.className = "output-body"; outputBody.innerHTML = `