Web-ai-app / static /scripts.js
Hadiil's picture
Update static/scripts.js
df3a4ea verified
raw
history blame
13 kB
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>`;
}
});
});
});