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

Privasi & Cookie
Situs ini menggunakan cookie untuk analitik, menyimpan preferensi, dan meningkatkan pengalaman membaca.
Koneksi Terputus
Koneksi internet Anda terputus. Sambungkan kembali internet lalu muat ulang halaman.