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