1- <!--
2- <!DOCTYPE html>
3- <html lang="en">
4- <head>
5- <meta charset="UTF-8" />
6- <meta name="viewport" content="width=device-width, initial-scale=1.0" />
7-
8- <!– Font Awesome –>
9- <link
10- rel="stylesheet"
11- href="https://cdnjs.cloudflare.com/ajax/libs/font-awesome/6.0.0/css/all.min.css"
12- />
13-
14- <!– Favicons –>
15- <link
16- rel="icon" type="image/png"
17- href="{{ '/assets/favicon-96x96.png' | relative_url }}"
18- sizes="96x96"
19- />
20- <link
21- rel="icon" type="image/svg+xml"
22- href="{{ '/assets/favicon.svg' | relative_url }}"
23- />
24- <link
25- rel="shortcut icon"
26- href="{{ '/assets/favicon.ico' | relative_url }}"
27- />
28- <link
29- rel="apple-touch-icon"
30- sizes="180x180"
31- href="{{ '/assets/apple-touch-icon.png' | relative_url }}"
32- />
33- <meta name="apple-mobile-web-app-title" content="Java" />
34- <link
35- rel="manifest"
36- href="/JavaEvolution-Learning-Growing-Mastering/assets/site.webmanifest"
37- />
38- <meta name="theme-color" content="#ffffff" />
39-
40- <title>{{ page.title }}</title>
41- <link
42- rel="stylesheet"
43- href="{{ '/assets/style.css' | relative_url }}"
44- />
45-
46- <script>
47- // Current timezone tracker
48- let currentZone = 'IST';
49- let tapCount = 0;
50- let tapTimer = null;
51- const TAP_TIMEOUT = 300; // ms for double-tap detection
52- const SCROLL_THRESHOLD = 100; // px to hide theme/time container
53-
54- // Update active link based on URL
55- function updateActiveLink() {
56- const currentPath = window.location.pathname;
57- const baseUrl = '{{ site.baseurl }}' || '';
58- console.log('Current Path:', currentPath, 'Base URL:', baseUrl); // Debug
59- document.querySelectorAll('.sidebar-link').forEach(link => {
60- link.classList.remove('active');
61- const href = link.getAttribute('href').replace(baseUrl, ''); // Normalize href
62- if (href === currentPath || (currentPath === '/' && href === '/')) {
63- link.classList.add('active');
64- console.log('Active Link Set:', href); // Debug
65- }
66- });
67- }
68-
69- // Sidebar toggle
70- function toggleSidebar(isHidden) {
71- const sidebar = document.getElementById('sidebar');
72- const toggleBtn = document.querySelector('.toggle-btn');
73- const content = document.querySelector('.content');
74- if (!sidebar) {
75- console.error('Sidebar element not found');
76- return;
77- }
78- sidebar.classList.toggle('hidden', isHidden);
79- content.style.marginLeft = isHidden ? '0' : '210px'; // Force margin update
80- localStorage.setItem('sidebar-hidden', isHidden);
81- if (window.innerWidth > 768) {
82- toggleBtn.style.display = isHidden ? 'block' : 'none';
83- } else {
84- toggleBtn.style.display = 'block';
85- }
86- updateActiveLink();
87- }
88-
89- // Handle tap/click events
90- function handleTap(event) {
91- const sidebar = document.getElementById('sidebar');
92- const target = event.target;
93- if (!sidebar) {
94- console.error('Sidebar not found during tap');
95- return;
96- }
97-
98- // Allow taps outside interactive elements to trigger hide/show
99- if (
100- target.closest('#sidebar') ||
101- target.closest('#theme-time-container') ||
102- target.closest('.toggle-btn') ||
103- target.closest('.tooltip')
104- ) {
105- return;
106- }
107-
108- tapCount++;
109- if (tapCount === 1) {
110- tapTimer = setTimeout(() => {
111- if (!sidebar.classList.contains('hidden')) {
112- toggleSidebar(true);
113- }
114- tapCount = 0;
115- }, TAP_TIMEOUT);
116- } else if (tapCount === 2) {
117- clearTimeout(tapTimer);
118- if (sidebar.classList.contains('hidden')) {
119- toggleSidebar(false);
120- }
121- tapCount = 0;
122- }
123- }
124-
125- // Dark mode toggle
126- function toggleDarkMode() {
127- const body = document.body;
128- body.classList.toggle('dark-mode');
129- const isDark = body.classList.contains('dark-mode');
130- localStorage.setItem('dark-mode', isDark);
131- const icon = document.querySelector('.dark-toggle i');
132- if (icon) {
133- icon.classList.remove('fa-moon', 'fa-sun');
134- icon.classList.add(isDark ? 'fa-sun' : 'fa-moon');
135- } else {
136- console.error('Dark mode icon not found');
137- }
138- // Force re-render of styled elements
139- const sidebar = document.getElementById('sidebar');
140- const themeContainer = document.getElementById('theme-time-container');
141- if (sidebar) sidebar.style.display = 'none'; // Trigger reflow
142- if (themeContainer) themeContainer.style.display = 'none';
143- setTimeout(() => {
144- if (sidebar) sidebar.style.display = '';
145- if (themeContainer) themeContainer.style.display = '';
146- }, 0);
147- }
148-
149- // Timezone toggle
150- function toggleTimezone() {
151- currentZone = currentZone === 'IST' ? 'GMT' : 'IST';
152- const tzButton = document.getElementById('tz-toggle-btn');
153- if (tzButton) {
154- tzButton.textContent = currentZone;
155- updateLiveTime();
156- } else {
157- console.error('Timezone button not found');
158- }
159- }
160-
161- // Update live time
162- function updateLiveTime() {
163- const liveTime = document.getElementById('live-time');
164- if (!liveTime) {
165- console.error('Live time element not found');
166- return;
167- }
168- const now = new Date();
169- let date;
170- if (currentZone === 'GMT') {
171- date = new Date(now.getTime() + now.getTimezoneOffset() * 60000);
172- } else {
173- const utc = now.getTime() + now.getTimezoneOffset() * 60000;
174- date = new Date(utc + 5.5 * 3600000);
175- }
176- let h = date.getHours();
177- const m = date.getMinutes().toString().padStart(2, '0');
178- const s = date.getSeconds().toString().padStart(2, '0');
179- const ampm = h >= 12 ? 'PM' : 'AM';
180- h = h % 12 || 12;
181- liveTime.textContent = `Time (${currentZone}): ${h}:${m}:${s} ${ampm}`;
182- }
183-
184- // Handle scroll for theme/time container
185- function handleScroll() {
186- const themeTimeContainer = document.getElementById('theme-time-container');
187- if (themeTimeContainer) {
188- if (window.scrollY > SCROLL_THRESHOLD) {
189- themeTimeContainer.classList.add('hidden');
190- } else {
191- themeTimeContainer.classList.remove('hidden');
192- }
193- } else {
194- console.error('Theme/time container not found');
195- }
196- }
197-
198- // On load: init dark mode, sidebar state, listeners, time, SW
199- window.onload = () => {
200- // Initialize dark mode
201- const isDark = localStorage.getItem('dark-mode') === 'true';
202- const body = document.body;
203- if (body) {
204- if (isDark) {
205- body.classList.add('dark-mode');
206- const icon = document.querySelector('.dark-toggle i');
207- if (icon) icon.classList.replace('fa-moon', 'fa-sun');
208- }
209- } else {
210- console.error('Body element not found');
211- }
212-
213- // Initialize sidebar state
214- const sidebar = document.getElementById('sidebar');
215- const toggleBtn = document.querySelector('.toggle-btn');
216- const content = document.querySelector('.content');
217- if (sidebar && toggleBtn && content) {
218- const isSidebarHidden = localStorage.getItem('sidebar-hidden') === 'true';
219- sidebar.classList.toggle('hidden', isSidebarHidden);
220- content.style.marginLeft = isSidebarHidden ? '0' : '210px';
221- if (window.innerWidth > 768) {
222- toggleBtn.style.display = isSidebarHidden ? 'block' : 'none';
223- } else {
224- toggleBtn.style.display = 'block';
225- }
226- } else {
227- console.error('Sidebar, toggle button, or content not found');
228- }
229-
230- // Add tap/click and scroll listeners
231- document.addEventListener('click', handleTap);
232- document.addEventListener('touchstart', handleTap, { passive: true });
233- window.addEventListener('scroll', handleScroll, { passive: true });
234-
235- // Show tooltip on first visit
236- const tooltip = document.getElementById('tooltip');
237- if (tooltip && !localStorage.getItem('tooltip-shown')) {
238- setTimeout(() => {
239- tooltip.classList.add('visible');
240- setTimeout(() => {
241- tooltip.classList.remove('visible');
242- localStorage.setItem('tooltip-shown', 'true');
243- }, 5000);
244- }, 1000);
245- } else if (!tooltip) {
246- console.error('Tooltip element not found');
247- }
248-
249- // Initialize active link
250- updateActiveLink();
251-
252- updateLiveTime();
253- setInterval(updateLiveTime, 1000);
254-
255- if ('serviceWorker' in navigator) {
256- navigator.serviceWorker
257- .register('/JavaEvolution-Learning-Growing-Mastering/assets/sw.js')
258- .then(() => console.log('Service Worker Registered'))
259- .catch(err => console.error('SW registration failed', err));
260- }
261- };
262- </script>
263- </head>
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-
3111<!DOCTYPE html>
3122< html lang ="en ">
3133< head >
621311 </ div >
622312</ div >
623313</ body >
624- </ html >
314+ </ html >
0 commit comments