Forum consepet
You are not logged in. Please Login.

Announcements
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.


Posted: Aug 21, 2025 5:35:40 am
cgetty




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>


Powered by myUPB v2.2.7  ·   © PHP Outburst 2002 - 2026

Creative Commons License