1/** 2 * Deonde Blog Theme v2.0 â JavaScript 3 * Mobile menu, search dropdown, AJAX load more, back to top 4 */ 5 6 7(function () { 8 'use strict'; 9 10 document.addEventListener('DOMContentLoaded', function () { 11 12 // ââââââââââââââââââââââââââââââââââââââââââ 13 // 1. MOBILE DRAWER 14 // ââââââââââââââââââââââââââââââââââââââââââ 15 var mobileBtn = document.getElementById('mobileToggle'); // was 'navMobileBtn' 16 var mobileDrawer = document.getElementById('mobileNav'); // was 'mobileDrawer' 17 var mobileOverlay = document.getElementById('mobileOverlay'); 18 19 function openMobileNav() { 20 mobileDrawer.classList.add('is-open'); // was 'open' 21 if (mobileOverlay) mobileOverlay.classList.add('is-open'); 22 mobileBtn.setAttribute('aria-expanded', 'true'); 23 document.body.style.overflow = 'hidden'; 24 } 25 function closeMobileNav() { 26 mobileDrawer.classList.remove('is-open'); // was 'open' 27 if (mobileOverlay) mobileOverlay.classList.remove('is-open'); 28 mobileBtn.setAttribute('aria-expanded', 'false'); 29 document.body.style.overflow = ''; 30 } 31 32 if (mobileBtn && mobileDrawer) { 33 mobileBtn.addEventListener('click', openMobileNav); 34 35 // Close button inside drawer 36 var mobileClose = document.getElementById('mobileClose'); 37 if (mobileClose) mobileClose.addEventListener('click', closeMobileNav); 38 39 // Close when clicking overlay 40 if (mobileOverlay) mobileOverlay.addEventListener('click', closeMobileNav); 41 42 // Close on ESC 43 document.addEventListener('keydown', function (e) { 44 if (e.key === 'Escape' && mobileDrawer.classList.contains('is-open')) { 45 closeMobileNav(); 46 } 47 }); 48 } 49 50 document.querySelectorAll('.mobile-group__toggle').forEach(function (btn) { 51 btn.addEventListener('click', function () { 52 var group = btn.closest('.mobile-group'); 53 var isOpen = group.classList.toggle('is-open'); 54 btn.setAttribute('aria-expanded', isOpen); 55 }); 56 }); 57 58 // ââââââââââââââââââââââââââââââââââââââââââ 59 // 2. SEARCH DROPDOWN 60 // ââââââââââââââââââââââââââââââââââââââââââ 61 var searchInput = document.getElementById('heroSearchInput'); 62 var searchDrop = document.getElementById('heroSearchDrop'); 63 var searchWrap = document.getElementById('searchWrap'); 64 65 if (searchInput && searchDrop) { 66 searchInput.addEventListener('focus', function () { 67 searchDrop.classList.add('open'); 68 }); 69 searchInput.addEventListener('input', function () { 70 if (this.value.trim()) searchDrop.classList.add('open'); 71 }); 72 73 document.addEventListener('click', function (e) { 74 if (searchWrap && !searchWrap.contains(e.target)) { 75 searchDrop.classList.remove('open'); 76 } 77 }); 78 79 document.addEventListener('keydown', function (e) { 80 if (e.key === 'Escape') { 81 searchDrop.classList.remove('open'); 82 searchInput.blur(); 83 } 84 }); 85 } 86 87 // ââââââââââââââââââââââââââââââââââââââââââ 88 // 3. AJAX LOAD MORE 89 // ââââââââââââââââââââââââââââââââââââââââââ 90 var loadMoreBtn = document.getElementById('loadMoreBtn'); 91 var blogGrid = document.getElementById('blogGrid'); 92 93 if (loadMoreBtn && blogGrid && typeof deonde_ajax !== 'undefined') { 94 var currentPage = 1; 95 var maxPages = parseInt(loadMoreBtn.getAttribute('data-max')) || parseInt(deonde_ajax.max_pages) || 1; 96 var isLoading = false; 97 98 if (currentPage >= maxPages) { 99 loadMoreBtn.style.display = 'none'; 100 } 101
102 loadMoreBtn.addEventListener('click', function () { 103 if (isLoading) return; 104 isLoading = true; 105 currentPage++; 106 107 var originalHTML = loadMoreBtn.innerHTML; 108 loadMoreBtn.innerHTML = '<svg width="16" height="16" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2.5" style="animation:spin .7s linear infinite"><path d="M21 12a9 9 0 1 1-6.219-8.56"/></svg> Loading...'; 109 loadMoreBtn.disabled = true; 110 loadMoreBtn.style.opacity = '0.7'; 111 112 var formData = new FormData(); 113 formData.append('action', 'deonde_load_more'); 114 formData.append('page', currentPage); 115 formData.append('posts_per_page', deonde_ajax.posts_per_page || 9); 116 formData.append('nonce', deonde_ajax.nonce); 117 118 fetch(deonde_ajax.ajax_url, { 119 method: 'POST', 120 body: formData, 121 credentials: 'same-origin', 122 }) 123 .then(function (r) { return r.json(); }) 124 .then(function (data) { 125 if (data.success && data.data.posts) { 126 var tmp = document.createElement('div'); 127 tmp.innerHTML = data.data.posts; 128 129 var newCards = tmp.querySelectorAll('.blog-card'); 130 newCards.forEach(function (card, idx) { 131 blogGrid.appendChild(card); 132 setTimeout(function () { 133 card.style.transition = 'opacity .4s ease, transform .4s ease'; 134 card.style.opacity = '1'; 135 card.style.transform = 'translateY(0)'; 136 }, idx * 60); 137 }); 138 139 maxPages = parseInt(data.data.max_pages) || maxPages; 140 if (currentPage >= maxPages) { 141 loadMoreBtn.style.display = 'none'; 142 } else { 143 loadMoreBtn.innerHTML = originalHTML; 144 loadMoreBtn.disabled = false; 145 loadMoreBtn.style.opacity = '1'; 146 } 147 } else { 148 loadMoreBtn.style.display = 'none'; 149 } 150 isLoading = false; 151 }) 152 .catch(function () { 153 loadMoreBtn.innerHTML = originalHTML; 154 loadMoreBtn.disabled = false; 155 loadMoreBtn.style.opacity = '1'; 156 isLoading = false; 157 }); 158 }); 159 } 160 161 // ââââââââââââââââââââââââââââââââââââââââââ 162 // 4. BACK TO TOP 163 // ââââââââââââââââââââââââââââââââââââââââââ 164 var backTopBtn = document.getElementById('backTop'); 165 if (backTopBtn) { 166 window.addEventListener('scroll', function () { 167 backTopBtn.classList.toggle('show', window.scrollY > 500); 168 }, { passive: true }); 169 170 backTopBtn.addEventListener('click', function () { 171 window.scrollTo({ top: 0, behavior: 'smooth' }); 172 }); 173 } 174 175 // ââââââââââââââââââââââââââââââââââââââââââ 176 // 5. SMOOTH SCROLL for anchor links 177 // ââââââââââââââââââââââââââââââââââââââââââ 178 document.querySelectorAll('a[href^="#"]').forEach(function (anchor) { 179 anchor.addEventListener('click', function (e) { 180 var href = this.getAttribute('href'); 181 if (href !== '#' && href !== '#!') { 182 var target = document.querySelector(href); 183 if (target) { 184 e.preventDefault(); 185 var offset = target.getBoundingClientRect().top + window.pageYOffset - 80; 186 window.scrollTo({ top: offset, behavior: 'smooth' }); 187 } 188 } 189 }); 190 }); 191 192 // ââââââââââââââââââââââââââââââââââââââââââ 193 // 6. SPIN KEYFRAME (for load more) 194 // ââââââââââââââââââââââââââââââââââââââââââ 195 if (!document.getElementById('deonde-spin-style')) { 196 var style = document.createElement('style'); 197 style.id = 'deonde-spin-style'; 198 style.textContent = '@keyframes spin { to { transform: rotate(360deg); } }'; 199 document.head.appendChild(style); 200 } 201 202 }); 203 204})();
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.