script custom index pada htdocs

Riky setyomulyo

 <?php

// --- 1. CONFIGURATION & SETUP ---

$sort_by = isset($_GET['sort']) ? $_GET['sort'] : 'name_asc';

$search_query = isset($_GET['q']) ? trim($_GET['q']) : '';


// Array for sort options to keep the code clean

$sort_options = [

    'name_asc' => 'Name (A-Z)',

    'name_desc' => 'Name (Z-A)',

    'date_desc' => 'Date (Newest)',

    'date_asc' => 'Date (Oldest)'

];


// --- 2. SCANNING & DATA GATHERING ---

$items = [];

$scan = scandir('.');


foreach ($scan as $item) {

    if ($item == '.' || $item == '..' || $item == basename(__FILE__)) {

        continue;

    }

    if ($search_query && stripos($item, $search_query) === false) {

        continue;

    }

    $items[] = [

        'name' => $item,

        'type' => is_dir($item) ? 'folder' : 'file',

        'date' => filemtime($item)

    ];

}


// --- 3. SORTING LOGIC ---

usort($items, function ($a, $b) use ($sort_by) {

    switch ($sort_by) {

        case 'name_desc': return strnatcasecmp($b['name'], $a['name']);

        case 'date_desc': return $b['date'] <=> $a['date'];

        case 'date_asc': return $a['date'] <=> $b['date'];

        case 'name_asc': default: return strnatcasecmp($a['name'], $b['name']);

    }

});


// --- 4. SEPARATE FOR DISPLAY ---

$folders = [];

$files = [];

foreach($items as $item) {

    if ($item['type'] === 'folder') {

        $folders[] = $item;

    } else {

        $files[] = $item;

    }

}

?>

<!DOCTYPE html>

<html lang="en">

