// Wait for the DOM to be fully loaded document.addEventListener('DOMContentLoaded', function() { // Configure marked.js marked.setOptions({ breaks: true, gfm: true, smartLists: true }); // API key storage in localStorage const API_KEY_STORAGE_KEY = 'grok2_api_key'; const apiKeyInput = document.getElementById('api-key-input'); const saveApiKeyBtn = document.getElementById('save-api-key'); const clearApiKeyBtn = document.getElementById('clear-api-key'); const apiKeyStatus = document.getElementById('api-key-status'); // Navigation const navLinks = document.querySelectorAll('nav ul li a'); const sections = document.querySelectorAll('.section'); // Image Generation const imagePromptInput = document.getElementById('image-prompt'); const generateImageBtn = document.getElementById('generate-image'); const imageResult = document.getElementById('image-result'); const generationStatus = document.getElementById('generation-status'); // Vision Analysis const uploadArea = document.getElementById('upload-area'); const imageUploadInput = document.getElementById('image-upload'); const visionPromptInput = document.getElementById('vision-prompt'); const analyzeImageBtn = document.getElementById('analyze-image'); const uploadedImageContainer = document.getElementById('uploaded-image'); const visionResult = document.getElementById('vision-result'); const visionStatus = document.getElementById('vision-status'); let uploadedImage = null; // Check if API key is stored on load checkStoredApiKey(); // API Key Management function checkStoredApiKey() { const storedApiKey = localStorage.getItem(API_KEY_STORAGE_KEY); if (storedApiKey) { apiKeyStatus.textContent = '✅ API key is stored'; apiKeyStatus.style.color = '#27ae60'; // Mask the input for security apiKeyInput.value = '•'.repeat(12); } else { apiKeyStatus.textContent = '❌ No API key stored'; apiKeyStatus.style.color = '#e74c3c'; apiKeyInput.value = ''; } } saveApiKeyBtn.addEventListener('click', function() { const apiKey = apiKeyInput.value.trim(); if (apiKey && apiKey !== '•'.repeat(12)) { localStorage.setItem(API_KEY_STORAGE_KEY, apiKey); apiKeyStatus.textContent = '✅ API key saved successfully'; apiKeyStatus.style.color = '#27ae60'; // Mask the input for security apiKeyInput.value = '•'.repeat(12); } else if (apiKey === '•'.repeat(12)) { apiKeyStatus.textContent = '❓ Please enter a new API key'; apiKeyStatus.style.color = '#f39c12'; } else { apiKeyStatus.textContent = '❌ Please enter a valid API key'; apiKeyStatus.style.color = '#e74c3c'; } }); clearApiKeyBtn.addEventListener('click', function() { localStorage.removeItem(API_KEY_STORAGE_KEY); apiKeyInput.value = ''; apiKeyStatus.textContent = '🗑️ API key cleared'; apiKeyStatus.style.color = '#e74c3c'; }); // Navigation between sections navLinks.forEach(link => { link.addEventListener('click', function(e) { e.preventDefault(); // Remove active class from all links and add to current navLinks.forEach(l => l.classList.remove('active')); this.classList.add('active'); // Show the selected section const targetSection = this.getAttribute('data-section'); sections.forEach(section => { section.classList.remove('active'); if (section.id === targetSection) { section.classList.add('active'); } }); }); }); // Image Upload Handling uploadArea.addEventListener('click', function() { imageUploadInput.click(); }); uploadArea.addEventListener('dragover', function(e) { e.preventDefault(); this.classList.add('dragover'); }); uploadArea.addEventListener('dragleave', function() { this.classList.remove('dragover'); }); uploadArea.addEventListener('drop', function(e) { e.preventDefault(); this.classList.remove('dragover'); if (e.dataTransfer.files && e.dataTransfer.files[0]) { handleImageUpload(e.dataTransfer.files[0]); } }); imageUploadInput.addEventListener('change', function() { if (this.files && this.files[0]) { handleImageUpload(this.files[0]); } }); function handleImageUpload(file) { if (!file.type.match('image.*')) { visionStatus.textContent = '❌ Please upload an image file'; return; } const reader = new FileReader(); reader.onload = function(e) { const img = document.createElement('img'); img.src = e.target.result; uploadedImageContainer.innerHTML = ''; uploadedImageContainer.appendChild(img); uploadedImage = file; analyzeImageBtn.disabled = false; visionStatus.textContent = '✅ Image uploaded successfully'; }; reader.readAsDataURL(file); } // Image Generation generateImageBtn.addEventListener('click', function() { const prompt = imagePromptInput.value.trim(); if (!prompt) { generationStatus.textContent = '❌ Please enter a prompt'; return; } const apiKey = localStorage.getItem(API_KEY_STORAGE_KEY); if (!apiKey) { generationStatus.textContent = '❌ API key is required. Please add your API key in the API Key section.'; return; } // Show loading state generationStatus.innerHTML = ' Generating image...'; generateImageBtn.disabled = true; imageResult.innerHTML = ''; // Call the backend API with OpenAI-style format fetch('/api/generate-image', { method: 'POST', headers: { 'Content-Type': 'application/json' }, body: JSON.stringify({ api_key: apiKey, prompt: prompt, use_openai_format: true }) }) .then(response => { if (!response.ok) { return response.json().then(err => { throw err; }); } return response.json(); }) .then(data => { if (data.image_url) { // Display the generated image let imageHTML = `Generated image`; // Add caption if available if (data.caption) { imageHTML += `
${data.caption}
`; } imageResult.innerHTML = imageHTML; generationStatus.textContent = '✅ Image generated successfully'; } else { throw new Error('No image URL in response'); } }) .catch(error => { generationStatus.textContent = `❌ Error: ${error.error || error.message || 'Unknown error'}`; console.error('Image generation error:', error); }) .finally(() => { generateImageBtn.disabled = false; }); }); // Vision Analysis analyzeImageBtn.addEventListener('click', function() { if (!uploadedImage) { visionStatus.textContent = '❌ Please upload an image first'; return; } const prompt = visionPromptInput.value.trim() || 'Describe this image in detail'; const apiKey = localStorage.getItem(API_KEY_STORAGE_KEY); if (!apiKey) { visionStatus.textContent = '❌ API key is required. Please add your API key in the API Key section.'; return; } // Show loading state visionStatus.innerHTML = ' Analyzing image...'; analyzeImageBtn.disabled = true; visionResult.textContent = ''; // Create form data for file upload const formData = new FormData(); formData.append('image', uploadedImage); formData.append('api_key', apiKey); formData.append('prompt', prompt); // Call the backend API fetch('/api/analyze-image', { method: 'POST', body: formData }) .then(response => { if (!response.ok) { return response.json().then(err => { throw err; }); } return response.json(); }) .then(data => { if (data.analysis) { // Display the analysis result with Markdown support visionResult.innerHTML = marked.parse(data.analysis); visionStatus.textContent = '✅ Analysis completed'; } else { throw new Error('No analysis in response'); } }) .catch(error => { visionStatus.textContent = `❌ Error: ${error.error || error.message || 'Unknown error'}`; console.error('Vision analysis error:', error); }) .finally(() => { analyzeImageBtn.disabled = false; }); }); });