-
+
+
+
+
+
+
+
+
+
+
+
+
+
diff --git a/script.js b/script.js
index 268d1b2..3881652 100644
--- a/script.js
+++ b/script.js
@@ -3,8 +3,11 @@ document.addEventListener('DOMContentLoaded', () => {
const emojiGrid = document.getElementById('emoji-grid');
const searchInput = document.getElementById('search-input');
const darkModeToggle = document.getElementById('dark-mode-toggle');
+ const darkModeToggleDesktop = document.getElementById('dark-mode-toggle-desktop');
const lightIcon = document.getElementById('theme-toggle-light-icon');
const darkIcon = document.getElementById('theme-toggle-dark-icon');
+ const lightIconDesktop = document.getElementById('theme-toggle-light-icon-desktop');
+ const darkIconDesktop = document.getElementById('theme-toggle-dark-icon-desktop');
const modal = document.getElementById('emoji-modal');
const modalContent = document.getElementById('modal-content');
const modalCloseBtn = document.getElementById('modal-close-btn');
@@ -14,6 +17,15 @@ document.addEventListener('DOMContentLoaded', () => {
const modalKeywords = document.getElementById('modal-keywords');
const modalCopyBtn = document.getElementById('modal-copy-btn');
const loadMoreBtn = document.getElementById('load-more-btn');
+ const categoryButtons = document.querySelectorAll('.category-btn');
+ const currentCategoryTitle = document.getElementById('current-category-title');
+ const currentCategoryCount = document.getElementById('current-category-count');
+ const offcanvasToggle = document.getElementById('offcanvas-toggle');
+ const offcanvasOverlay = document.getElementById('offcanvas-overlay');
+ const offcanvasClose = document.getElementById('offcanvas-close');
+ const offcanvasBackdrop = document.getElementById('offcanvas-backdrop');
+ const offcanvasSidebar = document.getElementById('offcanvas-sidebar');
+ const offcanvasNav = document.getElementById('offcanvas-nav');
// --- State ---
let allEmojis = [];
@@ -21,26 +33,33 @@ document.addEventListener('DOMContentLoaded', () => {
let currentPage = 1;
const EMOJIS_PER_PAGE = 100;
let indonesianKeywords = {};
+ let currentCategory = 'all';
+ let categorizedEmojis = {};
// --- Dark Mode Logic ---
const applyTheme = (isDark) => {
document.documentElement.classList.toggle('dark', isDark);
+ // Mobile icons
lightIcon.classList.toggle('hidden', !isDark);
darkIcon.classList.toggle('hidden', isDark);
+ // Desktop icons
+ lightIconDesktop.classList.toggle('hidden', !isDark);
+ darkIconDesktop.classList.toggle('hidden', isDark);
};
- darkModeToggle.addEventListener('click', () => {
+ const toggleDarkMode = () => {
const isDark = !document.documentElement.classList.contains('dark');
localStorage.setItem('darkMode', isDark);
applyTheme(isDark);
- });
+ };
+
+ darkModeToggle.addEventListener('click', toggleDarkMode);
+ darkModeToggleDesktop.addEventListener('click', toggleDarkMode);
// Set initial icon state on load
const initialIsDark = document.documentElement.classList.contains('dark');
applyTheme(initialIsDark);
-
-
// --- Data Fetching & Processing ---
const jsonFiles = [
'array.json',
@@ -92,7 +111,24 @@ document.addEventListener('DOMContentLoaded', () => {
}
});
allEmojis = Array.from(uniqueEmojis.values());
+
+ // Organize emojis by category
+ categorizedEmojis = {
+ 'all': allEmojis,
+ 'Smileys & Emotion': allEmojis.filter(e => e.category === 'Smileys & Emotion'),
+ 'People & Body': allEmojis.filter(e => e.category === 'People & Body'),
+ 'Animals & Nature': allEmojis.filter(e => e.category === 'Animals & Nature'),
+ 'Food & Drink': allEmojis.filter(e => e.category === 'Food & Drink'),
+ 'Travel & Places': allEmojis.filter(e => e.category === 'Travel & Places'),
+ 'Activities': allEmojis.filter(e => e.category === 'Activities'),
+ 'Objects': allEmojis.filter(e => e.category === 'Objects'),
+ 'Symbols': allEmojis.filter(e => e.category === 'Symbols'),
+ 'Flags': allEmojis.filter(e => e.category === 'Flags')
+ };
+
currentEmojiList = allEmojis;
+ initializeCategoryMenu();
+ updateCategoryDisplay();
displayPage(1);
})
.catch(error => {
@@ -143,21 +179,145 @@ document.addEventListener('DOMContentLoaded', () => {
displayPage(currentPage + 1);
});
+ // --- Category Logic ---
+ function initializeCategoryMenu() {
+ // Desktop category buttons
+ categoryButtons.forEach(btn => {
+ btn.addEventListener('click', () => {
+ const category = btn.dataset.category;
+ setActiveCategory(category);
+ });
+ });
+
+ // Offcanvas category menu
+ const categories = [
+ { key: 'all', name: 'All Emojis', icon: '🌟' },
+ { key: 'Smileys & Emotion', name: 'Smileys & Emotion', icon: '😀' },
+ { key: 'People & Body', name: 'People & Body', icon: '👋' },
+ { key: 'Animals & Nature', name: 'Animals & Nature', icon: '🐶' },
+ { key: 'Food & Drink', name: 'Food & Drink', icon: '🍎' },
+ { key: 'Travel & Places', name: 'Travel & Places', icon: '🌍' },
+ { key: 'Activities', name: 'Activities', icon: '⚽' },
+ { key: 'Objects', name: 'Objects', icon: '💡' },
+ { key: 'Symbols', name: 'Symbols', icon: '❤️' },
+ { key: 'Flags', name: 'Flags', icon: '🏳️' }
+ ];
+
+ offcanvasNav.innerHTML = categories.map(cat => `
+
+ `).join('');
+
+ // Offcanvas category button events
+ document.querySelectorAll('.offcanvas-category-btn').forEach(btn => {
+ btn.addEventListener('click', () => {
+ const category = btn.dataset.category;
+ setActiveCategory(category);
+ closeOffcanvas();
+ });
+ });
+
+ // Offcanvas menu controls
+ offcanvasToggle.addEventListener('click', openOffcanvas);
+ offcanvasClose.addEventListener('click', closeOffcanvas);
+ offcanvasBackdrop.addEventListener('click', closeOffcanvas);
+ }
+
+ function setActiveCategory(category) {
+ currentCategory = category;
+
+ // Update active state for desktop buttons
+ categoryButtons.forEach(btn => {
+ btn.classList.toggle('active', btn.dataset.category === category);
+ if (btn.dataset.category === category) {
+ btn.classList.add('bg-blue-100', 'dark:bg-blue-900', 'text-blue-700', 'dark:text-blue-300');
+ } else {
+ btn.classList.remove('bg-blue-100', 'dark:bg-blue-900', 'text-blue-700', 'dark:text-blue-300');
+ }
+ });
+
+ // Update active state for offcanvas buttons
+ document.querySelectorAll('.offcanvas-category-btn').forEach(btn => {
+ if (btn.dataset.category === category) {
+ btn.classList.add('bg-blue-100', 'dark:bg-blue-900', 'text-blue-700', 'dark:text-blue-300');
+ } else {
+ btn.classList.remove('bg-blue-100', 'dark:bg-blue-900', 'text-blue-700', 'dark:text-blue-300');
+ }
+ });
+
+ // Filter emojis by category
+ const baseEmojis = categorizedEmojis[category] || [];
+
+ // Apply search filter if there's a search term
+ const searchTerm = searchInput.value.toLowerCase().trim();
+ if (searchTerm) {
+ currentEmojiList = baseEmojis.filter(emoji => {
+ const nameMatch = emoji.name.toLowerCase().includes(searchTerm);
+ const keywordMatch = emoji.keywords && Array.isArray(emoji.keywords) && emoji.keywords.some(k => k.toLowerCase().includes(searchTerm));
+ const categoryMatch = emoji.category && emoji.category.toLowerCase().includes(searchTerm);
+ const subcategoryMatch = emoji.subcategory && emoji.subcategory.toLowerCase().includes(searchTerm);
+
+ // Indonesian keywords search
+ const indonesianMatch = emoji.indonesianKeywords && Array.isArray(emoji.indonesianKeywords) &&
+ emoji.indonesianKeywords.some(k => k.toLowerCase().includes(searchTerm));
+
+ return nameMatch || keywordMatch || categoryMatch || subcategoryMatch || indonesianMatch;
+ });
+ } else {
+ currentEmojiList = baseEmojis;
+ }
+
+ updateCategoryDisplay();
+ displayPage(1);
+ }
+
+ function updateCategoryDisplay() {
+ const categoryName = currentCategory === 'all' ? 'All Emojis' : currentCategory;
+ currentCategoryTitle.textContent = categoryName;
+ currentCategoryCount.textContent = `${currentEmojiList.length} emojis`;
+ }
+
+ function openOffcanvas() {
+ offcanvasOverlay.classList.remove('hidden');
+ setTimeout(() => {
+ offcanvasSidebar.classList.remove('-translate-x-full');
+ }, 10);
+ }
+
+ function closeOffcanvas() {
+ offcanvasSidebar.classList.add('-translate-x-full');
+ setTimeout(() => {
+ offcanvasOverlay.classList.add('hidden');
+ }, 300);
+ }
+
// --- Search Logic ---
searchInput.addEventListener('input', (e) => {
const searchTerm = e.target.value.toLowerCase().trim();
- currentEmojiList = allEmojis.filter(emoji => {
- const nameMatch = emoji.name.toLowerCase().includes(searchTerm);
- const keywordMatch = emoji.keywords && Array.isArray(emoji.keywords) && emoji.keywords.some(k => k.toLowerCase().includes(searchTerm));
- const categoryMatch = emoji.category && emoji.category.toLowerCase().includes(searchTerm);
- const subcategoryMatch = emoji.subcategory && emoji.subcategory.toLowerCase().includes(searchTerm);
-
- // Indonesian keywords search
- const indonesianMatch = emoji.indonesianKeywords && Array.isArray(emoji.indonesianKeywords) &&
- emoji.indonesianKeywords.some(k => k.toLowerCase().includes(searchTerm));
-
- return nameMatch || keywordMatch || categoryMatch || subcategoryMatch || indonesianMatch;
- });
+ const baseEmojis = categorizedEmojis[currentCategory] || [];
+
+ if (searchTerm) {
+ currentEmojiList = baseEmojis.filter(emoji => {
+ const nameMatch = emoji.name.toLowerCase().includes(searchTerm);
+ const keywordMatch = emoji.keywords && Array.isArray(emoji.keywords) && emoji.keywords.some(k => k.toLowerCase().includes(searchTerm));
+ const categoryMatch = emoji.category && emoji.category.toLowerCase().includes(searchTerm);
+ const subcategoryMatch = emoji.subcategory && emoji.subcategory.toLowerCase().includes(searchTerm);
+
+ // Indonesian keywords search
+ const indonesianMatch = emoji.indonesianKeywords && Array.isArray(emoji.indonesianKeywords) &&
+ emoji.indonesianKeywords.some(k => k.toLowerCase().includes(searchTerm));
+
+ return nameMatch || keywordMatch || categoryMatch || subcategoryMatch || indonesianMatch;
+ });
+ } else {
+ currentEmojiList = baseEmojis;
+ }
+
+ updateCategoryDisplay();
displayPage(1);
});
@@ -233,4 +393,17 @@ document.addEventListener('DOMContentLoaded', () => {
setTimeout(() => { modalCopyBtn.textContent = originalText; }, 2000);
});
}
+
+ // Initialize footer with dynamic year
+ function initFooter() {
+ const yearElement = document.getElementById('current-year');
+ if (yearElement) {
+ const currentYear = new Date().getFullYear();
+ yearElement.textContent = currentYear;
+ }
+ }
+
+ // Initialize footer
+ initFooter();
+
});