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}

`; } finally { loader.classList.add('loader-hidden'); analyzeBtn.disabled = false; } }); // --- Dynamic Result Display Function --- function displayResults(data) { resultsContainer.innerHTML = ''; let delay = 0; // This function creates a new card and adds it to the DOM with a delay const addCard = (card) => { if(card) { resultsContainer.appendChild(card); setTimeout(() => card.classList.add('visible'), delay); delay += 200; } }; // Handle different report types if (data.final_verdict) { // Text-only report addCard(createTextCard(data)); } else { // Image report (which can contain text analysis) addCard(createImageManipulationCard(data.image_manipulation_report)); addCard(createReverseImageSearchCard(data.reverse_image_search_report)); addCard(createImageContentCard(data.in_image_content_report)); if (data.extracted_text_analysis_report && data.extracted_text_analysis_report.final_verdict) { addCard(createExtractedTextCard(data.extracted_text_analysis_report)); } } } // --- Helper functions to create HTML for each card --- function createTextCard(report) { if (!report) return null; const card = document.createElement('div'); card.className = 'result-card animate-on-scroll fade-in'; let sourcesHtml = ''; if (report.source && Object.keys(report.source).length > 0) { sourcesHtml = Object.entries(report.source).map(([source, url]) => `
${source}
${url}
` ).join(''); } card.innerHTML = `

Text Analysis Report

Verdict: ${report.final_verdict || 'N/A'}

Explanation: ${report.explanation || 'N/A'}

${sourcesHtml ? `

Sources:

${sourcesHtml}
` : ''} `; return card; } function createImageManipulationCard(report) { if (!report) return null; const card = document.createElement('div'); card.className = 'result-card animate-on-scroll fade-in'; // FIXED: Use the correct path for the ELA image const elaLink = report.ela_image_path ? `

ELA Analysis Image: View ELA Result

` : ''; card.innerHTML = `

Image Manipulation Analysis

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 = `

Image Content Analysis

${contentHtml || '

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 => `
${match.title}
${match.url}
` ).join(''); } card.innerHTML = `

Reverse Image Search

${matchesHtml} `; return card; } function createExtractedTextCard(report) { if (!report) return null; // Re-use the text card creation logic const card = createTextCard(report); card.querySelector('h3').innerHTML = ` Extracted Text Analysis`; return card; } });