Spaces:
Sleeping
Sleeping
| document.addEventListener('DOMContentLoaded', () => { | |
| // Starry Background Animation | |
| const stars = document.createElement('canvas'); | |
| stars.className = 'stars'; | |
| document.body.appendChild(stars); | |
| const ctx = stars.getContext('2d'); | |
| stars.width = window.innerWidth; | |
| stars.height = window.innerHeight; | |
| const starArray = []; | |
| for (let i = 0; i < 100; i++) { | |
| starArray.push({ | |
| x: Math.random() * stars.width, | |
| y: Math.random() * stars.height, | |
| radius: Math.random() * 2, | |
| opacity: Math.random() | |
| }); | |
| } | |
| function animateStars() { | |
| ctx.clearRect(0, 0, stars.width, stars.height); | |
| starArray.forEach(star => { | |
| ctx.beginPath(); | |
| ctx.arc(star.x, star.y, star.radius, 0, Math.PI * 2); | |
| ctx.fillStyle = `rgba(255, 255, 255, ${star.opacity})`; | |
| ctx.fill(); | |
| star.opacity += (Math.random() - 0.5) * 0.05; | |
| if (star.opacity > 1) star.opacity = 1; | |
| if (star.opacity < 0) star.opacity = 0; | |
| }); | |
| requestAnimationFrame(animateStars); | |
| } | |
| animateStars(); | |
| // Card Hover Effects | |
| const cards = document.querySelectorAll(".card"); | |
| cards.forEach(card => { | |
| card.addEventListener("mouseenter", () => { | |
| if (!card.classList.contains('shadowed')) { | |
| card.style.transition = "transform 0.4s ease-in-out"; | |
| card.style.transform = "scale(1.05) rotate(0.5deg)"; | |
| } | |
| }); | |
| card.addEventListener("mouseleave", () => { | |
| if (!card.classList.contains('shadowed')) { | |
| card.style.transform = "scale(1) rotate(0deg)"; | |
| } | |
| }); | |
| }); | |
| // Window Resize Handler for Canvas | |
| window.addEventListener('resize', () => { | |
| stars.width = window.innerWidth; | |
| stars.height = window.innerHeight; | |
| starArray.length = 0; | |
| for (let i = 0; i < 100; i++) { | |
| starArray.push({ | |
| x: Math.random() * stars.width, | |
| y: Math.random() * stars.height, | |
| radius: Math.random() * 2, | |
| opacity: Math.random() | |
| }); | |
| } | |
| }); | |
| // Box Click to Open Modal | |
| document.querySelectorAll('.function-box').forEach(box => { | |
| box.addEventListener('click', () => { | |
| const modalId = box.dataset.modal; | |
| const modal = document.getElementById(modalId); | |
| if (modal) { | |
| modal.classList.remove('hidden'); | |
| document.querySelectorAll('.function-box').forEach(otherBox => { | |
| if (otherBox !== box) { | |
| otherBox.classList.add('shadowed'); | |
| } | |
| }); | |
| } | |
| }); | |
| }); | |
| // Chatbot Icon Click | |
| const chatbotIcon = document.querySelector('.chatbot-icon'); | |
| if (chatbotIcon) { | |
| chatbotIcon.addEventListener('click', () => { | |
| const chatbotModal = document.getElementById('chatbot-modal'); | |
| if (chatbotModal) { | |
| chatbotModal.classList.remove('hidden'); | |
| } | |
| }); | |
| } | |
| // Close Modal | |
| document.querySelectorAll('.close-modal').forEach(closeBtn => { | |
| closeBtn.addEventListener('click', () => { | |
| const modal = closeBtn.closest('.modal'); | |
| modal.classList.add('hidden'); | |
| const forms = modal.querySelectorAll('form'); | |
| forms.forEach(form => form.reset()); | |
| const responseCards = modal.querySelectorAll('.response-card'); | |
| responseCards.forEach(card => { | |
| card.classList.add('hidden'); | |
| card.innerHTML = ''; | |
| }); | |
| const spinners = modal.querySelectorAll('.loading-spinner'); | |
| spinners.forEach(spinner => spinner.classList.add('hidden')); | |
| const dropAreas = modal.querySelectorAll('.drop-area p'); | |
| dropAreas.forEach(p => p.textContent = 'Drop File Here or Click to Choose'); | |
| if (modal.id === 'chatbot-modal') { | |
| const conversation = document.getElementById('chatbot-conversation'); | |
| if (conversation) { | |
| conversation.innerHTML = ''; | |
| } | |
| } | |
| document.querySelectorAll('.function-box').forEach(box => { | |
| box.classList.remove('shadowed'); | |
| }); | |
| }); | |
| }); | |
| // Tab Switching for Summarize and Translate | |
| document.querySelectorAll('.tab-btn').forEach(btn => { | |
| btn.addEventListener('click', () => { | |
| const tab = btn.dataset.tab; | |
| const modal = btn.closest('.modal'); | |
| modal.querySelectorAll('.tab-btn').forEach(b => b.classList.remove('active')); | |
| btn.classList.add('active'); | |
| modal.querySelectorAll('.tab-content').forEach(content => { | |
| content.classList.add('hidden'); | |
| if (content.dataset.tab === tab) content.classList.remove('hidden'); | |
| }); | |
| }); | |
| }); | |
| // File Drop Handler | |
| window.handleDrop = function(event, dropArea) { | |
| event.preventDefault(); | |
| const fileInput = dropArea.querySelector('input[type="file"]'); | |
| const files = event.dataTransfer.files; | |
| if (files.length > 0) { | |
| fileInput.files = files; | |
| dropArea.querySelector('p').textContent = `Selected: ${files[0].name}`; | |
| } | |
| }; | |
| // File Input Click Handler | |
| document.querySelectorAll('.drop-area').forEach(dropArea => { | |
| const fileInput = dropArea.querySelector('input[type="file"]'); | |
| dropArea.addEventListener('click', () => { | |
| fileInput.click(); | |
| }); | |
| fileInput.addEventListener('change', () => { | |
| if (fileInput.files.length > 0) { | |
| dropArea.querySelector('p').textContent = `Selected: ${fileInput.files[0].name}`; | |
| } | |
| }); | |
| }); | |
| // Chatbot Form Submission | |
| const chatbotForm = document.getElementById('chatbot-form'); | |
| if (chatbotForm) { | |
| chatbotForm.addEventListener('submit', async (e) => { | |
| e.preventDefault(); | |
| const input = e.target.querySelector('input'); | |
| const message = input.value.trim(); | |
| const spinner = e.target.querySelector('.loading-spinner') || document.createElement('div'); | |
| if (!spinner.classList.contains('loading-spinner')) { | |
| spinner.className = 'loading-spinner'; | |
| spinner.innerHTML = '<span>Processing...</span>'; | |
| e.target.appendChild(spinner); | |
| } | |
| if (!message) return; | |
| spinner.classList.remove('hidden'); | |
| const conversation = document.getElementById('chatbot-conversation'); | |
| conversation.innerHTML += `<p class="user-message">You: ${message}</p>`; | |
| conversation.scrollTop = conversation.scrollHeight; | |
| input.value = ''; | |
| try { | |
| const response = await fetch('/chat', { | |
| method: 'POST', | |
| headers: { 'Content-Type': 'application/json' }, | |
| body: JSON.stringify({ message }) | |
| }); | |
| const data = await response.json(); | |
| spinner.classList.add('hidden'); | |
| if (response.ok) { | |
| conversation.innerHTML += `<p class="bot-message">Gemini: ${data.response}</p>`; | |
| } else { | |
| conversation.innerHTML += `<p class="bot-message">Error: ${data.detail || 'Unknown error'}</p>`; | |
| } | |
| conversation.scrollTop = conversation.scrollHeight; | |
| } catch (error) { | |
| spinner.classList.add('hidden'); | |
| conversation.innerHTML += `<p class="bot-message">Error: ${error.message}</p>`; | |
| conversation.scrollTop = conversation.scrollHeight; | |
| } | |
| }); | |
| } | |
| // Form Submissions for Other Functionalities | |
| const forms = { | |
| 'summarize-form': { endpoint: '/process', intent: 'summarize' }, | |
| 'summarize-file-form': { endpoint: '/process', intent: 'summarize' }, | |
| 'translate-text-form': { endpoint: '/process', intent: 'translate' }, | |
| 'translate-file-form': { endpoint: '/process', intent: 'file-translate' }, | |
| 'file-qa-form': { endpoint: '/process', intent: 'file-qa' }, | |
| 'image-caption-form': { endpoint: '/process', intent: 'image-to-text' }, | |
| 'visual-qa-form': { endpoint: '/process', intent: 'visual-qa' }, | |
| 'visualize-form': { endpoint: '/process', intent: 'visualize' } | |
| }; | |
| Object.keys(forms).forEach(formId => { | |
| const form = document.getElementById(formId); | |
| if (!form) return; | |
| form.addEventListener('submit', async (e) => { | |
| e.preventDefault(); | |
| const formData = new FormData(); | |
| const responseCard = form.nextElementSibling; | |
| let spinner = form.querySelector('.loading-spinner'); | |
| if (!spinner) { | |
| spinner = document.createElement('div'); | |
| spinner.className = 'loading-spinner hidden'; | |
| spinner.innerHTML = '<span>Processing...</span>'; | |
| form.appendChild(spinner); | |
| } | |
| // Collect form data | |
| const textInput = form.querySelector('textarea, input[type="text"]'); | |
| const fileInput = form.querySelector('input[type="file"]'); | |
| const languageSelect = form.querySelector('select[name="language"]'); | |
| const visualizationSelect = form.querySelector('select[name="visualization-type"]'); | |
| let textValue = textInput && textInput.value.trim() ? textInput.value.trim() : ''; | |
| if (languageSelect && textValue && (formId === 'translate-text-form' || formId === 'translate-file-form')) { | |
| textValue = `Translate to ${languageSelect.value}: ${textValue}`; | |
| } | |
| if (textValue) { | |
| formData.append('text', textValue); | |
| } | |
| if (fileInput && fileInput.files.length > 0) { | |
| formData.append('file', fileInput.files[0]); | |
| } | |
| if (visualizationSelect) { | |
| formData.append('text', visualizationSelect.value); | |
| } | |
| // Validate input | |
| if (!textValue && (!fileInput || fileInput.files.length === 0)) { | |
| responseCard.classList.remove('hidden'); | |
| responseCard.innerHTML = '<p class="error">Please provide text or a file.</p>'; | |
| return; | |
| } | |
| spinner.classList.remove('hidden'); | |
| responseCard.classList.add('hidden'); | |
| responseCard.innerHTML = ''; | |
| // Display uploaded image locally for caption and visual QA | |
| let localImageUrl = ''; | |
| if (fileInput && fileInput.files.length > 0 && (formId === 'image-caption-form' || formId === 'visual-qa-form')) { | |
| const file = fileInput.files[0]; | |
| localImageUrl = await new Promise(resolve => { | |
| const reader = new FileReader(); | |
| reader.onload = () => resolve(reader.result); | |
| reader.readAsDataURL(file); | |
| }); | |
| } | |
| try { | |
| const response = await fetch(forms[formId].endpoint, { | |
| method: 'POST', | |
| body: formData | |
| }); | |
| const data = await response.json(); | |
| spinner.classList.add('hidden'); | |
| responseCard.classList.remove('hidden'); | |
| if (response.ok) { | |
| let responseText = data.response; | |
| if (data.type === 'visualization_code') { | |
| responseText = `<pre>${responseText}</pre>`; | |
| } else if (data.type === 'caption' || data.type === 'visual_qa') { | |
| responseText = `${responseText}<br><img src="${localImageUrl}" alt="Uploaded Image" style="max-width: 100%; margin-top: 10px;">`; | |
| } else if (data.type === 'file_qa' || data.type === 'file_translation') { | |
| responseText = `${responseText}<br><small>File: ${data.additional_data.file_name}</small>`; | |
| } | |
| responseCard.innerHTML = `<p>${responseText}</p>`; | |
| if (data.message) { | |
| responseCard.innerHTML += `<p><small>${data.message}</small></p>`; | |
| } | |
| } else { | |
| responseCard.innerHTML = `<p class="error">Error: ${data.detail || 'Unknown error'}</p>`; | |
| } | |
| } catch (error) { | |
| spinner.classList.add('hidden'); | |
| responseCard.classList.remove('hidden'); | |
| responseCard.innerHTML = `<p class="error">Error: ${error.message}</p>`; | |
| } | |
| }); | |
| }); | |
| }); |