<head>

    <meta charset="UTF-8">

    <meta name="viewport" content="width=device-width, initial-scale=1.0">

    <title>Localhost Projects</title>

    <style>

        :root {

            --bg-color: #1a1a1a;

            --card-bg-color: #2c2c2c;

            --text-color: #e0e0e0;

            --title-color: #ffffff;

            --hover-bg-color: #383838;

            --shadow-color: rgba(0, 0, 0, 0.2);

            --icon-color: #9e9e9e;

            --accent-color: #007bff;

            --border-color: #444;

        }


        body {

            font-family: -apple-system, BlinkMacSystemFont, "Segoe UI", Roboto, Helvetica, Arial, sans-serif;

            background-color: var(--bg-color);

            color: var(--text-color);

            margin: 0;

            padding: 2rem;

        }


        .container { max-width: 1200px; margin: 0 auto; }

        .header { border-bottom: 1px solid var(--border-color); padding-bottom: 1rem; margin-bottom: 2rem; }

        .header h1 { color: var(--title-color); margin: 0; }

        .header p { margin: 0.25rem 0 0; color: #b0b0b0; }


        /* --- CONTROLS: Search & Sort --- */

        .controls {

            display: flex;

            flex-wrap: wrap;

            gap: 1rem;

            justify-content: space-between;

            align-items: center;

            margin-bottom: 2rem;

        }


        .search-box {

            flex-grow: 1;

            min-width: 250px;

        }

        

        #search-input {

            width: 100%;

            padding: 0.75rem 1rem;

            border-radius: 6px;

            border: 1px solid var(--border-color);

            background-color: var(--card-bg-color);

            color: var(--text-color);

            font-size: 1rem;

            box-sizing: border-box;

        }

        #search-input:focus { outline: none; border-color: var(--accent-color); }

        

        .sort-box label {

            color: #b0b0b0;

            margin-right: 0.5rem;

            font-size: 0.9rem;

        }


        #sort-select {

            padding: 0.75rem 1rem;

            border-radius: 6px;

            border: 1px solid var(--border-color);

            background-color: var(--card-bg-color);

            color: var(--text-color);

            font-size: 1rem;

            cursor: pointer;

            -webkit-appearance: none;

            -moz-appearance: none;

            appearance: none;

            background-image: url("data:image/svg+xml,%3csvg xmlns='http://www.w3.org/2000/svg' viewBox='0 0 16 16'%3e%3cpath fill='none' stroke='%239e9e9e' stroke-linecap='round' stroke-linejoin='round' stroke-width='2' d='M2 5l6 6 6-6'/%3e%3c/svg%3e");

            background-repeat: no-repeat;

            background-position: right 0.75rem center;

            background-size: 1em;

            padding-right: 2.5rem; /* Make space for the arrow */

        }

        #sort-select:focus { outline: none; border-color: var(--accent-color); }

        

        .grid { display: grid; grid-template-columns: repeat(auto-fill, minmax(220px, 1fr)); gap: 1.5rem; padding: 0; list-style-type: none; }

        .card a { display: flex; align-items: center; padding: 1rem; background-color: var(--card-bg-color); border-radius: 8px; text-decoration: none; color: var(--text-color); transition: all 0.2s ease; height: 100%; box-shadow: 0 2px 5px var(--shadow-color); box-sizing: border-box; }

        .card a:hover { background-color: var(--hover-bg-color); transform: translateY(-5px); box-shadow: 0 8px 15px var(--shadow-color); }

        .card .icon { flex-shrink: 0; margin-right: 1rem; width: 24px; height: 24px; color: var(--icon-color); }

        .card .name { font-weight: 500; word-break: break-all; }

        h2 { color: #c7c7c7; margin-top: 3rem; margin-bottom: 1rem; font-weight: 500; }

        .empty-state { text-align: center; padding: 3rem; color: #777; }

    </style>

</head>

<body>


<div class="container">

    <div class="header">

        <h1>Index of /</h1>

        <p><?php echo htmlspecialchars($_SERVER['SERVER_NAME'] . ':' . $_SERVER['SERVER_PORT']); ?></p>

    </div>


    <div class="controls">

        <div class="search-box">

            <input type="text" id="search-input" placeholder="Search files and folders..." value="<?= htmlspecialchars($search_query) ?>">

        </div>

        

        <form id="sort-form" method="get" class="sort-box">

            <input type="hidden" name="q" value="<?= htmlspecialchars($search_query) ?>">

            

            <label for="sort-select">Sort by:</label>

            <select name="sort" id="sort-select" onchange="this.form.submit()">

                <?php foreach ($sort_options as $value => $label): ?>

                    <option value="<?= $value ?>" <?= ($value == $sort_by) ? 'selected' : '' ?>>

                        <?= $label ?>

                    </option>

                <?php endforeach; ?>

            </select>

        </form>

    </div>

    

    <?php

    $folderIcon = '<svg class="icon" xmlns="http://www.w3.org/2000/svg" viewBox="0 0 24 24" fill="currentColor"><path d="M4 5h16a2 2 0 0 1 2 2v12a2 2 0 0 1-2 2H4a2 2 0 0 1-2-2V7a2 2 0 0 1 2-2zm0 2v2h16V7H4zm0 4v8h16v-8H4z"/></svg>';

    $fileIcon = '<svg class="icon" xmlns="http://www.w3.org/2000/svg" viewBox="0 0 24 24" fill="currentColor"><path d="M6 2a2 2 0 0 0-2 2v16a2 2 0 0 0 2 2h12a2 2 0 0 0 2-2V8l-6-6H6zm8 7h-2V4h2v5zm-2 2h2v5h-2v-5z"/></svg>';

    

    if (empty($folders) && empty($files)) {

        echo "<div class='empty-state'>No files or folders found matching your search.</div>";

    }


    if (!empty($folders)) {

        echo '<h2 id="folders-header">Folders</h2>';

        echo '<ul class="grid" id="folders-grid">';

        foreach ($folders as $folder) {

            echo '<li class="card" data-name="' . htmlspecialchars($folder['name']) . '">';

            echo '<a href="' . htmlspecialchars($folder['name']) . '">';

            echo $folderIcon;

            echo '<span class="name">' . htmlspecialchars($folder['name']) . '</span>';

            echo '</a>';

            echo '</li>';

        }

        echo '</ul>';

    }


    if (!empty($files)) {

        echo '<h2 id="files-header">Files</h2>';

        echo '<ul class="grid" id="files-grid">';

        foreach ($files as $file) {

            echo '<li class="card" data-name="' . htmlspecialchars($file['name']) . '">';

            echo '<a href="' . htmlspecialchars($file['name']) . '">';

            echo $fileIcon;

            echo '<span class="name">' . htmlspecialchars($file['name']) . '</span>';

            echo '</a>';

            echo '</li>';

        }

        echo '</ul>';

    }

    ?>

</div>


<script>

document.addEventListener('DOMContentLoaded', function() {

    const searchInput = document.getElementById('search-input');

    const sortForm = document.getElementById('sort-form');

    const hiddenSearchInput = sortForm.querySelector('input[name="q"]');


    // Live search filtering

    searchInput.addEventListener('keyup', function() {

        const query = this.value.toLowerCase().trim();

        hiddenSearchInput.value = query; // Update hidden input for sorting

        filterItems(query);

    });


    function filterItems(query) {

        let folderCount = 0, fileCount = 0;

        document.querySelectorAll('.card').forEach(card => {

            const name = card.dataset.name.toLowerCase();

            const isVisible = name.includes(query);

            card.style.display = isVisible ? '' : 'none';

            if (isVisible) {

                if (card.parentElement.id === 'folders-grid') folderCount++;

                else fileCount++;

            }

        });

        

        const foldersHeader = document.getElementById('folders-header');

        const filesHeader = document.getElementById('files-header');

        if (foldersHeader) foldersHeader.style.display = folderCount > 0 ? '' : 'none';

        if (filesHeader) filesHeader.style.display = fileCount > 0 ? '' : 'none';

    }


    // Apply initial filter if needed

    if (searchInput.value) {

        filterItems(searchInput.value.toLowerCase().trim());

    }

});

</script>


</body>

</html>

Posting Komentar

Cookie Consent
We serve cookies on this site to analyze traffic, remember your preferences, and optimize your experience.
Oops!
It seems there is something wrong with your internet connection. Please connect to the internet and start browsing again.