Download script.js from VibeCodingStudio/deepsite-project-9illa: direct link, hf CLI and curl.
- Browser
- Download file 17.9 kB
-
https://huggingface.co/spaces/VibeCodingStudio/deepsite-project-9illa/resolve/main/script.js
- Command line
-
hf download hf://spaces/VibeCodingStudio/deepsite-project-9illa/script.js
-
curl -L -o script.js https://huggingface.co/spaces/VibeCodingStudio/deepsite-project-9illa/resolve/main/script.js
17.9 kB
| // Art Gallery Data | |
| const artworks = [ | |
| { | |
| id: 1, | |
| title: "Cyberpunk City Nights", | |
| artist: "NeonDreamer", | |
| category: "digital", | |
| image: "https://static.photos/technology/640x480/1", | |
| avatar: "https://static.photos/people/200x200/1", | |
| likes: 2453, | |
| views: "12.5K", | |
| comments: 89, | |
| description: "A futuristic cityscape inspired by Blade Runner and cyberpunk aesthetics. Created in Blender and Photoshop over 3 weeks.", | |
| tags: ["cyberpunk", "cityscape", "digital", "scifi"] | |
| }, | |
| { | |
| id: 2, | |
| title: "Ethereal Forest Spirit", | |
| artist: "MysticArt", | |
| category: "digital", | |
| image: "https://static.photos/nature/640x360/2", | |
| avatar: "https://static.photos/people/200x200/2", | |
| likes: 1892, | |
| views: "8.2K", | |
| comments: 56, | |
| description: "Digital painting of an ancient forest guardian. Exploring light and atmosphere in fantasy environments.", | |
| tags: ["fantasy", "forest", "spirit", "digitalpainting"] | |
| }, | |
| { | |
| id: 3, | |
| title: "Portrait Study #42", | |
| artist: "ArtStudent_99", | |
| category: "traditional", | |
| image: "https://static.photos/people/640x480/3", | |
| avatar: "https://static.photos/people/200x200/3", | |
| likes: 567, | |
| views: "2.1K", | |
| comments: 23, | |
| description: "Oil on canvas. 40x50cm. Working on skin tones and lighting from natural window light.", | |
| tags: ["oilpainting", "portrait", "traditional", "study"] | |
| }, | |
| { | |
| id: 4, | |
| title: "Abstract Emotions", | |
| artist: "ColorSplash", | |
| category: "digital", | |
| image: "https://static.photos/abstract/640x360/4", | |
| avatar: "https://static.photos/people/200x200/4", | |
| likes: 3201, | |
| views: "15K", | |
| comments: 134, | |
| description: "Exploring the relationship between color and emotion. Digital abstract composition using custom brushes.", | |
| tags: ["abstract", "colors", "emotional", "digital"] | |
| }, | |
| { | |
| id: 5, | |
| title: "Mountain Mist", | |
| artist: "NatureLens", | |
| category: "photography", | |
| image: "https://static.photos/nature/640x480/5", | |
| avatar: "https://static.photos/people/200x200/5", | |
| likes: 892, | |
| views: "4.5K", | |
| comments: 45, | |
| description: "Early morning shot in the Alps. Sony A7III with 24-70mm lens. f/8, 1/125s, ISO 100.", | |
| tags: ["photography", "landscape", "mountains", "nature"] | |
| }, | |
| { | |
| id: 6, | |
| title: "Mecha Warrior", | |
| artist: "RobotDesigner", | |
| category: "3d", | |
| image: "https://static.photos/technology/640x360/6", | |
| avatar: "https://static.photos/people/200x200/6", | |
| likes: 4521, | |
| views: "22K", | |
| comments: 201, | |
| description: "Hard surface modeling practice. Rendered in Octane. Concept inspired by Gundam and Pacific Rim.", | |
| tags: ["3d", "mecha", "robot", "scifi", "blender"] | |
| }, | |
| { | |
| id: 7, | |
| title: "Cherry Blossom Dreams", | |
| artist: "SakuraArtist", | |
| category: "anime", | |
| image: "https://static.photos/nature/640x480/7", | |
| avatar: "https://static.photos/people/200x200/7", | |
| likes: 5678, | |
| views: "28K", | |
| comments: 312, | |
| description: "Original character illustration. Clip Studio Paint. Focusing on soft lighting and spring atmosphere.", | |
| tags: ["anime", "manga", "illustration", "sakura"] | |
| }, | |
| { | |
| id: 8, | |
| title: "Urban Decay", | |
| artist: "StreetWalker", | |
| category: "photography", | |
| image: "https://static.photos/cityscape/640x360/8", | |
| avatar: "https://static.photos/people/200x200/8", | |
| likes: 1234, | |
| views: "6.7K", | |
| comments: 78, | |
| description: "Abandoned factory exploration. High contrast black and white processing to emphasize texture.", | |
| tags: ["urban", "abandoned", "blackwhite", "photography"] | |
| }, | |
| { | |
| id: 9, | |
| title: "Dragon's Lair", | |
| artist: "FantasyMaster", | |
| category: "digital", | |
| image: "https://static.photos/abstract/640x480/9", | |
| avatar: "https://static.photos/people/200x200/9", | |
| likes: 3892, | |
| views: "18K", | |
| comments: 156, | |
| description: "Epic fantasy scene. Photoshop and Wacom Cintiq. 40+ hours of work on the scales alone!", | |
| tags: ["dragon", "fantasy", "epic", "creature"] | |
| }, | |
| { | |
| id: 10, | |
| title: "Minimalist Architecture", | |
| artist: "CleanLines", | |
| category: "photography", | |
| image: "https://static.photos/minimal/640x360/10", | |
| avatar: "https://static.photos/people/200x200/10", | |
| likes: 2156, | |
| views: "9.3K", | |
| comments: 67, | |
| description: "Geometry in modern architecture. Shot in Tokyo. Minimal post-processing to maintain clean lines.", | |
| tags: ["architecture", "minimal", "geometry", "modern"] | |
| }, | |
| { | |
| id: 11, | |
| title: "Space Station Omega", | |
| artist: "StarTraveler", | |
| category: "3d", | |
| image: "https://static.photos/technology/640x480/11", | |
| avatar: "https://static.photos/people/200x200/11", | |
| likes: 1789, | |
| views: "7.8K", | |
| comments: 89, | |
| description: "Environment design for sci-fi game project. Blender and Unreal Engine 5. Real-time rendering.", | |
| tags: ["3d", "environment", "scifi", "space"] | |
| }, | |
| { | |
| id: 12, | |
| title: "Watercolor Sunset", | |
| artist: "BrushAndPaint", | |
| category: "traditional", | |
| image: "https://static.photos/nature/640x360/12", | |
| avatar: "https://static.photos/people/200x200/12", | |
| likes: 923, | |
| views: "3.4K", | |
| comments: 34, | |
| description: "Wet-on-wet technique. Winsor & Newton watercolors. Arches cold press 300gsm.", | |
| tags: ["watercolor", "traditional", "sunset", "seascape"] | |
| } | |
| ]; | |
| let currentCategory = 'all'; | |
| let currentSort = 'newest'; | |
| let likedArtworks = new Set(); | |
| // Initialize | |
| document.addEventListener('DOMContentLoaded', () => { | |
| lucide.createIcons(); | |
| renderGallery(); | |
| setupEventListeners(); | |
| checkNullUndefined(); | |
| }); | |
| // Error handling demonstration for undefined/null | |
| function checkNullUndefined() { | |
| // Simulating safe data access patterns | |
| const safeGet = (obj, path, defaultValue = null) => { | |
| try { | |
| return path.split('.').reduce((acc, part) => | |
| acc && acc[part] !== undefined ? acc[part] : defaultValue, obj); | |
| } catch (e) { | |
| console.warn('Null/Undefined value encountered:', path); | |
| return defaultValue; | |
| } | |
| }; | |
| // Example of handling potentially undefined data | |
| const testData = { artwork: { title: "Test", stats: null } }; | |
| // Safe access without errors | |
| const title = safeGet(testData, 'artwork.title', 'Untitled'); | |
| const likes = safeGet(testData, 'artwork.stats.likes', 0); | |
| console.log('Null/Undefined handling demo:', { title, likes }); | |
| } | |
| function renderGallery() { | |
| const gallery = document.getElementById('gallery'); | |
| const filtered = filterArtworks(); | |
| const sorted = sortArtworks(filtered); | |
| gallery.innerHTML = sorted.map(artwork => createArtworkCard(artwork)).join(''); | |
| lucide.createIcons(); | |
| // Update count | |
| document.getElementById('resultCount').textContent = `Showing ${sorted.length} artworks`; | |
| } | |
| function createArtworkCard(artwork) { | |
| const isLiked = likedArtworks.has(artwork.id); | |
| const likeClass = isLiked ? 'text-red-500 fill-current' : 'text-white'; | |
| return ` | |
| <div class="group relative bg-card rounded-lg overflow-hidden cursor-pointer transition-transform hover:scale-[1.02] hover:shadow-2xl" | |
| onclick="openModal(${artwork.id})"> | |
| <div class="aspect-w-4 aspect-h-3 relative overflow-hidden"> | |
| <img src="${artwork.image}" | |
| alt="${artwork.title}" | |
| class="w-full h-64 object-cover transition-transform duration-500 group-hover:scale-110" | |
| loading="lazy" | |
| onerror="this.src='https://static.photos/abstract/640x480/999'"> | |
| <!-- Hover Overlay --> | |
| <div class="absolute inset-0 opacity-0 group-hover:opacity-100 transition-opacity duration-300"> | |
| <div class="absolute inset-0 hover-overlay"></div> | |
| <div class="absolute bottom-0 left-0 right-0 p-4 transform translate-y-2 group-hover:translate-y-0 transition-transform"> | |
| <h3 class="font-bold text-white text-lg mb-1 line-clamp-1">${artwork.title}</h3> | |
| <p class="text-gray-300 text-sm mb-2">by ${artwork.artist}</p> | |
| <div class="flex items-center justify-between"> | |
| <div class="flex items-center gap-3 text-xs text-gray-300"> | |
| <span class="flex items-center gap-1"> | |
| <i data-lucide="heart" class="w-3 h-3"></i> | |
| ${formatNumber(artwork.likes)} | |
| </span> | |
| <span class="flex items-center gap-1"> | |
| <i data-lucide="message-circle" class="w-3 h-3"></i> | |
| ${artwork.comments} | |
| </span> | |
| </div> | |
| <button onclick="toggleLike(event, ${artwork.id})" | |
| class="p-2 rounded-full bg-white/20 hover:bg-white/30 transition-colors ${likeClass}"> | |
| <i data-lucide="heart" class="w-4 h-4 ${isLiked ? 'fill-current'}"></i> | |
| </button> | |
| </div> | |
| </div> | |
| </div> | |
| <!-- Category Badge --> | |
| <div class="absolute top-3 left-3"> | |
| <span class="px-2 py-1 bg-black/60 backdrop-blur-sm rounded text-xs font-medium text-white capitalize"> | |
| ${artwork.category} | |
| </span> | |
| </div> | |
| </div> | |
| </div> | |
| `; | |
| } | |
| function filterArtworks() { | |
| if (currentCategory === 'all') return artworks; | |
| return artworks.filter(art => art.category === currentCategory); | |
| } | |
| function sortArtworks(artworks) { | |
| const sorted = [...artworks]; | |
| switch(currentSort) { | |
| case 'popular': | |
| return sorted.sort((a, b) => b.likes - a.likes); | |
| case 'comments': | |
| return sorted.sort((a, b) => b.comments - a.comments); | |
| default: | |
| return sorted.sort((a, b) => b.id - a.id); | |
| } | |
| } | |
| function formatNumber(num) { | |
| if (num >= 1000) { | |
| return (num / 1000).toFixed(1) + 'K'; | |
| } | |
| return num; | |
| } | |
| function toggleLike(event, id) { | |
| event.stopPropagation(); | |
| if (likedArtworks.has(id)) { | |
| likedArtworks.delete(id); | |
| showToast('Removed from favorites'); | |
| } else { | |
| likedArtworks.add(id); | |
| showToast('Added to favorites'); | |
| // Add animation class | |
| const btn = event.currentTarget; | |
| btn.classList.add('like-anim'); | |
| setTimeout(() => btn.classList.remove('like-anim'), 300); | |
| } | |
| renderGallery(); | |
| } | |
| function openModal(id) { | |
| const artwork = artworks.find(a => a.id === id); | |
| if (!artwork) { | |
| console.error('Artwork not found:', id); | |
| return; | |
| } | |
| document.getElementById('modalImage').src = artwork.image; | |
| document.getElementById('modalTitle').textContent = artwork.title; | |
| document.getElementById('modalCategory').textContent = artwork.category.charAt(0).toUpperCase() + artwork.category.slice(1); | |
| document.getElementById('modalArtist').textContent = artwork.artist; | |
| document.getElementById('modalAvatar').src = artwork.avatar; | |
| document.getElementById('modalDescription').textContent = artwork.description; | |
| document.getElementById('modalViews').textContent = artwork.views; | |
| document.getElementById('modalComments').textContent = artwork.comments; | |
| document.getElementById('modalLikes').textContent = artwork.likes; | |
| // Render tags | |
| const tagsContainer = document.getElementById('modalTags'); | |
| tagsContainer.innerHTML = artwork.tags.map(tag => | |
| `<span class="px-3 py-1 bg-gray-800 rounded-full text-xs text-gray-300 hover:bg-accent hover:text-dark cursor-pointer transition-colors">#${tag}</span>` | |
| ).join(''); | |
| // Setup like button in modal | |
| const likeBtn = document.getElementById('modalLikeBtn'); | |
| const isLiked = likedArtworks.has(id); | |
| updateModalLikeButton(likeBtn, isLiked); | |
| likeBtn.onclick = () => { | |
| if (likedArtworks.has(id)) { | |
| likedArtworks.delete(id); | |
| updateModalLikeButton(likeBtn, false); | |
| showToast('Removed from favorites'); | |
| } else { | |
| likedArtworks.add(id); | |
| updateModalLikeButton(likeBtn, true); | |
| showToast('Added to favorites'); | |
| } | |
| renderGallery(); | |
| }; | |
| document.getElementById('imageModal').classList.remove('hidden'); | |
| document.body.style.overflow = 'hidden'; | |
| lucide.createIcons(); | |
| } | |
| function updateModalLikeButton(btn, isLiked) { | |
| const icon = btn.querySelector('i'); | |
| if (isLiked) { | |
| icon.classList.add('text-red-500', 'fill-current'); | |
| icon.classList.remove('text-white'); | |
| } else { | |
| icon.classList.remove('text-red-500', 'fill-current'); | |
| icon.classList.add('text-white'); | |
| } | |
| } | |
| function closeModal() { | |
| document.getElementById('imageModal').classList.add('hidden'); | |
| document.body.style.overflow = ''; | |
| } | |
| function showToast(message) { | |
| const toast = document.getElementById('toast'); | |
| const toastMessage = document.getElementById('toastMessage'); | |
| toastMessage.textContent = message; | |
| toast.classList.remove('translate-y-20', 'opacity-0'); | |
| setTimeout(() => { | |
| toast.classList.add('translate-y-20', 'opacity-0'); | |
| }, 3000); | |
| } | |
| function setupEventListeners() { | |
| // Filter buttons | |
| document.querySelectorAll('.filter-btn').forEach(btn => { | |
| btn.addEventListener('click', (e) => { | |
| document.querySelectorAll('.filter-btn').forEach(b => { | |
| b.classList.remove('active', 'bg-accent', 'text-dark'); | |
| b.classList.add('bg-card', 'border-gray-700'); | |
| }); | |
| e.target.classList.remove('bg-card', 'border-gray-700'); | |
| e.target.classList.add('active', 'bg-accent', 'text-dark'); | |
| currentCategory = e.target.dataset.category; | |
| renderGallery(); | |
| }); | |
| }); | |
| // Sort select | |
| document.getElementById('sortSelect').addEventListener('change', (e) => { | |
| currentSort = e.target.value; | |
| renderGallery(); | |
| }); | |
| // Search | |
| document.getElementById('searchInput').addEventListener('input', (e) => { | |
| const query = e.target.value.toLowerCase(); | |
| if (query === '') { | |
| renderGallery(); | |
| return; | |
| } | |
| const filtered = artworks.filter(art => | |
| art.title.toLowerCase().includes(query) || | |
| art.artist.toLowerCase().includes(query) || | |
| art.tags.some(tag => tag.toLowerCase().includes(query)) | |
| ); | |
| const gallery = document.getElementById('gallery'); | |
| gallery.innerHTML = filtered.map(artwork => createArtworkCard(artwork)).join(''); | |
| lucide.createIcons(); | |
| document.getElementById('resultCount').textContent = `Found ${filtered.length} artworks`; | |
| }); | |
| // Modal close | |
| document.getElementById('closeModal').addEventListener('click', closeModal); | |
| document.getElementById('imageModal').addEventListener('click', (e) => { | |
| if (e.target.id === 'imageModal') closeModal(); | |
| }); | |
| // Keyboard navigation | |
| document.addEventListener('keydown', (e) => { | |
| if (e.key === 'Escape') closeModal(); | |
| }); | |
| // Load more (simulation) | |
| document.getElementById('loadMoreBtn').addEventListener('click', () => { | |
| const loadingState = document.getElementById('loadingState'); | |
| const btn = document.getElementById('loadMoreBtn'); | |
| btn.classList.add('hidden'); | |
| loadingState.classList.remove('hidden'); | |
| setTimeout(() => { | |
| loadingState.classList.add('hidden'); | |
| btn.classList.remove('hidden'); | |
| showToast('More artworks loaded!'); | |
| // Duplicate existing artworks with new IDs to simulate more data | |
| const newArtworks = artworks.map(art => ({ | |
| ...art, | |
| id: art.id + artworks.length, | |
| likes: Math.floor(Math.random() * 5000) | |
| })); | |
| artworks.push(...newArtworks); | |
| renderGallery(); | |
| }, 1500); | |
| }); | |
| // Theme toggle | |
| let isDark = true; | |
| document.getElementById('themeToggle').addEventListener('click', () => { | |
| isDark = !isDark; | |
| const icon = document.querySelector('#themeToggle i'); | |
| if (isDark) { | |
| document.documentElement.classList.remove('light'); | |
| icon.setAttribute('data-lucide', 'moon'); | |
| } else { | |
| document.documentElement.classList.add('light'); | |
| icon.setAttribute('data-lucide', 'sun'); | |
| } | |
| lucide.createIcons(); | |
| }); | |
| } | |
| // Handle null/undefined image errors globally | |
| window.addEventListener('error', (e) => { | |
| if (e.target.tagName === 'IMG') { | |
| console.warn('Image failed to load:', e.target.src); | |
| e.target.src = 'https://static.photos/abstract/640x480/999'; | |
| e.target.onerror = null; // Prevent infinite loop | |
| } | |
| }, true); |