document.addEventListener('DOMContentLoaded', () => { // --- Scroll-triggered Animations --- const observer = new IntersectionObserver((entries) => { entries.forEach(entry => { if (entry.isIntersecting) { entry.target.classList.add('visible'); } }); }, { threshold: 0.1 }); document.querySelectorAll('.animate-on-scroll').forEach(element => { observer.observe(element); }); // --- Form & API Logic --- const form = document.getElementById('analysis-form'); const analyzeBtn = document.getElementById('analyze-btn'); const loader = document.getElementById('loader'); const resultsContainer = document.getElementById('results-container'); const imageInput = document.getElementById('image-input'); const fileLabelText = document.getElementById('file-label-text'); imageInput.addEventListener('change', () => { if (imageInput.files.length > 0) { fileLabelText.textContent = `File selected: ${imageInput.files[0].name}`; } else { fileLabelText.textContent = 'Click to Upload an Image'; } }); form.addEventListener('submit', async (event) => { event.preventDefault(); const textInput = document.getElementById('text-input').value; const imageFile = imageInput.files[0]; if (!textInput.trim() && !imageFile) { alert("Please provide text or an image."); return; } loader.classList.remove('loader-hidden'); resultsContainer.innerHTML = ''; analyzeBtn.disabled = true; const formData = new FormData(); // Append data only if it exists to avoid sending empty fields if(textInput.trim()) formData.append('text_input', textInput); if(imageFile) formData.append('image_file', imageFile); try { // FIXED: Use the full, absolute URL for the API endpoint const response = await fetch('/analyze', { method: 'POST', body: formData }); const result = await response.json(); if (!response.ok) { throw new Error(result.detail || `HTTP error! Status: ${response.status}`); } // FIXED: Directly use the result object as it's the main data displayResults(result); } catch (error) { console.error('Analysis error:', error); resultsContainer.innerHTML = `
Error: ${error.message}
Verdict: ${report.final_verdict || 'N/A'}
Explanation: ${report.explanation || 'N/A'}
${sourcesHtml ? `ELA Analysis Image: View ELA Result
` : ''; card.innerHTML = `AI-Generated Score: ${report.ai_generated_score_percent?.toFixed(2) || '0.00'}%
Classic Edit Score (ELA): ${report.classic_edit_score_percent?.toFixed(2) || '0.00'}%
${elaLink} `; return card; } function createImageContentCard(report) { if (!report) return null; const card = document.createElement('div'); card.className = 'result-card animate-on-scroll fade-in'; let contentHtml = ''; if (report['Safe Search']) { const ss = report['Safe Search']; contentHtml += `Safe Search: Adult: ${ss.adult}, Violence: ${ss.violence}
`; } if (report['Identified Entities']) { contentHtml += `Identified Entities: ${report['Identified Entities'].join(', ')}
`; } card.innerHTML = `No specific content detected.
'} `; return card; } function createReverseImageSearchCard(report) { if (!report) return null; const card = document.createElement('div'); card.className = 'result-card animate-on-scroll fade-in'; let matchesHtml = 'No online matches found.
'; if (report['Reverse Image Matches'] && report['Reverse Image Matches'].length > 0) { matchesHtml = report['Reverse Image Matches'].map(match => `