![]() |
![]() |
You are not logged in. Please Login.
|
| If you don't want to register but you would like to comment login using the temp account. ID sp_cc Password 12345678. If you want me to know who you are leave your first name or handle at the end of your post. http://tiny.cc/energ. |
![]()
Posts: 137
Registered: 2013-12-25 |
I made this little directory scanner so that it will look at certain directories and then I can be able to upload them easily to my a I so he could visually see what they look like it prints out a text format of the directory structure. ------------------------------------------------------------------------------------------------------------------ It's a miracle this file is actually done it's complete it works well amazing I don't know where I'm gonna put it yet but I gotta put it somewhere Where it will reside permanently, Currently it's here http://localhost/vb3/VisualJS/projects/builder_my_try1/dir_tree.php. ------------------------------------------------------------------------------------------------------------------ Here is the PHP file for the program. <?php // Function to scan directory and return structure function scanDirectory($path) { if (!is_dir($path)) { return array('error' => "Not a valid directory path"); } $result = array(); $items = scandir($path); foreach ($items as $item) { if ($item == '.' || $item == '..') continue; $fullPath = $path . DIRECTORY_SEPARATOR . $item; $isDir = is_dir($fullPath); $result[] = array( 'name' => $item, 'path' => $fullPath, 'is_dir' => $isDir, 'children' => $isDir ? scanDirectory($fullPath) : array() ); } return $result; } // Process request $output = array(); if (isset($_GET['path']) && !empty($_GET['path'])) { $requestedPath = trim($_GET['path']); $output = scanDirectory($requestedPath); } else if (isset($_GET['action']) && $_GET['action'] == 'get_structure' && isset($_GET['path'])) { $requestedPath = trim($_GET['path']); $output = scanDirectory($requestedPath); header('Content-Type: application/json'); echo json_encode($output); exit; } ?> <!DOCTYPE html> <html lang="en"> <head> <meta charset="UTF-8"> <meta name="viewport" content="width=device-width, initial-scale=1.0"> <title>Directory Structure Explorer</title> <style> * { box-sizing: border-box; font-family: 'Segoe UI', Tahoma, Geneva, Verdana, sans-serif; } body { margin: 0; padding: 20px; background: rgba(106, 17, 203, 0.7); /* Semi-transparent background */ height: 100vh; overflow: hidden; display: flex; justify-content: center; align-items: center; backdrop-filter: blur(5px); /* Frosted glass effect */ } .window { width: 600px; height: 600px; background: white; border-radius: 12px; box-shadow: 0 20px 40px rgba(0, 0, 0, 0.3); overflow: hidden; display: flex; flex-direction: column; position: relative; resize: both; /* Allow resizing */ } .header { background: #4a6fa5; color: white; padding: 15px; text-align: center; font-weight: bold; font-size: 18px; cursor: move; position: relative; user-select: none; } .header-controls { position: absolute; right: 15px; top: 50%; transform: translateY(-50%); display: flex; align-items: center; } .control-btn { width: 12px; height: 12px; border-radius: 50%; display: inline-block; margin-left: 8px; cursor: pointer; transition: transform 0.3s; } .close { background: #ff5f56; } .minimize { background: #ffbd2e; } .maximize { background: #27c93f; } /* Animation for processing state */ .processing .close { animation: pulse-red 1.5s infinite; } .processing .minimize { animation: pulse-yellow 1.5s infinite; animation-delay: 0.5s; } .processing .maximize { animation: pulse-green 1.5s infinite; animation-delay: 1s; } @keyframes pulse-red { 0%, 100% { transform: scale(1); opacity: 1; } 50% { transform: scale(1.2); opacity: 0.7; } } @keyframes pulse-yellow { 0%, 100% { transform: scale(1); opacity: 1; } 50% { transform: scale(1.2); opacity: 0.7; } } @keyframes pulse-green { 0%, 100% { transform: scale(1); opacity: 1; } 50% { transform: scale(1.2); opacity: 0.7; } } .content { padding: 20px; flex-grow: 1; display: flex; flex-direction: column; overflow: hidden; } .input-group { margin-bottom: 15px; display: flex; } input[type="text"] { flex-grow: 1; padding: 12px; border: 1px solid #ddd; border-radius: 6px 0 0 6px; font-size: 14px; } button { background: #4a6fa5; color: white; border: none; padding: 12px 20px; border-radius: 0 6px 6px 0; cursor: pointer; font-weight: bold; transition: background 0.3s; } button:hover { background: #385d8a; } .output { margin-top: 20px; padding: 15px; background: #f8f9fa; border-radius: 6px; border: 1px solid #eee; flex-grow: 1; overflow: auto; font-family: 'Consolas', 'Courier New', monospace; font-size: 14px; line-height: 1.5; } .dir-item, .file-item { margin: 4px 0; position: relative; cursor: pointer; user-select: none; display: flex; align-items: center; } .dir-item { color: #2c5aa0; font-weight: 500; } .expand-icon { width: 16px; margin-right: 4px; text-align: center; transition: transform 0.2s; } .dir-item.expanded .expand-icon { transform: rotate(90deg); } .file-item { color: #333; padding-left: 20px; } .item-icon { margin-right: 6px; font-size: 14px; width: 18px; text-align: center; } .children { margin-left: 16px; display: none; border-left: 1px dashed #ddd; padding-left: 8px; } .dir-item.expanded > .children { display: block; } .item-name { display: inline-block; padding: 2px 4px; border-radius: 3px; } .dir-item:hover > .item-name, .file-item:hover > .item-name { background: #e6f3ff; } .footer { padding: 10px; text-align: center; font-size: 11px; color: #777; border-top: 1px solid #eee; display: flex; justify-content: space-between; align-items: center; } .footer button { padding: 6px 12px; font-size: 12px; border-radius: 4px; } .compact-btn { background: #6c757d; } .compact-btn:hover { background: #5a6268; } .export-btn { background: #28a745; } .export-btn:hover { background: #218838; } .copy-btn { background: #17a2b8; } .copy-btn:hover { background: #138496; } .loading { color: #777; font-style: italic; } .error { color: #d9534f; font-weight: 500; } .text-output { display: none; width: 100%; height: 100%; padding: 10px; border: 1px solid #ccc; border-radius: 4px; font-family: 'Courier New', monospace; font-size: 12px; white-space: pre; background: #f8f9fa; } .toast { position: fixed; bottom: 20px; left: 50%; transform: translateX(-50%); background: #333; color: white; padding: 10px 20px; border-radius: 4px; opacity: 0; transition: opacity 0.3s; z-index: 1000; } .toast.show { opacity: 1; } </style> </head> <body> <div class="window" id="mainWindow"> <div class="header" id="windowHeader"> Directory Structure Explorer <div class="header-controls"> <span class="control-btn close" id="closeBtn"></span> <span class="control-btn minimize" id="minimizeBtn"></span> <span class="control-btn maximize" id="maximizeBtn"></span> </div> </div> <div class="content"> <div class="input-group"> <input type="text" id="pathInput" placeholder="Enter directory path (e.g., C:xampphtdocs)" value="<?php echo isset($_GET['path']) ? htmlspecialchars($_GET['path']) : ''; ?>"> <button id="generateBtn">Explore</button> </div> <div class="output" id="output"> <?php if (isset($output['error'])): ?> <div class="error"><?php echo htmlspecialchars($output['error']); ?></div> <?php elseif (!empty($output)): ?> <div class="directory-tree" id="directoryTree"> <?php function renderTree($items) { foreach ($items as $item) { $isDir = $item['is_dir']; $hasChildren = !empty($item['children']); echo '<div class="' . ($isDir ? 'dir-item' : 'file-item') . '" data-path="' . htmlspecialchars($item['path']) . '">'; if ($isDir) { echo '<span class="expand-icon">▶</span>'; echo '<span class="item-icon"></span>'; } else { echo '<span class="item-icon" style="visibility: hidden;"></span>'; echo '<span class="item-icon"></span>'; } echo '<span class="item-name">' . htmlspecialchars($item['name']) . '</span>'; if ($isDir && $hasChildren) { echo '<div class="children">'; renderTree($item['children']); echo '</div>'; } echo '</div>'; } } renderTree($output); ?> </div> <?php else: ?> <div class="loading">Enter a directory path and click "Explore" to see the directory structure.</div> <?php endif; ?> </div> <textarea class="text-output" id="textOutput" readonly></textarea> </div> <div class="footer"> <button id="compactBtn" class="compact-btn">Compact View</button> <span>PHP Directory Explorer</span> <div> <button id="copyBtn" class="copy-btn">Copy to Clipboard</button> <button id="exportBtn" class="export-btn">Export as Text</button> </div> </div> </div> <div class="toast" id="toast">Copied to clipboard!</div> <script> document.addEventListener('DOMContentLoaded', function() { const output = document.getElementById('output'); const generateBtn = document.getElementById('generateBtn'); const pathInput = document.getElementById('pathInput'); const windowElement = document.getElementById('mainWindow'); const header = document.getElementById('windowHeader'); const compactBtn = document.getElementById('compactBtn'); const copyBtn = document.getElementById('copyBtn'); const exportBtn = document.getElementById('exportBtn'); const closeBtn = document.getElementById('closeBtn'); const minimizeBtn = document.getElementById('minimizeBtn'); const maximizeBtn = document.getElementById('maximizeBtn'); const textOutput = document.getElementById('textOutput'); const directoryTree = document.getElementById('directoryTree'); const toast = document.getElementById('toast'); let isCompactView = false; let isProcessing = false; // Load saved preferences const savedPath = localStorage.getItem('dirExplorer_path'); const savedPosition = JSON.parse(localStorage.getItem('dirExplorer_position') || '{}'); if (savedPath) { pathInput.value = savedPath; } if (savedPosition.x !== undefined && savedPosition.y !== undefined) { windowElement.style.position = 'absolute'; windowElement.style.left = savedPosition.x + 'px'; windowElement.style.top = savedPosition.y + 'px'; } // Make window draggable let isDragging = false; let dragOffset = {x: 0, y: 0}; header.addEventListener('mousedown', function(e) { isDragging = true; const rect = windowElement.getBoundingClientRect(); dragOffset.x = e.clientX - rect.left; dragOffset.y = e.clientY - rect.top; windowElement.style.cursor = 'move'; e.preventDefault(); }); document.addEventListener('mousemove', function(e) { if (isDragging) { windowElement.style.position = 'absolute'; windowElement.style.left = (e.clientX - dragOffset.x) + 'px'; windowElement.style.top = (e.clientY - dragOffset.y) + 'px'; // Save position localStorage.setItem('dirExplorer_position', JSON.stringify({ x: e.clientX - dragOffset.x, y: e.clientY - dragOffset.y })); } }); document.addEventListener('mouseup', function() { isDragging = false; windowElement.style.cursor = 'default'; }); // Show toast notification function showToast(message) { toast.textContent = message; toast.classList.add('show'); setTimeout(() => { toast.classList.remove('show'); }, 2000); } // Set processing state with visual feedback function setProcessing(state) { isProcessing = state; if (state) { header.classList.add('processing'); generateBtn.disabled = true; generateBtn.textContent = 'Scanning...'; } else { header.classList.remove('processing'); generateBtn.disabled = false; generateBtn.textContent = 'Explore'; } } // Handle directory expansion output.addEventListener('click', function(e) { let target = e.target; // Find the parent directory item if a child element was clicked while (target && !target.classList.contains('dir-item') && target !== output) { target = target.parentElement; } if (target && target.classList.contains('dir-item')) { // Set processing state setProcessing(true); // Toggle the expanded class target.classList.toggle('expanded'); // If this is the first expansion, load children via AJAX if needed const children = target.querySelector('.children'); if (children && children.children.length === 0) { const path = target.getAttribute('data-path'); if (path) { children.innerHTML = '<div class="loading">Loading...</div>'; // AJAX request to get directory contents const xhr = new xmlHttpRequest(); xhr.open('GET', '?action=get_structure&path=' + encodeURIComponent(path), true); xhr.onload = function() { if (xhr.status === 200) { try { const data = JSON.parse(xhr.responseText); if (data.error) { children.innerHTML = '<div class="error">' + data.error + '</div>'; } else { children.innerHTML = ''; renderTree(data, children); } } catch (e) { children.innerHTML = '<div class="error">Error parsing response</div>'; } } else { children.innerHTML = '<div class="error">Error loading directory</div>'; } setProcessing(false); }; xhr.onerror = function() { children.innerHTML = '<div class="error">Request failed</div>'; setProcessing(false); }; xhr.send(); return; } } // If no AJAX call was needed, reset processing state after a short delay setTimeout(() => setProcessing(false), 300); } }); // Generate button handler generateBtn.addEventListener('click', function() { const path = pathInput.value.trim(); if (path) { setProcessing(true); localStorage.setItem('dirExplorer_path', path); window.location.href = '?path=' + encodeURIComponent(path); } }); // Enter key handler pathInput.addEventListener('keypress', function(e) { if (e.key === 'Enter') { generateBtn.click(); } }); // Compact view button compactBtn.addEventListener('click', function() { if (isCompactView) { // Expand view windowElement.style.width = '600px'; windowElement.style.height = '600px'; compactBtn.textContent = 'Compact View'; output.style.display = 'block'; textOutput.style.display = 'none'; } else { // Compact view windowElement.style.width = '300px'; windowElement.style.height = '400px'; compactBtn.textContent = 'Expand View'; output.style.display = 'none'; textOutput.style.display = 'block'; // Generate text representation if (directoryTree) { textOutput.value = generateTextTree(directoryTree); } } isCompactView = !isCompactView; }); // Copy to clipboard button copyBtn.addEventListener('click', function() { if (directoryTree) { const textTree = generateTextTree(directoryTree); // Use the modern Clipboard API navigator.clipboard.writeText(textTree).then(function() { showToast('Directory structure copied to clipboard!'); }).catch(function(err) { // Fallback for older browsers textOutput.value = textTree; textOutput.select(); document.execCommand('copy'); showToast('Copied to clipboard!'); }); } }); // Export button exportBtn.addEventListener('click', function() { if (directoryTree) { const textTree = generateTextTree(directoryTree); const blob = new Blob([textTree], { type: 'text/plain' }); const url = URL.createobjectURL(blob); const a = document.createElement('a'); a.href = url; a.download = 'directory_structure.txt'; document.body.appendChild(a); a.click(); document.body.removeChild(a); URL.revokeobjectURL(url); showToast('File downloaded!'); } }); // Window control buttons if (closeBtn) { closeBtn.addEventListener('click', function() { window.close(); }); } if (minimizeBtn) { minimizeBtn.addEventListener('click', function() { windowElement.style.display = windowElement.style.display === 'none' ? 'flex' : 'none'; }); } if (maximizeBtn) { let isMaximized = false; maximizeBtn.addEventListener('click', function() { if (isMaximized) { windowElement.style.width = '600px'; windowElement.style.height = '600px'; windowElement.style.top = ''; windowElement.style.left = ''; } else { windowElement.style.width = '90%'; windowElement.style.height = '90%'; windowElement.style.top = '5%'; windowElement.style.left = '5%'; } isMaximized = !isMaximized; }); } // Function to generate text tree representation function generateTextTree(element, level = 0, prefix = '') { let result = ''; const items = element.children; for (let i = 0; i < items.length; i++) { const item = items[i]; const isLast = i === items.length - 1; const newPrefix = level === 0 ? '' : prefix + (isLast ? ' ' : '│ '); if (item.classList.contains('dir-item') || item.classList.contains('file-item')) { const name = item.querySelector('.item-name'); const itemPrefix = level === 0 ? '' : prefix + (isLast ? '└── ' : '├── '); result += itemPrefix + name.textContent + 'n'; // Process children const children = item.querySelector('.children'); if (children && item.classList.contains('expanded')) { result += generateTextTree(children, level + 1, newPrefix); } } } return result; } // Function to render directory tree function renderTree(items, parentElement) { items.forEach(function(item) { const div = document.createElement('div'); div.className = item.is_dir ? 'dir-item' : 'file-item'; div.setAttribute('data-path', item.path); if (item.is_dir) { const expandIcon = document.createElement('span'); expandIcon.className = 'expand-icon'; expandIcon.textContent = '▶'; div.appendChild(expandIcon); const icon = document.createElement('span'); icon.className = 'item-icon'; icon.textContent = ''; div.appendChild(icon); } else { // Add invisible spacer for files to align with folders const spacer = document.createElement('span'); spacer.className = 'item-icon'; spacer.style.visibility = 'hidden'; spacer.textContent = ''; div.appendChild(spacer); const icon = document.createElement('span'); icon.className = 'item-icon'; icon.textContent = ''; div.appendChild(icon); } const name = document.createElement('span'); name.className = 'item-name'; name.textContent = item.name; div.appendChild(name); parentElement.appendChild(div); if (item.is_dir && item.children && item.children.length > 0) { const childrenDiv = document.createElement('div'); childrenDiv.className = 'children'; div.appendChild(childrenDiv); renderTree(item.children, childrenDiv); } }); } // Focus the input field on load pathInput.focus(); }); </script> </body> </html> |
|
Last edited by: cgetty on Aug 21, 2025 6:22:34 am
| |