|
163 | 163 | </html> |
164 | 164 | --> |
165 | 165 |
|
166 | | - |
167 | 166 | <!DOCTYPE html> |
168 | 167 | <html lang="en"> |
169 | 168 | <head> |
|
211 | 210 | <script> |
212 | 211 | // Current timezone tracker |
213 | 212 | let currentZone = 'IST'; |
| 213 | + let tapCount = 0; |
| 214 | + let tapTimer = null; |
| 215 | + const TAP_TIMEOUT = 300; // ms for double-tap detection |
214 | 216 |
|
215 | 217 | // Sidebar toggle |
216 | | - function toggleSidebar() { |
217 | | - const sidebar = document.getElementById('sidebar'); |
218 | | - sidebar.classList.toggle('hidden'); |
219 | | - localStorage.setItem('sidebar-hidden', sidebar.classList.contains('hidden')); |
| 218 | + function toggleSidebar(isHidden) { |
| 219 | + const sidebar = document.getElementById('sidebar'); |
| 220 | + const toggleBtn = document.querySelector('.toggle-btn'); |
| 221 | + sidebar.classList.toggle('hidden', isHidden); |
| 222 | + localStorage.setItem('sidebar-hidden', isHidden); |
| 223 | + // Show/hide toggle button based on sidebar state (desktop) |
| 224 | + if (window.innerWidth > 768) { |
| 225 | + toggleBtn.style.display = isHidden ? 'block' : 'none'; |
| 226 | + } |
220 | 227 | } |
221 | 228 |
|
222 | | - // Hide sidebar on outside click (mobile only) |
223 | | - function hideSidebarIfClickedOutside(e) { |
224 | | - const sidebar = document.getElementById('sidebar'); |
225 | | - const toggleBtn = document.querySelector('.toggle-btn'); |
226 | | - if ( |
227 | | - !sidebar.classList.contains('hidden') && |
228 | | - !sidebar.contains(e.target) && |
229 | | - !toggleBtn.contains(e.target) && |
230 | | - window.innerWidth <= 768 |
231 | | - ) { |
232 | | - sidebar.classList.add('hidden'); |
233 | | - localStorage.setItem('sidebar-hidden', true); |
234 | | - } |
| 229 | + // Handle tap/click events |
| 230 | + function handleTap(event) { |
| 231 | + const sidebar = document.getElementById('sidebar'); |
| 232 | + const toggleBtn = document.querySelector('.toggle-btn'); |
| 233 | + const target = event.target; |
| 234 | + |
| 235 | + // Ignore taps on interactive elements |
| 236 | + if ( |
| 237 | + target.closest('a') || |
| 238 | + target.closest('button') || |
| 239 | + target.closest('#sidebar') || |
| 240 | + target.closest('#theme-time-container') |
| 241 | + ) { |
| 242 | + return; |
| 243 | + } |
| 244 | + |
| 245 | + tapCount++; |
| 246 | + if (tapCount === 1) { |
| 247 | + tapTimer = setTimeout(() => { |
| 248 | + // Single tap: hide sidebar if visible |
| 249 | + if (!sidebar.classList.contains('hidden')) { |
| 250 | + toggleSidebar(true); |
| 251 | + } |
| 252 | + tapCount = 0; |
| 253 | + }, TAP_TIMEOUT); |
| 254 | + } else if (tapCount === 2) { |
| 255 | + clearTimeout(tapTimer); |
| 256 | + // Double tap: show sidebar if hidden |
| 257 | + if (sidebar.classList.contains('hidden')) { |
| 258 | + toggleSidebar(false); |
| 259 | + } |
| 260 | + tapCount = 0; |
| 261 | + } |
235 | 262 | } |
236 | 263 |
|
237 | 264 | // Dark mode toggle |
238 | 265 | function toggleDarkMode() { |
239 | | - const body = document.body; |
240 | | - body.classList.toggle('dark-mode'); |
241 | | - const isDark = body.classList.contains('dark-mode'); |
242 | | - localStorage.setItem('dark-mode', isDark); |
243 | | - const icon = document.querySelector('.dark-toggle i'); |
244 | | - icon.classList.remove('fa-moon', 'fa-sun'); |
245 | | - icon.classList.add(isDark ? 'fa-sun' : 'fa-moon'); |
| 266 | + const body = document.body; |
| 267 | + body.classList.toggle('dark-mode'); |
| 268 | + const isDark = body.classList.contains('dark-mode'); |
| 269 | + localStorage.setItem('dark-mode', isDark); |
| 270 | + const icon = document.querySelector('.dark-toggle i'); |
| 271 | + icon.classList.remove('fa-moon', 'fa-sun'); |
| 272 | + icon.classList.add(isDark ? 'fa-sun' : 'fa-moon'); |
246 | 273 | } |
247 | 274 |
|
248 | 275 | // Timezone toggle |
249 | 276 | function toggleTimezone() { |
250 | | - currentZone = currentZone === 'IST' ? 'GMT' : 'IST'; |
251 | | - document.getElementById('tz-toggle-btn').textContent = currentZone; |
252 | | - updateLiveTime(); |
| 277 | + currentZone = currentZone === 'IST' ? 'GMT' : 'IST'; |
| 278 | + document.getElementById('tz-toggle-btn').textContent = currentZone; |
| 279 | + updateLiveTime(); |
253 | 280 | } |
254 | 281 |
|
255 | 282 | // Update live time |
256 | 283 | function updateLiveTime() { |
257 | | - const now = new Date(); |
258 | | - let date; |
259 | | - if (currentZone === 'GMT') { |
260 | | - date = new Date(now.getTime() + now.getTimezoneOffset() * 60000); |
261 | | - } else { |
262 | | - const utc = now.getTime() + now.getTimezoneOffset() * 60000; |
263 | | - date = new Date(utc + 5.5 * 3600000); |
264 | | - } |
265 | | - let h = date.getHours(); |
266 | | - const m = date.getMinutes().toString().padStart(2, '0'); |
267 | | - const s = date.getSeconds().toString().padStart(2, '0'); |
268 | | - const ampm = h >= 12 ? 'PM' : 'AM'; |
269 | | - h = h % 12 || 12; |
270 | | - document.getElementById('live-time').textContent = |
271 | | - `Time (${currentZone}): ${h}:${m}:${s} ${ampm}`; |
| 284 | + const now = new Date(); |
| 285 | + let date; |
| 286 | + if (currentZone === 'GMT') { |
| 287 | + date = new Date(now.getTime() + now.getTimezoneOffset() * 60000); |
| 288 | + } else { |
| 289 | + const utc = now.getTime() + now.getTimezoneOffset() * 60000; |
| 290 | + date = new Date(utc + 5.5 * 3600000); |
| 291 | + } |
| 292 | + let h = date.getHours(); |
| 293 | + const m = date.getMinutes().toString().padStart(2, '0'); |
| 294 | + const s = date.getSeconds().toString().padStart(2, '0'); |
| 295 | + const ampm = h >= 12 ? 'PM' : 'AM'; |
| 296 | + h = h % 12 || 12; |
| 297 | + document.getElementById('live-time').textContent = |
| 298 | + `Time (${currentZone}): ${h}:${m}:${s} ${ampm}`; |
272 | 299 | } |
273 | 300 |
|
274 | 301 | // On load: init dark mode, sidebar state, listeners, time, SW |
275 | 302 | window.onload = () => { |
276 | | - // Initialize dark mode |
277 | | - const isDark = localStorage.getItem('dark-mode') === 'true'; |
278 | | - const body = document.body; |
279 | | - if (isDark) { |
280 | | - body.classList.add('dark-mode'); |
281 | | - document.querySelector('.dark-toggle i').classList.replace('fa-moon', 'fa-sun'); |
282 | | - } |
283 | | - |
284 | | - // Initialize sidebar state |
285 | | - const sidebar = document.getElementById('sidebar'); |
286 | | - if (localStorage.getItem('sidebar-hidden') === 'true') { |
287 | | - sidebar.classList.add('hidden'); |
288 | | - } else { |
289 | | - sidebar.classList.remove('hidden'); |
290 | | - } |
291 | | - |
292 | | - document.addEventListener('click', hideSidebarIfClickedOutside); |
293 | | - updateLiveTime(); |
294 | | - setInterval(updateLiveTime, 1000); |
295 | | - |
296 | | - if ('serviceWorker' in navigator) { |
297 | | - navigator.serviceWorker |
298 | | - .register('/JavaEvolution-Learning-Growing-Mastering/assets/sw.js') |
299 | | - .then(() => console.log('Service Worker Registered')) |
300 | | - .catch(err => console.error('SW registration failed', err)); |
301 | | - } |
| 303 | + // Initialize dark mode |
| 304 | + const isDark = localStorage.getItem('dark-mode') === 'true'; |
| 305 | + const body = document.body; |
| 306 | + if (isDark) { |
| 307 | + body.classList.add('dark-mode'); |
| 308 | + document.querySelector('.dark-toggle i').classList.replace('fa-moon', 'fa-sun'); |
| 309 | + } |
| 310 | + |
| 311 | + // Initialize sidebar state |
| 312 | + const sidebar = document.getElementById('sidebar'); |
| 313 | + const toggleBtn = document.querySelector('.toggle-btn'); |
| 314 | + const isSidebarHidden = localStorage.getItem('sidebar-hidden') === 'true'; |
| 315 | + sidebar.classList.toggle('hidden', isSidebarHidden); |
| 316 | + if (window.innerWidth > 768) { |
| 317 | + toggleBtn.style.display = isSidebarHidden ? 'block' : 'none'; |
| 318 | + } else { |
| 319 | + toggleBtn.style.display = 'block'; // Always show on mobile |
| 320 | + } |
| 321 | + |
| 322 | + // Add tap/click listeners |
| 323 | + document.addEventListener('click', handleTap); |
| 324 | + document.addEventListener('touchstart', handleTap, { passive: true }); |
| 325 | + |
| 326 | + updateLiveTime(); |
| 327 | + setInterval(updateLiveTime, 1000); |
| 328 | + |
| 329 | + if ('serviceWorker' in navigator) { |
| 330 | + navigator.serviceWorker |
| 331 | + .register('/JavaEvolution-Learning-Growing-Mastering/assets/sw.js') |
| 332 | + .then(() => console.log('Service Worker Registered')) |
| 333 | + .catch(err => console.error('SW registration failed', err)); |
| 334 | + } |
302 | 335 | }; |
303 | 336 | </script> |
304 | 337 | </head> |
|
317 | 350 |
|
318 | 351 | <!-- Collapsible Sidebar --> |
319 | 352 | <div id="sidebar" class="sidebar"> |
320 | | - <button class="close-btn" onclick="toggleSidebar()" aria-label="Close Sidebar">×</button> |
321 | 353 | <a href="{{ site.baseurl }}/" class="sidebar-link active"> |
322 | 354 | <i class="fas fa-home"></i> Home |
323 | 355 | </a> |
|
333 | 365 | </a> |
334 | 366 | </div> |
335 | 367 |
|
336 | | -<!-- Toggle Button for Mobile --> |
337 | | -<button class="toggle-btn" onclick="toggleSidebar()" aria-label="Toggle Sidebar"> |
| 368 | +<!-- Toggle Button (Fallback) --> |
| 369 | +<button class="toggle-btn" onclick="toggleSidebar(!document.getElementById('sidebar').classList.contains('hidden'))" aria-label="Toggle Sidebar"> |
338 | 370 | <i class="fas fa-bars"></i> |
339 | 371 | </button> |
340 | 372 |
|
|
0 commit comments