1// DOM elements 2const emojiContainer = document.getElementById('emoji-container'); 3const searchInput = document.getElementById('search-input'); 4const noResults = document.getElementById('no-results'); 5const loadingContainer = document.getElementById('loading-container'); 6const copyToast = document.getElementById('copy-toast'); 7const toastMessage = document.getElementById('toast-message'); 8const visibleCount = document.getElementById('visible-count'); 9const emojiCount = document.getElementById('emoji-count'); 10const totalEmojis = document.getElementById('total-emojis'); 11const categoryCount = document.getElementById('category-count'); 12 13// Initialize Bootstrap toast 14const toast = new bootstrap.Toast(copyToast, { delay: 5000, autohide: true }); 15 16// Load emojis from JSON file 17async function loadEmojis() { 18 try { 19 showLoadingState(); 20 21 // Simulate loading delay for better UX 22 await new Promise(resolve => setTimeout(resolve, 1000)); 23 24 const response = await fetch('emojis.json'); 25 const emojis = await response.json(); 26 27 // Update counts 28 emojiCount.textContent = emojis.length; 29 totalEmojis.textContent = emojis.length; 30 31 // Calculate unique categories 32 const categories = [...new Set(emojis.map(e => e.category))]; 33 categoryCount.textContent = categories.length; 34 35 hideLoadingState(); 36 displayEmojis(emojis); 37 updateVisibleCount(emojis.length); 38 39 } catch (error) { 40 console.error('Error loading emojis:', error); 41 showErrorState(); 42 } 43} 44 45function showLoadingState() { 46 loadingContainer.style.display = 'block'; 47 emojiContainer.style.display = 'none'; 48 noResults.style.display = 'none'; 49} 50 51function hideLoadingState() { 52 loadingContainer.style.display = 'none'; 53 emojiContainer.style.display = 'grid'; 54} 55 56function showErrorState() { 57 loadingContainer.innerHTML = ` 58 <div class="text-white"> 59 <i class="bi bi-emoji-expressionless display-1"></i> 60 <h3 class="mt-3">Oops! Something went wrong</h3> 61 <p class="mb-4">We couldn't load the emoji database</p> 62 <button class="btn btn-light" onclick="loadEmojis()"> 63 <i class="bi bi-arrow-clockwise me-2"></i>Try Again 64 </button> 65 </div> 66 `; 67} 68 69// Display all emojis 70function displayEmojis(emojiList) { 71 emojiContainer.innerHTML = ''; 72 73 if (emojiList.length === 0) { 74 emojiContainer.style.display = 'none'; 75 noResults.style.display = 'block'; 76 updateVisibleCount(0); 77 return; 78 } 79 80 noResults.style.display = 'none'; 81 emojiContainer.style.display = 'grid'; 82 83 emojiList.forEach(item => { 84 const emojiCard = document.createElement('button'); 85 emojiCard.className = 'emoji-card'; 86 emojiCard.innerHTML = ` 87 <span class="emoji">${item.emoji}</span> 88 <div class="emoji-name">${item.name}</div> 89 <div class="emoji-category">${item.category}</div> 90 `; 91 92 // Add click event to copy emoji 93 emojiCard.addEventListener('click', (event) => { 94 copyEmojiToClipboard(item.emoji, item.name, event); 95 }); 96 97 emojiContainer.appendChild(emojiCard); 98 }); 99 100 updateVisibleCount(emojiList.length); 101} 102 103// Copy emoji to clipboard with feedback 104async function copyEmojiToClipboard(emoji, name, event) { 105 try { 106 await navigator.clipboard.writeText(emoji); 107 108 // Show success toast 109 toastMessage.innerHTML = `Copied ${emoji} to clipboard!`; 110 copyToast.classList.remove('bg-danger'); 111 copyToast.classList.add('bg-success'); 112 toast.show(); 113 114 // Visual feedback on the card 115 const activeCard = event.currentTarget || event.target; 116 activeCard.style.transform = 'scale(0.95)'; 117 activeCard.style.background = 'linear-gradient(135deg, #e8f5e8, #ffffff)'; 118 // console.log(activeCard.style) 119 setTimeout(() => { 120 activeCard.style.transform = ''; 121 activeCard.style.background = ''; 122 }, 300); 123 124 } catch (error) { 125 console.error('Failed to copy:', error); 126 127 // Show error toast 128 toastMessage.innerHTML = `<i class="bi bi-exclamation-triangle-fill me-2"></i>Failed to copy emoji`; 129 copyToast.classList.remove('bg-success'); 130 copyToast.classList.add('bg-danger'); 131 toast.show(); 132 } 133} 134 135// Filter emojis based on search input 136function filterEmojis(emojis) { 137 const searchTerm = searchInput.value.toLowerCase().trim(); 138 139 if (searchTerm === '') { 140 displayEmojis(emojis); 141 return; 142 } 143 144 const filteredEmojis = emojis.filter(item => 145 item.name.toLowerCase().includes(searchTerm) || 146 item.category.toLowerCase().includes(searchTerm) || 147 item.emoji.includes(searchTerm) 148 ); 149 150 displayEmojis(filteredEmojis); 151} 152 153// Update visible emoji count 154function updateVisibleCount(count) { 155 visibleCount.textContent = count; 156} 157 158// Clear search and show all emojis 159function clearSearch() { 160 searchInput.value = ''; 161 loadEmojis(); 162 searchInput.focus(); 163} 164 165// Initialize search with debouncing 166let currentEmojis = []; 167let searchTimeout; 168 169searchInput.addEventListener('input', () => { 170 clearTimeout(searchTimeout); 171 searchTimeout = setTimeout(() => { 172 filterEmojis(currentEmojis); 173 }, 300); 174}); 175 176// Enhanced version of loadEmojis that stores the data 177async function initializeApp() { 178 try { 179 const response = await fetch('emojis.json'); 180 currentEmojis = await response.json(); 181 182 // Update counts 183 emojiCount.textContent = currentEmojis.length; 184 totalEmojis.textContent = currentEmojis.length; 185 186 const categories = [...new Set(currentEmojis.map(e => e.category))]; 187 categoryCount.textContent = categories.length; 188 189 hideLoadingState(); 190 displayEmojis(currentEmojis); 191 updateVisibleCount(currentEmojis.length); 192 193 } catch (error) { 194 console.error('Error loading emojis:', error); 195 showErrorState(); 196 } 197} 198 199// Focus search input on page load 200window.addEventListener('load', () => { 201 searchInput.focus(); 202}); 203 204// Initialize the app 205initializeApp();
Line numbers count LF bytes from the start of the resource, as the search results do. Vendor segments are library code the classifier recognised; they are stored but not indexed. Bytes are shown as Latin1 characters, one per byte.