// Tree data will be loaded from tree.json file let treeData = []; // All documents are loaded dynamically from HTML files class TreeView { constructor(container, data) { this.container = container; this.data = data; this.activeItem = null; this.init(); } init() { this.render(); this.bindEvents(); loadDocument_index(); } render() { this.container.innerHTML = ''; this.data.forEach(item => { this.renderItem(item, this.container); }); } renderItem(item, parent) { const itemDiv = document.createElement('div'); itemDiv.className = 'tree-item'; itemDiv.dataset.id = item.id; const contentDiv = document.createElement('div'); contentDiv.className = 'tree-content'; const toggleDiv = document.createElement('div'); toggleDiv.className = item.children ? 'tree-toggle collapsed' : 'tree-toggle leaf'; const titleSpan = document.createElement('span'); titleSpan.textContent = item.title; contentDiv.appendChild(toggleDiv); contentDiv.appendChild(titleSpan); itemDiv.appendChild(contentDiv); if (item.children) { const childrenDiv = document.createElement('div'); childrenDiv.className = 'tree-children'; item.children.forEach(child => { this.renderItem(child, childrenDiv); }); itemDiv.appendChild(childrenDiv); } parent.appendChild(itemDiv); } bindEvents() { this.container.addEventListener('click', (e) => { const treeContent = e.target.closest('.tree-content'); if (!treeContent) return; const treeItem = treeContent.closest('.tree-item'); const toggle = treeContent.querySelector('.tree-toggle'); const children = treeItem.querySelector('.tree-children'); if (toggle && toggle.classList.contains('collapsed')) { toggle.classList.remove('collapsed'); toggle.classList.add('expanded'); if (children) { children.classList.add('expanded'); setTimeout(() => { this.container.querySelectorAll('.tree-children.expanded').forEach(el => { el.style.maxHeight = 'none'; }); }, 350); } } else if (toggle && toggle.classList.contains('expanded')) { toggle.classList.remove('expanded'); toggle.classList.add('collapsed'); if (children) { children.style.maxHeight = children.scrollHeight + 'px'; children.offsetHeight; children.style.maxHeight = ''; children.classList.remove('expanded'); } } // Activate element this.setActiveItem(treeItem); // Load document const itemId = treeItem.dataset.id; loadDocument(itemId); if (!treeItem.querySelector('.tree-children') && isMobileViewport()) { closeHamburgerMenu(); } }); } setActiveItem(item) { // Remove previous active item if (this.activeItem) { this.activeItem.querySelector('.tree-content').classList.remove('active'); } // Set new active item this.activeItem = item; item.querySelector('.tree-content').classList.add('active'); } collapseAll() { this.container.querySelectorAll('.tree-children.expanded').forEach(el => { el.style.maxHeight = ''; }); const toggles = this.container.querySelectorAll('.tree-toggle.expanded'); const children = this.container.querySelectorAll('.tree-children.expanded'); toggles.forEach(toggle => { toggle.classList.remove('expanded'); toggle.classList.add('collapsed'); }); children.forEach(child => { child.classList.remove('expanded'); }); } expandAll() { const toggles = this.container.querySelectorAll('.tree-toggle.collapsed'); const children = this.container.querySelectorAll('.tree-children:not(.expanded)'); toggles.forEach(toggle => { toggle.classList.remove('collapsed'); toggle.classList.add('expanded'); }); children.forEach(child => { child.classList.add('expanded'); }); this.container.querySelectorAll('.tree-children.expanded').forEach(el => { el.style.maxHeight = 'none'; }); } } // Initialization let treeView; let isResizing = false; let startX, startWidth; function isMobileViewport() { return window.matchMedia('(max-width: 768px)').matches; } function openHamburgerMenu() { document.getElementById('sidebar').classList.add('hamburger-open'); document.getElementById('hamburgerOverlay').classList.add('active'); document.getElementById('hamburgerBtn').classList.add('active'); } function closeHamburgerMenu() { document.getElementById('sidebar').classList.remove('hamburger-open'); document.getElementById('hamburgerOverlay').classList.remove('active'); document.getElementById('hamburgerBtn').classList.remove('active'); } function getDefaultSidebarWidth() { return 305; } function applySidebarWidth(sidebar, toggleBtn, width) { sidebar.style.width = width + 'px'; if (!sidebar.classList.contains('collapsed')) { toggleBtn.style.left = width + 'px'; } } function getSidebarMinWidth() { return 160; } function getSidebarMaxWidth() { return Math.min(400, Math.max(getSidebarMinWidth(), window.innerWidth - 40)); } function refreshIOSPdfEmbeds() { (function () { const isIOS = /iPad|iPhone|iPod/.test(navigator.userAgent); if (!isIOS) return; const frames = document.querySelectorAll('iframe.pdf-embed'); const mozillaViewerPrefix = 'https://mozilla.github.io/pdf.js/web/viewer.html?file='; frames.forEach(frame => { const src = frame.getAttribute('src') || ''; if (src.startsWith(mozillaViewerPrefix)) { frame.remove(); } }); })(); } // Load tree data from JSON file async function loadTreeData() { try { const response = await fetch('tree.json'); if (response.ok) { treeData = await response.json(); return true; } else { console.error('Failed to load tree.json'); return false; } } catch (error) { console.error('Error loading tree.json:', error); return false; } } document.addEventListener('DOMContentLoaded', async () => { // Load tree data first const dataLoaded = await loadTreeData(); if (!dataLoaded) { console.error('Could not load tree data, using empty tree'); treeData = []; } const treeContainer = document.getElementById('treeContainer'); treeView = new TreeView(treeContainer, treeData); // Collapse/expand all buttons document.getElementById('collapseAll').addEventListener('click', () => { treeView.collapseAll(); }); document.getElementById('expandAll').addEventListener('click', () => { treeView.expandAll(); }); let isCollapsed = false; let savedWidth = 0; const sidebar = document.getElementById('sidebar'); const toggleBtn = document.getElementById('toggleBtn'); const hamburgerBtn = document.getElementById('hamburgerBtn'); const hamburgerOverlay = document.getElementById('hamburgerOverlay'); if (!isMobileViewport()) { applySidebarWidth(sidebar, toggleBtn, getDefaultSidebarWidth()); toggleBtn.classList.add('sidebar-visible'); toggleBtn.style.left = sidebar.offsetWidth + 'px'; } hamburgerBtn.addEventListener('click', () => { if (sidebar.classList.contains('hamburger-open')) { closeHamburgerMenu(); } else { openHamburgerMenu(); } }); hamburgerOverlay.addEventListener('click', () => { closeHamburgerMenu(); }); toggleBtn.addEventListener('click', () => { if(isCollapsed==false){ isCollapsed = true; savedWidth = sidebar.style.width || sidebar.offsetWidth + 'px'; sidebar.classList.add('collapsed'); toggleBtn.classList.remove('sidebar-visible'); toggleBtn.textContent = '▶'; toggleBtn.style.left = '0px'; setTimeout(() => { sidebar.style.width = '0px'; sidebar.style.padding = '0'; sidebar.style.minWidth = '0'; }, 300); }else{ isCollapsed = false; const widthToRestore = savedWidth || (getDefaultSidebarWidth() + 'px'); const widthValue = parseInt(widthToRestore) || getDefaultSidebarWidth(); sidebar.style.width = widthToRestore; sidebar.style.padding = ''; sidebar.style.minWidth = ''; sidebar.offsetWidth; sidebar.classList.remove('collapsed'); toggleBtn.classList.add('sidebar-visible'); toggleBtn.style.left = widthValue + 'px'; toggleBtn.textContent = '◀'; } }); window.addEventListener('resize', () => { if (isMobileViewport()) { closeHamburgerMenu(); return; } if (isCollapsed || isResizing) { return; } const defaultWidth = getDefaultSidebarWidth(); applySidebarWidth(sidebar, toggleBtn, defaultWidth); savedWidth = defaultWidth + 'px'; }); // Resize handle const resizeHandle = document.getElementById('resizeHandle'); resizeHandle.addEventListener('pointerdown', (e) => { if (isCollapsed) { return; } isResizing = true; startX = e.clientX; startWidth = sidebar.offsetWidth; sidebar.classList.add('no-transition'); document.body.style.cursor = 'col-resize'; resizeHandle.setPointerCapture(e.pointerId); e.preventDefault(); }); document.addEventListener('pointermove', (e) => { if (!isResizing) return; const deltaX = e.clientX - startX; const minWidth = getSidebarMinWidth(); const maxWidth = getSidebarMaxWidth(); const newWidth = Math.max(minWidth, Math.min(maxWidth, startWidth + deltaX)); sidebar.style.width = newWidth + 'px'; toggleBtn.style.left = newWidth + 'px'; savedWidth = newWidth + 'px'; e.preventDefault(); }); const stopResizing = () => { if (isResizing) { isResizing = false; sidebar.classList.remove('no-transition'); document.body.style.cursor = ''; } }; document.addEventListener('pointerup', stopResizing); document.addEventListener('pointercancel', stopResizing); }); function loadDocument_index() { const mainContent = document.getElementById('mainContent'); // Load document from HTML file const docPath = `00 Start`; fetch(docPath) .then(response => { if (response.ok) { console.log("Cześć!"); return response.text(); } else { mainContent.innerHTML = '
Select an item from the left panel to load the document
'; } }) .then(content => { mainContent.innerHTML = content; refreshIOSPdfEmbeds(); }) .catch(error => { console.error('Error loading document:', error); mainContent.innerHTML = '
Select an item from the left panel to load the document
'; }); } function loadDocument(docId) { const mainContent = document.getElementById('mainContent'); // Przewiń na górę mainContent.scrollTop = 0; // Load document from HTML file const docPath = `${docId}`; fetch(docPath) .then(response => { if (response.ok) { return response.text(); } else { throw new Error('Document not found'); } }) .then(content => { mainContent.innerHTML = content; refreshIOSPdfEmbeds(); // Opcjonalnie: przewiń ponownie po załadowaniu treści mainContent.scrollTop = 0; }) .catch(error => { console.error('Error loading document:', error); mainContent.innerHTML = '
Document not found
'; }); }