🐘
index_copy.php
Back
📝 Php ⚡ Executable Ctrl+S: Save • Ctrl+R: Run • Ctrl+F: Find
<?php // Force login + disable caching session_start(); require_once __DIR__ . '/../core/db_config.php'; // Anti-cache headers (dev) header('Cache-Control: no-store, no-cache, must-revalidate, max-age=0'); header('Cache-Control: post-check=0, pre-check=0', false); header('Pragma: no-cache'); header('Expires: 0'); // Redirect if not logged in if (empty($_SESSION['username'])) { $redirect = urlencode($_SERVER['REQUEST_URI'] ?? '/'); header("Location: /core/auth/login.php?redirect={$redirect}"); exit; } // Cache-busting helper (absolute & relative paths) function asset($path) { $isAbsolute = strlen($path) && $path[0] === '/'; $abs = $isAbsolute ? rtrim($_SERVER['DOCUMENT_ROOT'], '/') . $path : __DIR__ . '/' . $path; $v = is_file($abs) ? filemtime($abs) : time(); return $path . '?v=' . $v; } ?> <!DOCTYPE html> <html lang="en"> <head> <meta charset="UTF-8" /> <meta name="viewport" content="width=device-width, initial-scale=1" /> <title>App Index</title> <!-- Shared overlay CSS --> <link rel="stylesheet" href="<?= asset('/core/css/overlay.css') ?>"> <style> /* Global */ html, body { height: 100%; margin: 0; overscroll-behavior-y: contain; } body { background:#0b0f14; color:#e6edf3; font-family: system-ui, -apple-system, Segoe UI, Roboto, Inter, "Helvetica Neue", Arial; } .body-lock { overflow: hidden !important; touch-action: none; } /* Topbar */ .topbar { position: sticky; top: 0; z-index: 5; background: linear-gradient(180deg, rgba(11,15,20,.95), rgba(11,15,20,.85)); border-bottom: 1px solid #1e2633; backdrop-filter: blur(6px); } .topbar-inner { max-width:1000px; margin:0 auto; padding:.75rem; display:flex; align-items:center; gap:.75rem; /* no overflow here; let #buttonRow handle scrolling */ } /* Chips row: takes remaining space and scrolls horizontally */ #buttonRow { flex: 1 1 auto; min-width: 0; /* allow shrinking */ display: flex; gap: .75rem; align-items: center; overflow-x: auto; overflow-y: hidden; scrollbar-width: thin; -webkit-overflow-scrolling: touch; } /* 3-dots container: pinned at far right */ #menuContainer { flex: 0 0 auto; margin-left: .25rem; position: relative; } .chip { flex:0 0 auto; border:1px solid #2a3648; background:#1a2332; color:#e6edf3; padding:.55rem .9rem; border-radius:999px; font-weight:600; cursor:pointer; transition: background .15s ease; } .chip:hover { background:#263244; } /* Content */ .container { max-width:1000px; margin:1.25rem auto; padding:0 .75rem; } .lead { color:#9aa4b2; } /* 3-dots dropdown */ .menu-trigger { width:38px; text-align:center; } .menu-list { display:none; position:absolute; right:0; top:calc(100% + 6px); background:#1a2332; border:1px solid #2a3648; border-radius:10px; min-width:180px; padding:.25rem 0; z-index:9999; box-shadow: 0 10px 30px rgba(0,0,0,.3); } .menu-list.open { display:block; } .menu-item { display:block; width:100%; text-align:left; background:none; border:none; color:#e6edf3; padding:.6rem 1rem; cursor:pointer; font: inherit; } .menu-item:hover { background:#263244; } </style> </head> <body> <?php include __DIR__ . '/../core/auth/header.php'; ?> <header class="topbar" aria-label="Top navigation"> <div class="topbar-inner"> <div id="buttonRow" role="tablist" aria-label="App sections"></div> <div id="menuContainer" aria-label="More actions"></div> </div> </header> <main class="container"> <h1>Modular Overlay Index</h1> <p class="lead">Each module adds its own button and overlay content. If modules register extra actions, a 3-dots menu appears on the right.</p> </main> <!-- 1) Empty globals for modules --> <script> window.AppItems = []; // overlay sections window.AppMenu = []; // 3-dots actions (optional) </script> <!-- 2) Shared overlay --> <script src="<?= asset('/core/js/overlay.js') ?>" defer></script> <!-- 3) Modules --> <script src="<?= asset('code.js') ?>" defer></script> <script src="<?= asset('menu.js') ?>" defer></script> <script src="<?= asset('module.js') ?>" defer></script> <!-- 4) Render chips + menu --> <script defer> document.addEventListener('DOMContentLoaded', () => { // Buttons from AppItems const row = document.getElementById('buttonRow'); row.innerHTML = ''; (window.AppItems || []).forEach((item, i) => { const btn = document.createElement('button'); btn.className = 'chip'; btn.textContent = item.title || `Item ${i+1}`; btn.onclick = () => window.AppOverlay && AppOverlay.open(window.AppItems, i, btn); row.appendChild(btn); }); // 3-dots menu const menuContainer = document.getElementById('menuContainer'); menuContainer.innerHTML = ''; const menuItems = window.AppMenu || []; if (menuItems.length > 0) { const trigger = document.createElement('button'); trigger.className = 'chip menu-trigger'; trigger.type = 'button'; trigger.setAttribute('aria-haspopup','true'); trigger.setAttribute('aria-expanded','false'); trigger.setAttribute('aria-label','More actions'); trigger.textContent = '⋮'; menuContainer.appendChild(trigger); const dropdown = document.createElement('div'); dropdown.className = 'menu-list'; dropdown.setAttribute('role','menu'); dropdown.setAttribute('aria-hidden','true'); menuContainer.appendChild(dropdown); menuItems.forEach((m, idx) => { const item = document.createElement('button'); item.className = 'menu-item'; item.type = 'button'; item.setAttribute('role','menuitem'); item.textContent = m.label || `Action ${idx+1}`; item.onclick = () => { closeMenu(); try { m.action && m.action(); } catch(e) { console.error(e); } }; dropdown.appendChild(item); }); function openMenu(){ dropdown.classList.add('open'); dropdown.setAttribute('aria-hidden','false'); trigger.setAttribute('aria-expanded','true'); document.addEventListener('click', handleOutside); document.addEventListener('keydown', escClose); } function closeMenu(){ dropdown.classList.remove('open'); dropdown.setAttribute('aria-hidden','true'); trigger.setAttribute('aria-expanded','false'); document.removeEventListener('click', handleOutside); document.removeEventListener('keydown', escClose); } function handleOutside(e){ if (!menuContainer.contains(e.target)) closeMenu(); } function escClose(e){ if (e.key === 'Escape') closeMenu(); } trigger.addEventListener('click', (e)=>{ e.stopPropagation(); dropdown.classList.contains('open') ? closeMenu() : openMenu(); }); } }); </script> </body> </html>