PageSourceSearch

https://linangdata.com/emoji-search/js/script.js

js linangdata.com collected 2026-09-24 12:57:25 UTC 6,543 bytes, 205 lines download raw bytes

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.