|
| 1 | +<!-- |
1 | 2 | <!DOCTYPE html> |
2 | 3 | <html lang="en"> |
3 | 4 | <head> |
4 | 5 | <meta charset="UTF-8" /> |
5 | 6 | <meta name="viewport" content="width=device-width, initial-scale=1.0" /> |
6 | 7 |
|
7 | | - <!-- Font Awesome --> |
| 8 | + <!– Font Awesome –> |
8 | 9 | <link |
9 | 10 | rel="stylesheet" |
10 | 11 | href="https://cdnjs.cloudflare.com/ajax/libs/font-awesome/6.0.0/css/all.min.css" |
11 | 12 | /> |
12 | 13 |
|
13 | | - <!-- Favicons --> |
| 14 | + <!– Favicons –> |
14 | 15 | <link |
15 | 16 | rel="icon" type="image/png" |
16 | 17 | href="{{ '/assets/favicon-96x96.png' | relative_url }}" |
|
261 | 262 | </script> |
262 | 263 | </head> |
263 | 264 |
|
| 265 | +<body> |
| 266 | +<!– Dark Mode & Timezone Controls –> |
| 267 | +<div id="theme-time-container"> |
| 268 | + <button class="dark-toggle" onclick="toggleDarkMode()" aria-label="Toggle Dark Mode"> |
| 269 | + <i class="fas fa-moon"></i> |
| 270 | + </button> |
| 271 | + <div id="time-zone-wrapper"> |
| 272 | + <button id="tz-toggle-btn" class="time-toggle" onclick="toggleTimezone()" aria-label="Toggle Timezone">IST</button> |
| 273 | + <span id="live-time">Time: Loading...</span> |
| 274 | + </div> |
| 275 | +</div> |
| 276 | +
|
| 277 | +<!– Onboarding Tooltip –> |
| 278 | +<div id="tooltip" class="tooltip"> |
| 279 | + Single tap to hide sidebar, double tap to show |
| 280 | +</div> |
| 281 | +
|
| 282 | +<!– Collapsible Sidebar –> |
| 283 | +<div id="sidebar" class="sidebar"> |
| 284 | + <a href="{{ site.baseurl }}/" class="sidebar-link"> |
| 285 | + <i class="fas fa-home"></i> Home |
| 286 | + </a> |
| 287 | + <a href="{{ site.baseurl }}/content" class="sidebar-link"> |
| 288 | + <i class="fas fa-book"></i> All Contents |
| 289 | + </a> |
| 290 | + <a href="https://github.com/Someshdiwan/JavaEvolution-Learning-Growing-Mastering" class="sidebar-link" target="_blank"> |
| 291 | + <i class="fab fa-github"></i> GitHub Repo |
| 292 | + </a> |
| 293 | +</div> |
| 294 | +
|
| 295 | +<!– Toggle Button (Fallback) –> |
| 296 | +<button class="toggle-btn" onclick="toggleSidebar(!document.getElementById('sidebar').classList.contains('hidden'))" aria-label="Toggle Sidebar"> |
| 297 | + <i class="fas fa-bars"></i> |
| 298 | +</button> |
| 299 | +
|
| 300 | +<!– Main Content –> |
| 301 | +<div class="wrapper"> |
| 302 | + <div class="content"> |
| 303 | + <div class="fade-in"> |
| 304 | + {{ content }} |
| 305 | + </div> |
| 306 | + </div> |
| 307 | +</div> |
| 308 | +</body> |
| 309 | +</html>--> |
| 310 | + |
| 311 | +<!DOCTYPE html> |
| 312 | +<html lang="en"> |
| 313 | +<head> |
| 314 | + <meta charset="UTF-8" /> |
| 315 | + <meta name="viewport" content="width=device-width, initial-scale=1.0" /> |
| 316 | + |
| 317 | + <!-- Font Awesome --> |
| 318 | + <link |
| 319 | + rel="stylesheet" |
| 320 | + href="https://cdnjs.cloudflare.com/ajax/libs/font-awesome/6.0.0/css/all.min.css" |
| 321 | + /> |
| 322 | + |
| 323 | + <!-- Favicons --> |
| 324 | + <link |
| 325 | + rel="icon" type="image/png" |
| 326 | + href="{{ '/assets/favicon-96x96.png' | relative_url }}" |
| 327 | + sizes="96x96" |
| 328 | + /> |
| 329 | + <link |
| 330 | + rel="icon" type="image/svg+xml" |
| 331 | + href="{{ '/assets/favicon.svg' | relative_url }}" |
| 332 | + /> |
| 333 | + <link |
| 334 | + rel="shortcut icon" |
| 335 | + href="{{ '/assets/favicon.ico' | relative_url }}" |
| 336 | + /> |
| 337 | + <link |
| 338 | + rel="apple-touch-icon" |
| 339 | + sizes="180x180" |
| 340 | + href="{{ '/assets/apple-touch-icon.png' | relative_url }}" |
| 341 | + /> |
| 342 | + <meta name="apple-mobile-web-app-title" content="Java" /> |
| 343 | + <link |
| 344 | + rel="manifest" |
| 345 | + href="/JavaEvolution-Learning-Growing-Mastering/assets/site.webmanifest" |
| 346 | + /> |
| 347 | + <meta name="theme-color" content="#ffffff" /> |
| 348 | + |
| 349 | + <title>{{ page.title }}</title> |
| 350 | + <link |
| 351 | + rel="stylesheet" |
| 352 | + href="{{ '/assets/style.css' | relative_url }}" |
| 353 | + /> |
| 354 | + |
| 355 | + <script> |
| 356 | + // Current timezone tracker |
| 357 | + let currentZone = 'IST'; |
| 358 | + let tapCount = 0; |
| 359 | + let tapTimer = null; |
| 360 | + const TAP_TIMEOUT = 300; // ms for double-tap detection |
| 361 | + const SCROLL_THRESHOLD = 100; // px to hide theme/time container |
| 362 | + |
| 363 | + // Update active link based on URL |
| 364 | + function updateActiveLink() { |
| 365 | + const currentPath = window.location.pathname; |
| 366 | + const baseUrl = '{{ site.baseurl }}' || ''; |
| 367 | + console.log('Current Path:', currentPath, 'Base URL:', baseUrl); // Debug |
| 368 | + document.querySelectorAll('.sidebar-link').forEach(link => { |
| 369 | + link.classList.remove('active'); |
| 370 | + const href = link.getAttribute('href').replace(baseUrl, ''); // Normalize href |
| 371 | + if (href === currentPath || (currentPath === '/' && href === '/')) { |
| 372 | + link.classList.add('active'); |
| 373 | + console.log('Active Link Set:', href); // Debug |
| 374 | + } |
| 375 | + }); |
| 376 | + } |
| 377 | + |
| 378 | + // Sidebar toggle |
| 379 | + function toggleSidebar(isHidden) { |
| 380 | + const sidebar = document.getElementById('sidebar'); |
| 381 | + const toggleBtn = document.querySelector('.toggle-btn'); |
| 382 | + const content = document.querySelector('.content'); |
| 383 | + if (!sidebar) { |
| 384 | + console.error('Sidebar element not found'); |
| 385 | + return; |
| 386 | + } |
| 387 | + sidebar.classList.toggle('hidden', isHidden); |
| 388 | + content.style.marginLeft = isHidden ? '0' : '210px'; // Force margin update |
| 389 | + localStorage.setItem('sidebar-hidden', isHidden); |
| 390 | + if (window.innerWidth > 768) { |
| 391 | + toggleBtn.style.display = isHidden ? 'block' : 'none'; |
| 392 | + } else { |
| 393 | + toggleBtn.style.display = 'block'; |
| 394 | + } |
| 395 | + updateActiveLink(); |
| 396 | + } |
| 397 | + |
| 398 | + // Handle tap/click events |
| 399 | + function handleTap(event) { |
| 400 | + const sidebar = document.getElementById('sidebar'); |
| 401 | + const target = event.target; |
| 402 | + if (!sidebar) { |
| 403 | + console.error('Sidebar not found during tap'); |
| 404 | + return; |
| 405 | + } |
| 406 | + |
| 407 | + // Allow taps outside interactive elements to trigger hide/show |
| 408 | + if ( |
| 409 | + target.closest('#sidebar') || |
| 410 | + target.closest('#theme-time-container') || |
| 411 | + target.closest('.toggle-btn') || |
| 412 | + target.closest('.tooltip') |
| 413 | + ) { |
| 414 | + return; |
| 415 | + } |
| 416 | + |
| 417 | + tapCount++; |
| 418 | + if (tapCount === 1) { |
| 419 | + tapTimer = setTimeout(() => { |
| 420 | + if (!sidebar.classList.contains('hidden')) { |
| 421 | + toggleSidebar(true); |
| 422 | + } |
| 423 | + tapCount = 0; |
| 424 | + }, TAP_TIMEOUT); |
| 425 | + } else if (tapCount === 2) { |
| 426 | + clearTimeout(tapTimer); |
| 427 | + if (sidebar.classList.contains('hidden')) { |
| 428 | + toggleSidebar(false); |
| 429 | + } |
| 430 | + tapCount = 0; |
| 431 | + } |
| 432 | + } |
| 433 | + |
| 434 | + // Dark mode toggle |
| 435 | + function toggleDarkMode() { |
| 436 | + const body = document.body; |
| 437 | + body.classList.toggle('dark-mode'); |
| 438 | + const isDark = body.classList.contains('dark-mode'); |
| 439 | + localStorage.setItem('dark-mode', isDark); |
| 440 | + const icon = document.querySelector('.dark-toggle i'); |
| 441 | + if (icon) { |
| 442 | + icon.classList.remove('fa-moon', 'fa-sun'); |
| 443 | + icon.classList.add(isDark ? 'fa-sun' : 'fa-moon'); |
| 444 | + } else { |
| 445 | + console.error('Dark mode icon not found'); |
| 446 | + } |
| 447 | + // Force re-render of styled elements |
| 448 | + const sidebar = document.getElementById('sidebar'); |
| 449 | + const themeContainer = document.getElementById('theme-time-container'); |
| 450 | + if (sidebar) sidebar.style.display = 'none'; |
| 451 | + if (themeContainer) themeContainer.style.display = 'none'; |
| 452 | + setTimeout(() => { |
| 453 | + if (sidebar) sidebar.style.display = ''; |
| 454 | + if (themeContainer) themeContainer.style.display = ''; |
| 455 | + }, 0); |
| 456 | + } |
| 457 | + |
| 458 | + // Timezone toggle |
| 459 | + function toggleTimezone() { |
| 460 | + currentZone = currentZone === 'IST' ? 'GMT' : 'IST'; |
| 461 | + const tzButton = document.getElementById('tz-toggle-btn'); |
| 462 | + if (tzButton) { |
| 463 | + tzButton.textContent = currentZone; |
| 464 | + updateLiveTime(); |
| 465 | + } else { |
| 466 | + console.error('Timezone button not found'); |
| 467 | + } |
| 468 | + } |
| 469 | + |
| 470 | + // Update live time |
| 471 | + function updateLiveTime() { |
| 472 | + const liveTime = document.getElementById('live-time'); |
| 473 | + if (!liveTime) { |
| 474 | + console.error('Live time element not found'); |
| 475 | + return; |
| 476 | + } |
| 477 | + const now = new Date(); |
| 478 | + let date; |
| 479 | + if (currentZone === 'GMT') { |
| 480 | + date = new Date(now.getTime() + now.getTimezoneOffset() * 60000); |
| 481 | + } else { |
| 482 | + const utc = now.getTime() + now.getTimezoneOffset() * 60000; |
| 483 | + date = new Date(utc + 5.5 * 3600000); |
| 484 | + } |
| 485 | + let h = date.getHours(); |
| 486 | + const m = date.getMinutes().toString().padStart(2, '0'); |
| 487 | + const s = date.getSeconds().toString().padStart(2, '0'); |
| 488 | + const ampm = h >= 12 ? 'PM' : 'AM'; |
| 489 | + h = h % 12 || 12; |
| 490 | + liveTime.textContent = `Time (${currentZone}): ${h}:${m}:${s} ${ampm}`; |
| 491 | + } |
| 492 | + |
| 493 | + // Handle scroll for theme/time container |
| 494 | + function handleScroll() { |
| 495 | + const themeTimeContainer = document.getElementById('theme-time-container'); |
| 496 | + if (themeTimeContainer) { |
| 497 | + if (window.scrollY > SCROLL_THRESHOLD) { |
| 498 | + themeTimeContainer.classList.add('hidden'); |
| 499 | + } else { |
| 500 | + themeTimeContainer.classList.remove('hidden'); |
| 501 | + } |
| 502 | + } else { |
| 503 | + console.error('Theme/time container not found'); |
| 504 | + } |
| 505 | + } |
| 506 | + |
| 507 | + // On load: init dark mode, sidebar state, listeners, time, SW |
| 508 | + window.onload = () => { |
| 509 | + // Initialize dark mode |
| 510 | + const isDark = localStorage.getItem('dark-mode') === 'true'; |
| 511 | + const body = document.body; |
| 512 | + if (body) { |
| 513 | + if (isDark) { |
| 514 | + body.classList.add('dark-mode'); |
| 515 | + const icon = document.querySelector('.dark-toggle i'); |
| 516 | + if (icon) icon.classList.replace('fa-moon', 'fa-sun'); |
| 517 | + } |
| 518 | + } else { |
| 519 | + console.error('Body element not found'); |
| 520 | + } |
| 521 | + |
| 522 | + // Initialize sidebar state |
| 523 | + const sidebar = document.getElementById('sidebar'); |
| 524 | + const toggleBtn = document.querySelector('.toggle-btn'); |
| 525 | + const content = document.querySelector('.content'); |
| 526 | + if (sidebar && toggleBtn && content) { |
| 527 | + const isSidebarHidden = localStorage.getItem('sidebar-hidden') === 'true'; |
| 528 | + sidebar.classList.toggle('hidden', isSidebarHidden); |
| 529 | + content.style.marginLeft = isSidebarHidden ? '0' : '210px'; |
| 530 | + if (window.innerWidth > 768) { |
| 531 | + toggleBtn.style.display = isSidebarHidden ? 'block' : 'none'; |
| 532 | + } else { |
| 533 | + toggleBtn.style.display = 'block'; |
| 534 | + } |
| 535 | + } else { |
| 536 | + console.error('Sidebar, toggle button, or content not found'); |
| 537 | + } |
| 538 | + |
| 539 | + // Show tooltip on first visit or force for testing |
| 540 | + const tooltip = document.getElementById('tooltip'); |
| 541 | + if (tooltip) { |
| 542 | + const tooltipShown = localStorage.getItem('tooltip-shown'); |
| 543 | + if (!tooltipShown) { |
| 544 | + console.log('Showing tooltip for first visit'); // Debug |
| 545 | + setTimeout(() => { |
| 546 | + tooltip.classList.add('visible'); |
| 547 | + setTimeout(() => { |
| 548 | + tooltip.classList.remove('visible'); |
| 549 | + localStorage.setItem('tooltip-shown', 'true'); |
| 550 | + }, 5000); |
| 551 | + }, 1000); |
| 552 | + } else { |
| 553 | + console.log('Tooltip already shown, skipping'); // Debug |
| 554 | + } |
| 555 | + } else { |
| 556 | + console.error('Tooltip element not found'); |
| 557 | + } |
| 558 | + |
| 559 | + // Add tap/click and scroll listeners |
| 560 | + document.addEventListener('click', handleTap); |
| 561 | + document.addEventListener('touchstart', handleTap, { passive: true }); |
| 562 | + window.addEventListener('scroll', handleScroll, { passive: true }); |
| 563 | + |
| 564 | + // Initialize active link |
| 565 | + updateActiveLink(); |
| 566 | + |
| 567 | + updateLiveTime(); |
| 568 | + setInterval(updateLiveTime, 1000); |
| 569 | + |
| 570 | + if ('serviceWorker' in navigator) { |
| 571 | + navigator.serviceWorker |
| 572 | + .register('/JavaEvolution-Learning-Growing-Mastering/assets/sw.js') |
| 573 | + .then(() => console.log('Service Worker Registered')) |
| 574 | + .catch(err => console.error('SW registration failed', err)); |
| 575 | + } |
| 576 | + }; |
| 577 | + </script> |
| 578 | +</head> |
| 579 | + |
264 | 580 | <body> |
265 | 581 | <!-- Dark Mode & Timezone Controls --> |
266 | 582 | <div id="theme-time-container"> |
|
0 commit comments