Spaces:
Running
Running
| // Image to Image Generator Functionality | |
| document.addEventListener('DOMContentLoaded', function() { | |
| // Initialize image upload functionality | |
| const dropArea = document.getElementById('drop-area'); | |
| const fileInput = document.getElementById('file-input'); | |
| const uploadBtn = document.getElementById('upload-btn'); | |
| const previewContainer = document.getElementById('preview-container'); | |
| const previewImage = document.getElementById('preview-image'); | |
| const uploadContainer = document.getElementById('upload-container'); | |
| const removeImageBtn = document.getElementById('remove-image'); | |
| const generateBtn = document.getElementById('generate-btn'); | |
| const strengthSlider = document.getElementById('strength-slider'); | |
| const strengthValue = document.getElementById('strength-value'); | |
| const resultsGrid = document.getElementById('results-grid'); | |
| const generateText = document.getElementById('generate-text'); | |
| const loadingSpinner = document.getElementById('loading-spinner'); | |
| // Prevent default drag behaviors | |
| ['dragenter', 'dragover', 'dragleave', 'drop'].forEach(eventName => { | |
| dropArea.addEventListener(eventName, preventDefaults, false); | |
| }); | |
| function preventDefaults(e) { | |
| e.preventDefault(); | |
| e.stopPropagation(); | |
| } | |
| // Highlight drop area when item is dragged over it | |
| ['dragenter', 'dragover'].forEach(eventName => { | |
| dropArea.addEventListener(eventName, highlight, false); | |
| }); | |
| ['dragleave', 'drop'].forEach(eventName => { | |
| dropArea.addEventListener(eventName, unhighlight, false); | |
| }); | |
| function highlight() { | |
| dropArea.classList.add('border-secondary-pink', 'bg-tertiary-black'); | |
| } | |
| function unhighlight() { | |
| dropArea.classList.remove('border-secondary-pink', 'bg-tertiary-black'); | |
| } | |
| // Handle dropped files | |
| dropArea.addEventListener('drop', handleDrop, false); | |
| fileInput.addEventListener('change', handleFiles, false); | |
| uploadBtn.addEventListener('click', () => fileInput.click()); | |
| function handleDrop(e) { | |
| const dt = e.dataTransfer; | |
| const files = dt.files; | |
| handleFiles({ target: { files } }); | |
| } | |
| function handleFiles(e) { | |
| const files = e.target.files; | |
| if (files.length) { | |
| const file = files[0]; | |
| if (file.type.match('image.*')) { | |
| const reader = new FileReader(); | |
| reader.onload = function(e) { | |
| previewImage.src = e.target.result; | |
| uploadContainer.classList.add('hidden'); | |
| previewContainer.classList.remove('hidden'); | |
| }; | |
| reader.readAsDataURL(file); | |
| } | |
| } | |
| } | |
| // Remove image | |
| removeImageBtn.addEventListener('click', () => { | |
| previewImage.src = ''; | |
| fileInput.value = ''; | |
| uploadContainer.classList.remove('hidden'); | |
| previewContainer.classList.add('hidden'); | |
| }); | |
| // Update strength value display | |
| strengthSlider.addEventListener('input', () => { | |
| strengthValue.textContent = strengthSlider.value; | |
| }); | |
| // Generate variations | |
| generateBtn.addEventListener('click', async () => { | |
| if (!previewImage.src || previewImage.src === '') { | |
| alert('Please upload an image first'); | |
| return; | |
| } | |
| generateBtn.disabled = true; | |
| generateText.textContent = 'Generating...'; | |
| loadingSpinner.classList.remove('hidden'); | |
| try { | |
| // In a real implementation, you would call an AI API here | |
| // For demo purposes, we'll simulate API call with setTimeout | |
| setTimeout(() => { | |
| // Mock generated images | |
| const mockImages = [ | |
| 'http://static.photos/abstract/640x360/1', | |
| 'http://static.photos/abstract/640x360/2', | |
| 'http://static.photos/abstract/640x360/3', | |
| 'http://static.photos/abstract/640x360/4' | |
| ]; | |
| // Clear previous results | |
| resultsGrid.innerHTML = ''; | |
| // Add new results | |
| mockImages.forEach(imgSrc => { | |
| const imgContainer = document.createElement('div'); | |
| imgContainer.className = 'bg-secondary-black aspect-square rounded-lg overflow-hidden border border-tertiary-black'; | |
| imgContainer.innerHTML = ` | |
| <img src="${imgSrc}" class="w-full h-full object-cover" loading="lazy"> | |
| <div class="absolute bottom-0 left-0 right-0 bg-gradient-to-t from-black/80 to-transparent p-2"> | |
| <button class="text-white hover:text-primary-pink"> | |
| <i data-feather="download"></i> | |
| </button> | |
| </div> | |
| `; | |
| resultsGrid.appendChild(imgContainer); | |
| }); | |
| feather.replace(); | |
| }, 2000); | |
| } catch (error) { | |
| console.error('Error generating variations:', error); | |
| alert('Error generating variations. Please try again.'); | |
| } finally { | |
| generateBtn.disabled = false; | |
| generateText.textContent = 'Generate Variations'; | |
| loadingSpinner.classList.add('hidden'); | |
| } | |
| }); | |
| // Initialize community feed data with loading states | |
| const communityPosts = [ | |
| { | |
| id: 1, | |
| user: 'AI_Artist_42', | |
| avatar: 'http://static.photos/people/200x200/1', | |
| image: 'http://static.photos/abstract/640x360/1', | |
| prompt: 'Cyberpunk city at night with neon lights', | |
| likes: 142, | |
| timestamp: '2 hours ago' | |
| }, | |
| { | |
| id: 2, | |
| user: 'DigitalDreamer', | |
| avatar: 'http://static.photos/people/200x200/2', | |
| image: 'http://static.photos/abstract/640x360/2', | |
| prompt: 'Surreal landscape with floating islands', | |
| likes: 89, | |
| timestamp: '5 hours ago' | |
| }, | |
| { | |
| id: 3, | |
| user: 'PixelPioneer', | |
| avatar: 'http://static.photos/people/200x200/3', | |
| image: 'http://static.photos/abstract/640x360/3', | |
| prompt: 'Portrait of a robot with human emotions', | |
| likes: 217, | |
| timestamp: '1 day ago' | |
| } | |
| ]; | |
| // Enhanced render community feed with error handling | |
| function renderCommunityFeed() { | |
| const feedContainer = document.getElementById('community-feed'); | |
| feedContainer.innerHTML = ''; | |
| communityPosts.forEach(post => { | |
| const postElement = document.createElement('div'); | |
| postElement.className = 'bg-tertiary-black rounded-lg overflow-hidden shadow-lg transition-transform hover:scale-105'; | |
| postElement.innerHTML = ` | |
| <div class="relative"> | |
| <img src="${post.image}" alt="${post.prompt}" class="w-full h-64 object-cover"> | |
| <div class="absolute bottom-0 left-0 right-0 bg-gradient-to-t from-black/80 to-transparent p-4"> | |
| <p class="text-white font-medium">${post.prompt}</p> | |
| </div> | |
| </div> | |
| <div class="p-4"> | |
| <div class="flex items-center gap-3 mb-3"> | |
| <img src="${post.avatar}" alt="${post.user}" class="w-10 h-10 rounded-full"> | |
| <div> | |
| <p class="font-medium text-white">${post.user}</p> | |
| <p class="text-xs text-gray-400">${post.timestamp}</p> | |
| </div> | |
| </div> | |
| <div class="flex justify-between items-center"> | |
| <button class="flex items-center gap-1 text-primary-pink"> | |
| <i data-feather="heart"></i> | |
| <span>${post.likes}</span> | |
| </button> | |
| <button class="text-gray-400 hover:text-white"> | |
| <i data-feather="share-2"></i> | |
| </button> | |
| </div> | |
| </div> | |
| `; | |
| feedContainer.appendChild(postElement); | |
| }); | |
| feather.replace(); | |
| } | |
| document.addEventListener('DOMContentLoaded', function() { | |
| // Initialize accessibility features | |
| initAccessibility(); | |
| // Initialize community feed with loading state | |
| document.getElementById('community-feed').innerHTML = ` | |
| <div class="col-span-full text-center py-12"> | |
| <div class="inline-block animate-spin rounded-full h-8 w-8 border-t-2 border-b-2 border-primary-pink"></div> | |
| <p class="mt-2 text-gray-400">Loading community creations...</p> | |
| </div> | |
| `; | |
| renderCommunityFeed(); | |
| // Enhanced tab functionality with keyboard navigation | |
| const tabs = document.querySelectorAll('[role="tab"]'); | |
| const tabPanels = document.querySelectorAll('[role="tabpanel"]'); | |
| tabs.forEach(tab => { | |
| tab.addEventListener('click', function() { | |
| // Hide all tab panels | |
| tabPanels.forEach(panel => { | |
| panel.classList.add('hidden'); | |
| }); | |
| // Deactivate all tabs | |
| tabs.forEach(t => { | |
| t.setAttribute('aria-selected', 'false'); | |
| t.classList.remove('border-primary-500', 'text-primary-500', 'dark:border-primary |