First version, for githup; UNSTABLE, DO NOT USE!

This commit is contained in:
Fabio Herzig
2026-04-12 21:25:44 +02:00
commit a51fd9dbeb
423 changed files with 58560 additions and 0 deletions

131
www/displays/audio.php Normal file
View File

@@ -0,0 +1,131 @@
<!DOCTYPE html>
<html>
<head>
<title>Remote Audioplayer</title>
<meta name="robots" content="noindex">
<style>
body {
background: #000 !important;
height: 100vh;
margin: 0;
display: flex;
justify-content: center;
align-items: center;
font-family: sans-serif;
cursor: pointer;
}
h1 {
text-align: center;
color: #fff;
}
</style>
</head>
<body>
<script>
const userAccess = "audio";
let ws;
const RETRY_DELAY = 200; // ms
function startWebSocket() {
console.log("Attempting WebSocket connection...");
try {
ws = new WebSocket(`wss://` + window.location.hostname + `/ws/?access=${userAccess}`);
} catch (err) {
scheduleRetry();
return;
}
ws.onopen = () => {
console.log("WebSocket connected!");
document.querySelector('.errorws').style.display = 'none';
// SAFE: this executes only on successful connect
ws.send(JSON.stringify({
type: "SELF",
payload: {}
}));
};
ws.onerror = () => {
document.querySelector('h1').innerText = 'WS ERROR';
};
ws.onclose = () => {
document.querySelector('h1').innerText = 'WS DISCONECTED';
scheduleRetry();
};
}
function scheduleRetry() {
console.log(`Retrying in ${RETRY_DELAY}ms...`);
setTimeout(startWebSocket, RETRY_DELAY);
}
startWebSocket();
</script>
<h1>Der Audioplayer startet durch das Berühren des Displays</h1>
<audio id="peep" preload="auto"></audio>
<audio id="musicPlayer" preload="auto"></audio>
<script>
const peep = document.getElementById('peep');
const music = document.getElementById('musicPlayer');
let lastMusicUrl = null;
let pollingStarted = false; // ensure we start polling only once
async function fetchAndHandleMusic() {
try {
const response = await fetch('/displays/json/audio.json?t=' + Date.now(), { cache: 'no-store' });
const data = await response.json();
// Stop everything if musik is "stop"
if (!data.musik || data.musik === 'nan' || data.start == false) {
if (!music.paused) {
music.pause();
music.currentTime = 0;
}
if (!peep.paused) {
peep.pause();
peep.currentTime = 0;
}
lastMusicUrl = null;
return;
}
// Play only if new URL
if (data.musik !== lastMusicUrl) {
lastMusicUrl = data.musik;
// Play short peep first
peep.src = '/files/music/piep.mp3';
peep.play().then(() => {
// After 2 seconds, play the main music
setTimeout(() => {
music.src = data.musik;
music.play().catch(err => console.log('Music play error:', err));
}, 2000);
}).catch(err => console.log('Peep play error:', err));
}
} catch (err) {
console.error('Error fetching JSON:', err);
}
}
document.body.addEventListener('click', () => {
if (!pollingStarted) {
pollingStarted = true;
ws.addEventListener("message", () => {
fetchAndHandleMusic();
});
document.querySelector('h1').innerText = 'Player läuft'; // remove instruction
}
});
</script>
</body>
</html>

View File

@@ -0,0 +1,372 @@
:root {
--bg: #111827;
--panel: #020617;
--panel-soft: #0b1120;
--accent: #38bdf8;
--accent-soft: rgba(56, 189, 248, 0.15);
--text-main: #e5e7eb;
--text-muted: #9ca3af;
--danger: #ef4444;
--success: #22c55e;
--radius-lg: 18px;
--border-subtle: 1px solid rgba(148, 163, 184, 0.35);
--shadow-soft: 0 20px 45px rgba(15, 23, 42, 0.85);
--transition-fast: 180ms ease-out;
--colorStartDiv: #0b1120;
--panelBgLogo: #4a2f96;
--font-heading: clamp(1.5rem, 6vh, 4rem);
--font-sub: clamp(1rem, 3.5vh, 2.2rem);
--logo-size: clamp(150px, 40vh, 500px);
}
* {
box-sizing: border-box;
}
head > * {
pointer-events: none;
}
html,
body {
margin: 0;
padding: 0;
height: 100vh;
width: 100vw;
overflow: hidden;
position: fixed;
}
body {
display: flex;
justify-content: center;
align-items: stretch;
font-family: system-ui, -apple-system, BlinkMacSystemFont, "Segoe UI", sans-serif;
background-color: var(--bg);
color: var(--text-main);
overflow: hidden;
}
/* WebSocket error overlay */
.errorws {
position: fixed;
inset: 0;
display: flex;
flex-direction: column;
justify-content: center;
align-items: center;
gap: 16px;
padding: 5vh 5vw;
background: radial-gradient(circle at top, #020617 0, #020617 55%);
z-index: 10000;
}
.errorws .logoimg {
max-width: var(--logo-size);
height: auto;
margin-bottom: 2vh;
filter: drop-shadow(0 12px 30px rgba(0, 0, 0, 0.65));
}
.errortext {
margin: 0;
font-size: clamp(1.8rem, 8vw, 5rem);
line-height: 1.1;
max-width: 90vw;
font-weight: 500;
letter-spacing: 0.12em;
text-transform: uppercase;
color: var(--text-main);
text-align: center;
}
.errortextSmall {
margin: 10px;
font-size: clamp(1rem, 3vw, 2rem);
opacity: 0.8;
font-weight: 300;
letter-spacing: 0.12em;
color: var(--text-main);
text-align: center;
}
/* Startup logo overlay */
.logobg {
padding: 4vh;
position: fixed;
inset: 0;
display: flex;
flex-direction: column;
justify-content: center;
align-items: center;
gap: 12px;
background-color: var(--panelBgLogo);
z-index: 1000;
transition: opacity 0.5s ease;
}
.logoimg {
width: auto;
max-height: 45vh;
max-width: 80vw;
object-fit: contain;
/* filter: drop-shadow(0 18px 40px rgba(15, 23, 42, 0.4)); */
}
.logotext {
margin: 0;
font-size: clamp(1.8rem, 7vh, 6rem);
text-align: center;
width: 90vw;
line-height: 1.2;
/* Forces single line for names/titles to prevent overflow */
white-space: nowrap;
overflow: hidden;
text-overflow: ellipsis;
}
.logotext, .logoctext {
color: var(--text-color) !important;
text-align: center;
font-weight: 400;
margin-top: 1vh;
}
.logoctext {
margin: 0;
font-size: clamp(2rem, 7vw, 12rem);
}
/* 4. Responsive adjustments for different screen ratios */
@media (aspect-ratio: 4/3), (aspect-ratio: 10/7) {
/* Tablet specific tweaks (iPad/Android Tabs) */
:root {
--logo-size: 30vh;
}
.logotext {
font-size: 5vh;
}
}
@media (min-width: 1921px) {
/* Ultra-large TV/4K tweaks */
.logotext {
letter-spacing: 0.25em; /* Better legibility at distance */
}
}
/* Main scoreboard container full screen */
.pagediv {
flex: 1;
height: 100%;
width: 100vw;
display: flex;
flex-direction: column;
gap: 2vh;
padding: 2.2vh 2.4vw;
box-sizing: border-box;
background:
radial-gradient(circle at top left, var(--bg-soft), transparent 60%),
radial-gradient(circle at bottom right, var(--bg-soft), transparent 60%);
}
.pagediv.manuel {
padding-right: clamp(60px, 2.4vw, 2.4vw);
}
/* Common row styling */
.display-row {
flex: 1;
display: flex;
align-items: center;
padding: 30px;
border-radius: var(--radius-lg);
background: linear-gradient(135deg, var(--panel-soft), var(--panel));
border-bottom: var(--border-subtle);
position: relative;
overflow: hidden;
box-shadow: var(--shadow-soft);
}
.display-row::before {
content: "";
position: absolute;
inset: 0;
background: radial-gradient(circle at top left, var(--bg-soft), transparent 55%);
opacity: 0.5;
pointer-events: none;
}
.row1text,
.row2text p,
.row3 > p,
.start_text {
margin: 0;
padding: 0;
line-height: 1.1;
}
/* Row 1: athlete name */
.row1text {
font-size: min(8vh, 4.6vw);
font-weight: 600;
letter-spacing: 0.08em;
text-transform: uppercase;
white-space: nowrap;
}
/* Row 2: club, program, start/stop */
.row2 {
justify-content: space-between;
gap: 2vw;
}
.row2::after {
content: "";
position: absolute;
inset: 0;
background: radial-gradient(circle at bottom right, var(--colorStartDiv), transparent 55%);
opacity: 0.5;
pointer-events: none;
}
.row2text {
display: flex;
flex-direction: column;
gap: 0.8vh;
width: 50vw;
height: 100%;
}
.row2_1text {
color: var(--text-muted);
}
.row2_2text {
font-weight: 600;
}
/* Start / stop pill */
.start_div {
width: 35vw;
height: 100%;
display: flex;
justify-content: end;
align-items: center;
}
.start_text {
display: flex;
font-weight: 700;
letter-spacing: 0.1em;
text-transform: uppercase;
}
/* Row 3: D-score and total */
.row3 {
justify-content: space-between;
gap: 2vw;
}
.row3 > p {
font-size: min(9vh, 5vw);
font-weight: 700;
}
.row3_1text {
color: var(--color-note-l);
}
.row3_2text {
color: var(--color-note-r);
}
/* Existing #score and char/row styles if you use them elsewhere */
#score {
display: flex;
flex-direction: column;
justify-content: center;
align-items: center;
width: 100%;
height: 100%;
}
.char {
display: flex;
justify-content: center;
align-items: center;
font-size: 40vw;
line-height: 1;
}
.row {
display: flex;
justify-content: center;
align-items: center;
width: 100%;
font-size: 20vw;
}
/* Landscape / portrait logo scaling */
@media (orientation: landscape) {
.logoimg {
max-height: 60vh;
}
}
@media (orientation: portrait) {
.logoimg {
max-width: 60vw;
}
}
/* Small screens keep everything readable */
@media (max-width: 768px) {
.pagediv {
padding: 1.6vh 3vw;
gap: 1.4vh;
}
.display-row {
padding: 1.4vh 3vw;
}
.row2 {
flex-direction: column;
align-items: flex-start;
}
.start_div {
align-self: flex-end;
min-width: 40vw;
}
}
.noWsConnection {
position: fixed;
bottom: 20px;
right: 20px;
transform: rotate(270deg);
transform-origin: right bottom;
}
.rotator {
display: flex;
align-items: center;
gap: 6px;
transform: translateX(100%);
}
.noWsConnection img {
width: 20px;
height: 20px;
object-fit: contain;
}
.noWsConnection p {
font-size: 20px;
color: var(--text-muted);
margin: 0;
letter-spacing: 1.1px;
}

441
www/displays/display.php Normal file
View File

@@ -0,0 +1,441 @@
<?php
/*$protocol = (!empty($_SERVER['HTTPS']) && $_SERVER['HTTPS'] !== 'off') ? "https://" : "http://";
$fullDomain = $protocol . $_SERVER['HTTP_HOST'];*/
$lastSegment = strtolower($_GET['geraet']) ?? '';
$baseDir = $_SERVER['DOCUMENT_ROOT'];
$token = "QQa2UMbEYW8oOL7wz9DjtqECVCikSZsDuSdmzxiadEXFsKyujEUyQOW1AYMD2OqU8VXxClIRweRuWLzvBrZpPYL41e89Rs96tM7Lq1KpjA5E2mg2UfgvztheGRV";
require_once $baseDir . '/../scripts/db/db-verbindung-script-guest.php';
require_once $baseDir . '/../scripts/db/db-functions.php';
require_once $baseDir . '/../scripts/db/db-tables.php';
$stmt = $guest->prepare("SELECT `name` FROM $tableGeraete ORDER BY start_index ASC");
if (!$stmt->execute()) {
http_response_code(500);
exit;
}
$result = $stmt->get_result();
$disciplines = array_map(
'strtolower',
array_column($result->fetch_all(MYSQLI_ASSOC), 'name')
);
$stmt->close();
// Define a small helper function to keep the code DRY (Don't Repeat Yourself)
function sanitize_hex($color) {
return preg_replace('/[^0-9a-fA-F#]/', '', $color);
}
// Fetch and Sanitize Brand Colors
$wkName = db_get_var($guest, "SELECT `value` FROM $tableVar WHERE `name` = ?", ['wkName']);
$cleanColor = sanitize_hex(db_get_var($guest, "SELECT `value` FROM $tableVar WHERE `name` = ?", ['displayColourLogo']));
$cleanColorText = sanitize_hex(db_get_var($guest, "SELECT `value` FROM $tableVar WHERE `name` = ?", ['displayTextColourLogo']));
// Fetch and Sanitize Layout Colors
$displayColorScoringBg = sanitize_hex(db_get_var($guest, "SELECT `value` FROM $tableVar WHERE `name` = ?", ['displayColorScoringBg']));
$displayColorScoringBgSoft = sanitize_hex(db_get_var($guest, "SELECT `value` FROM $tableVar WHERE `name` = ?", ['displayColorScoringBgSoft']));
$displayColorScoringPanel = sanitize_hex(db_get_var($guest, "SELECT `value` FROM $tableVar WHERE `name` = ?", ['displayColorScoringPanel']));
$displayColorScoringPanelSoft = sanitize_hex(db_get_var($guest, "SELECT `value` FROM $tableVar WHERE `name` = ?", ['displayColorScoringPanelSoft']));
// Fetch and Sanitize Text Colors
$displayColorScoringPanelText = sanitize_hex(db_get_var($guest, "SELECT `value` FROM $tableVar WHERE `name` = ?", ['displayColorScoringPanelText']));
$displayColorScoringPanelTextSoft = sanitize_hex(db_get_var($guest, "SELECT `value` FROM $tableVar WHERE `name` = ?", ['displayColorScoringPanelTextSoft']));
// Fetch and Sanitize Accent Colors (Note: fixed 'diplay' typo here)
$displayColorScoringPanelTextNoteL = sanitize_hex(db_get_var($guest, "SELECT `value` FROM $tableVar WHERE `name` = ?", ['displayColorScoringPanelTextNoteL']));
$displayColorScoringPanelTextNoteR = sanitize_hex(db_get_var($guest, "SELECT `value` FROM $tableVar WHERE `name` = ?", ['displayColorScoringPanelTextNoteR']));
$guest->close();
if (!isset($lastSegment) || !in_array($lastSegment, $disciplines)){
echo 'kein Gerät';
exit;
}
$jsonUrlconfig = '/displays/json/config.json';
$jsonUrl = '/displays/json/display_' . $lastSegment . '.json';
?>
<!DOCTYPE html>
<html>
<head>
<title><?= $wkName ?> Anzeigen</title>
<meta name="robots" content="noindex">
<link rel="stylesheet" href="/displays/css/display.css">
<style>
:root {
/* Brand */
--panelBgLogo: <?= $cleanColor ?>;
--text-color: <?= $cleanColorText ?>;
/* Backgrounds */
--bg: <?= $displayColorScoringBg ?>;
--bg-soft: <?= $displayColorScoringBgSoft ?>26;
--panel: <?= $displayColorScoringPanel ?>;
--panel-soft: <?= $displayColorScoringPanelSoft ?>;
/* Typography */
--text-main: <?= $displayColorScoringPanelText ?>;
--text-muted: <?= $displayColorScoringPanelTextSoft ?>;
/* Noten */
--color-note-l: <?= $displayColorScoringPanelTextNoteL ?>;
--color-note-r: <?= $displayColorScoringPanelTextNoteR ?>;
}
</style>
</head>
<body>
<div class="errorws">
<img class="logoimg" src="https://cdn-icons-png.freepik.com/512/12890/12890341.png?ga=GA1.1.991281105.1761199359">
<p class="errortext">Keine WebSocket Verbindung</p>
<p class="errortextSmall">Versuche Verbindung... (Versuch <span id="counterTries"></span> / <span id="counterMaxTries"></span>)</p>
</div>
<div class="noWsConnection">
<div class="rotator">
<img src="https://cdn-icons-png.freepik.com/512/12890/12890341.png?ga=GA1.1.991281105.1761199359">
<p>Keine WebSocket Verbindung, Syncronisation via FETCH</p>
</div>
</div>
<div class="logobg">
<img id="jsImgLogo" class="logoimg" src="/intern/img/logo-normal.png">
<p class="logotext"><?= $wkName ?></p>
<p class="logoctext"></p>
</div>
<div class="pagediv">
<div class="display-row row1">
<p class="row1text"></p>
</div>
<div class="display-row row2">
<div class="row2text">
<p class="row2_1text sds"></p>
<p class="row2_2text"></p>
</div>
<div class="start_div">
<p class="start_text"></p>
</div>
</div>
<div class="display-row row3">
<p class="row3_1text"></p>
<p class="row3_2text"></p>
</div>
</div>
<script>
const userAccess = "<?php echo $lastSegment; ?>_display";
const jsonUrl = "<?php echo $jsonUrl; ?>";
const jsonUrlconfig = "<?php echo $jsonUrlconfig; ?>";
// --- State Management ---
let ws;
let filedConectCount = 1;
const fallbackConectCount = 10;
const RETRY_DELAY = 1000;
const FALLBACK_POLL_INTERVAL = 3000; // Fetch every 3 seconds if WS is dead
let fallbackTimer = null;
// Hold our current data in memory
let displayConfig = { type: 'logo', ctext: '' };
let currentScore = {};
let lastUniqueId = null;
// UI Elements
const counterTriesEl = document.getElementById('counterTries');
const counterMaxTriesEl = document.getElementById('counterMaxTries');
if(counterTriesEl) counterTriesEl.innerHTML = filedConectCount;
if(counterMaxTriesEl) counterMaxTriesEl.innerHTML = fallbackConectCount;
// --- Fullscreen Listener ---
const fs = document.documentElement;
document.body.addEventListener('click', () => {
if (fs.requestFullscreen) fs.requestFullscreen();
else if (fs.webkitRequestFullscreen) fs.webkitRequestFullscreen();
else if (fs.mozRequestFullScreen) fs.mozRequestFullScreen();
else if (fs.msRequestFullscreen) fs.msRequestFullscreen();
});
// --- WebSocket Logic ---
function startWebSocket() {
console.log("Attempting WebSocket connection...");
try {
ws = new WebSocket(`wss://${window.location.hostname}/ws/?access=${userAccess}`);
} catch (err) {
scheduleRetry();
return;
}
ws.onopen = () => {
console.log("WebSocket connected!");
document.querySelector('.errorws').style.display = 'none';
document.querySelector('.noWsConnection').style.display = 'none';
document.querySelector('.pagediv').classList.remove("manuel");
filedConectCount = 1;
if(counterTriesEl) counterTriesEl.innerHTML = filedConectCount;
// Stop fallback polling since WS is alive
stopFallbackPolling();
// Do ONE initial fetch to sync current state
fetchFullState();
};
ws.onerror = () => {
document.querySelector('.errorws').style.display = 'flex';
};
ws.onclose = () => {
document.querySelector('.errorws').style.display = 'flex';
scheduleRetry();
};
ws.addEventListener("message", msg => {
let msgJSON;
try {
msgJSON = JSON.parse(msg.data);
} catch (error) {
return; // Ignore malformed messages
}
// Route the incoming push data
switch (msgJSON.type) {
case "EINSTELLUNGEN_DISPLAY_UPDATE":
updateSettings(msgJSON.payload.key, msgJSON.payload.value);
break;
case "UPDATE_DISPLAYCONTROL":
// Expecting payload: { type: 'logo'|'ctext'|'scoring', ctext: '...' }
displayConfig = msgJSON.payload;
renderDOM();
break;
case "UPDATE_SCORE":
// Expecting payload: the exact same structure as your jsonUrl outputs
currentScore = msgJSON.payload;
renderDOM();
break;
}
});
}
function scheduleRetry() {
console.log(`Retrying in ${RETRY_DELAY}ms...`);
if (filedConectCount >= fallbackConectCount) {
// MAX RETRIES REACHED -> Enter Fallback Mode
document.querySelector('.errorws').style.display = 'none';
document.querySelector('.noWsConnection').style.display = 'flex';
document.querySelector('.pagediv').classList.add("manuel");
startFallbackPolling();
} else {
if(counterTriesEl) counterTriesEl.innerHTML = filedConectCount;
setTimeout(startWebSocket, RETRY_DELAY);
filedConectCount++;
}
}
// --- Fallback Polling Logic ---
function startFallbackPolling() {
if (fallbackTimer === null) {
console.warn("Starting JSON fallback polling...");
fetchFullState(); // Fetch immediately once
fallbackTimer = setInterval(fetchFullState, FALLBACK_POLL_INTERVAL);
// Optionally, keep trying to reconnect the WS slowly in the background
setTimeout(startWebSocket, 10000);
}
}
function stopFallbackPolling() {
if (fallbackTimer !== null) {
clearInterval(fallbackTimer);
fallbackTimer = null;
console.log("Stopped JSON fallback polling.");
}
}
// --- Data Fetching (Initial Sync & Fallback) ---
async function fetchFullState() {
try {
// Fetch both config and score simultaneously
const [resConfig, resScore] = await Promise.all([
fetch(jsonUrlconfig + '?t=' + Date.now(), { cache: "no-store" }),
fetch(jsonUrl + '?t=' + Date.now(), { cache: "no-store" })
]);
if (resConfig.ok) displayConfig = await resConfig.json();
if (resScore.ok) currentScore = await resScore.json();
renderDOM();
} catch (err) {
console.error("Error fetching JSON:", err);
const container = document.getElementById('score');
if(container) {
container.innerHTML = "";
container.style.backgroundColor = "black";
}
}
}
// --- The Master Renderer ---
function renderDOM() {
const logobg = document.querySelector('.logobg');
const ctext = document.querySelector('.logoctext');
if (displayConfig.type === 'logo' || displayConfig.type === 'ctext') {
// LOGO OR CUSTOM TEXT MODE
if (logobg) logobg.style.opacity = "1";
if (ctext) ctext.innerText = (displayConfig.type === 'ctext') ? (displayConfig.ctext || '') : '';
} else if (displayConfig.type === 'scoring') {
// SCORING MODE
if (logobg) logobg.style.opacity = "0";
if (currentScore.uniqueid !== lastUniqueId) {
lastUniqueId = currentScore.uniqueid;
// Reset any animation/repeat logic here if needed
}
const safeText = (selector, text) => {
const el = document.querySelector(selector);
if (el) el.innerText = text !== undefined ? text : '';
};
safeText('.row1text', `${currentScore.vorname || ''} ${currentScore.name || ''}`);
safeText('.row2_1text', currentScore.verein ? `${currentScore.verein}, ` : '');
safeText('.row2_2text', currentScore.programm || '');
const starttext = document.querySelector('.start_text');
const row2El = document.querySelector('.row2');
if (starttext && row2El) {
const rootStyles = getComputedStyle(document.documentElement);
const dangerColor = rootStyles.getPropertyValue('--danger').trim();
const successColor = rootStyles.getPropertyValue('--success').trim();
if (currentScore.start === true) {
row2El.style.setProperty('--colorStartDiv', successColor);
starttext.innerHTML = 'Start';
} else {
row2El.style.setProperty('--colorStartDiv', dangerColor);
starttext.innerHTML = 'Stop';
}
}
safeText('.row3_1text', currentScore.noteLinks);
safeText('.row3_2text', currentScore.noteRechts);
}
fitTextAll();
}
// --- Settings & UI Handlers ---
function updateSettings(type, value) {
const sanitizeHex = (val) => val.replace(/[^0-9a-fA-F#]/g, '');
switch (type) {
case 'wkName':
const logotext = document.querySelector('.logotext');
if (logotext) logotext.innerHTML = value;
break;
case 'displayColourLogo':
document.documentElement.style.setProperty('--panelBgLogo', sanitizeHex(value));
break;
case 'displayTextColourLogo':
document.documentElement.style.setProperty('--text-color', sanitizeHex(value));
break;
case 'displayColorScoringBg':
document.documentElement.style.setProperty('--bg', sanitizeHex(value));
break;
case 'displayColorScoringBgSoft':
document.documentElement.style.setProperty('--bg-soft', sanitizeHex(value) + "26");
break;
case 'displayColorScoringPanel':
document.documentElement.style.setProperty('--panel', sanitizeHex(value));
break;
case 'displayColorScoringPanelSoft':
document.documentElement.style.setProperty('--panel-soft', sanitizeHex(value));
break;
case 'displayColorScoringPanelText':
document.documentElement.style.setProperty('--text-main', sanitizeHex(value));
break;
case 'displayColorScoringPanelTextSoft':
document.documentElement.style.setProperty('--text-muted', sanitizeHex(value));
break;
case 'displayColorScoringPanelTextNoteL': // Matching your PHP typo
document.documentElement.style.setProperty('--color-note-l', sanitizeHex(value));
break;
case 'displayColorScoringPanelTextNoteR': // Matching your PHP typo
document.documentElement.style.setProperty('--color-note-r', sanitizeHex(value));
break;
case 'logo-normal':
const jsImgLogo = document.getElementById('jsImgLogo');
if(jsImgLogo) jsImgLogo.src = '/intern/img/logo-normal.png?' + Date.now();
break;
}
}
// --- Text Resizing Engine ---
function isOverflown(parent, elem, heightscale, widthscale, paddingtext) {
return (
(elem.scrollWidth + paddingtext) > (parent.clientWidth / widthscale) ||
(elem.scrollHeight + paddingtext) > (parent.clientHeight / heightscale)
);
}
function fitTextElement(elem, { minSize = 10, maxSize = 1000, step = 1, unit = 'px' } = {}) {
if (!elem) return;
const parent = elem.parentElement;
if (!parent) return;
// FIXED: Declare variables properly so they don't leak into the global scope
let heightscale = 1;
let widthscale = 1;
let paddingtext = 60;
if (parent.classList.contains('row2text')) {
heightscale = 2;
paddingtext = 0;
}
if (parent.classList.contains('row3')) {
widthscale = 2;
}
let size = minSize;
elem.style.whiteSpace = 'nowrap';
elem.style.fontSize = size + unit;
while (size < maxSize && !isOverflown(parent, elem, heightscale, widthscale, paddingtext)) {
size += step;
elem.style.fontSize = size + unit;
}
elem.style.fontSize = (size - step) + unit;
}
function fitTextAll() {
const paragraphs = document.querySelectorAll('.pagediv p');
paragraphs.forEach(p => fitTextElement(p));
}
window.addEventListener('resize', fitTextAll);
// --- Initialize ---
startWebSocket();
</script>
</body>
</html>

Binary file not shown.

Binary file not shown.

View File

@@ -0,0 +1,91 @@
This Font Software is licensed under the SIL Open Font License, Version 1.1.
This license is copied below, and is also available with a FAQ at:
https://openfontlicense.org
-----------------------------------------------------------
SIL OPEN FONT LICENSE Version 1.1 - 26 February 2007
-----------------------------------------------------------
PREAMBLE
The goals of the Open Font License (OFL) are to stimulate worldwide
development of collaborative font projects, to support the font creation
efforts of academic and linguistic communities, and to provide a free and
open framework in which fonts may be shared and improved in partnership
with others.
The OFL allows the licensed fonts to be used, studied, modified and
redistributed freely as long as they are not sold by themselves. The
fonts, including any derivative works, can be bundled, embedded,
redistributed and/or sold with any software provided that any reserved
names are not used by derivative works. The fonts and derivatives,
however, cannot be released under any other type of license. The
requirement for fonts to remain under this license does not apply
to any document created using the fonts or their derivatives.
DEFINITIONS
"Font Software" refers to the set of files released by the Copyright
Holder(s) under this license and clearly marked as such. This may
include source files, build scripts and documentation.
"Reserved Font Name" refers to any names specified as such after the
copyright statement(s).
"Original Version" refers to the collection of Font Software components as
distributed by the Copyright Holder(s).
"Modified Version" refers to any derivative made by adding to, deleting,
or substituting -- in part or in whole -- any of the components of the
Original Version, by changing formats or by porting the Font Software to a
new environment.
"Author" refers to any designer, engineer, programmer, technical
writer or other person who contributed to the Font Software.
PERMISSION & CONDITIONS
Permission is hereby granted, free of charge, to any person obtaining
a copy of the Font Software, to use, study, copy, merge, embed, modify,
redistribute, and sell modified and unmodified copies of the Font
Software, subject to the following conditions:
1) Neither the Font Software nor any of its individual components,
in Original or Modified Versions, may be sold by itself.
2) Original or Modified Versions of the Font Software may be bundled,
redistributed and/or sold with any software, provided that each copy
contains the above copyright notice and this license. These can be
included either as stand-alone text files, human-readable headers or
in the appropriate machine-readable metadata fields within text or
binary files as long as those fields can be easily viewed by the user.
3) No Modified Version of the Font Software may use the Reserved Font
Name(s) unless explicit written permission is granted by the corresponding
Copyright Holder. This restriction only applies to the primary font name as
presented to the users.
4) The name(s) of the Copyright Holder(s) or the Author(s) of the Font
Software shall not be used to promote, endorse or advertise any
Modified Version, except to acknowledge the contribution(s) of the
Copyright Holder(s) and the Author(s) or with their explicit written
permission.
5) The Font Software, modified or unmodified, in part or in whole,
must be distributed entirely under this license, and must not be
distributed under any other license. The requirement for fonts to
remain under this license does not apply to any document created
using the Font Software.
TERMINATION
This license becomes null and void if any of the above conditions are
not met.
DISCLAIMER
THE FONT SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO ANY WARRANTIES OF
MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT
OF COPYRIGHT, PATENT, TRADEMARK, OR OTHER RIGHT. IN NO EVENT SHALL THE
COPYRIGHT HOLDER BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY,
INCLUDING ANY GENERAL, SPECIAL, INDIRECT, INCIDENTAL, OR CONSEQUENTIAL
DAMAGES, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
FROM, OUT OF THE USE OR INABILITY TO USE THE FONT SOFTWARE OR FROM
OTHER DEALINGS IN THE FONT SOFTWARE.

View File

@@ -0,0 +1,112 @@
Google Sans Flex Variable Font
==============================
This download contains Google Sans Flex as both a variable font and static fonts.
Google Sans Flex is a variable font with these axes:
GRAD
ROND
opsz
slnt
wdth
wght
This means all the styles are contained in a single file:
GoogleSansFlex-VariableFont_GRAD,ROND,opsz,slnt,wdth,wght.ttf
If your app fully supports variable fonts, you can now pick intermediate styles
that arent available as static fonts. Not all apps support variable fonts, and
in those cases you can use the static font files for Google Sans Flex:
static/GoogleSansFlex_9pt-Thin.ttf
static/GoogleSansFlex_9pt-ExtraLight.ttf
static/GoogleSansFlex_9pt-Light.ttf
static/GoogleSansFlex_9pt-Regular.ttf
static/GoogleSansFlex_9pt-Medium.ttf
static/GoogleSansFlex_9pt-SemiBold.ttf
static/GoogleSansFlex_9pt-Bold.ttf
static/GoogleSansFlex_9pt-ExtraBold.ttf
static/GoogleSansFlex_9pt-Black.ttf
static/GoogleSansFlex_24pt-Thin.ttf
static/GoogleSansFlex_24pt-ExtraLight.ttf
static/GoogleSansFlex_24pt-Light.ttf
static/GoogleSansFlex_24pt-Regular.ttf
static/GoogleSansFlex_24pt-Medium.ttf
static/GoogleSansFlex_24pt-SemiBold.ttf
static/GoogleSansFlex_24pt-Bold.ttf
static/GoogleSansFlex_24pt-ExtraBold.ttf
static/GoogleSansFlex_24pt-Black.ttf
static/GoogleSansFlex_36pt-Thin.ttf
static/GoogleSansFlex_36pt-ExtraLight.ttf
static/GoogleSansFlex_36pt-Light.ttf
static/GoogleSansFlex_36pt-Regular.ttf
static/GoogleSansFlex_36pt-Medium.ttf
static/GoogleSansFlex_36pt-SemiBold.ttf
static/GoogleSansFlex_36pt-Bold.ttf
static/GoogleSansFlex_36pt-ExtraBold.ttf
static/GoogleSansFlex_36pt-Black.ttf
static/GoogleSansFlex_72pt-Thin.ttf
static/GoogleSansFlex_72pt-ExtraLight.ttf
static/GoogleSansFlex_72pt-Light.ttf
static/GoogleSansFlex_72pt-Regular.ttf
static/GoogleSansFlex_72pt-Medium.ttf
static/GoogleSansFlex_72pt-SemiBold.ttf
static/GoogleSansFlex_72pt-Bold.ttf
static/GoogleSansFlex_72pt-ExtraBold.ttf
static/GoogleSansFlex_72pt-Black.ttf
static/GoogleSansFlex_120pt-Thin.ttf
static/GoogleSansFlex_120pt-ExtraLight.ttf
static/GoogleSansFlex_120pt-Light.ttf
static/GoogleSansFlex_120pt-Regular.ttf
static/GoogleSansFlex_120pt-Medium.ttf
static/GoogleSansFlex_120pt-SemiBold.ttf
static/GoogleSansFlex_120pt-Bold.ttf
static/GoogleSansFlex_120pt-ExtraBold.ttf
static/GoogleSansFlex_120pt-Black.ttf
Get started
-----------
1. Install the font files you want to use
2. Use your app's font picker to view the font family and all the
available styles
Learn more about variable fonts
-------------------------------
https://developers.google.com/web/fundamentals/design-and-ux/typography/variable-fonts
https://variablefonts.typenetwork.com
https://medium.com/variable-fonts
In desktop apps
https://theblog.adobe.com/can-variable-fonts-illustrator-cc
https://helpx.adobe.com/nz/photoshop/using/fonts.html#variable_fonts
Online
https://developers.google.com/fonts/docs/getting_started
https://developer.mozilla.org/en-US/docs/Web/CSS/CSS_Fonts/Variable_Fonts_Guide
https://developer.microsoft.com/en-us/microsoft-edge/testdrive/demos/variable-fonts
Installing fonts
MacOS: https://support.apple.com/en-us/HT201749
Linux: https://www.google.com/search?q=how+to+install+a+font+on+gnu%2Blinux
Windows: https://support.microsoft.com/en-us/help/314960/how-to-install-or-remove-a-font-in-windows
Android Apps
https://developers.google.com/fonts/docs/android
https://developer.android.com/guide/topics/ui/look-and-feel/downloadable-fonts
License
-------
Please read the full license text (OFL.txt) to understand the permissions,
restrictions and requirements for usage, redistribution, and modification.
You can use them in your products & projects print or digital,
commercial or otherwise.
This isn't legal advice, please consider consulting a lawyer and see the full
license for all details.

15
www/files/fonts/fonts.css Normal file
View File

@@ -0,0 +1,15 @@
@font-face {
font-family: "Google Sans Flex";
src: url(/files/fonts/Google_Sans_Flex/GoogleSansFlex-VariableFont_GRAD,ROND,opsz,slnt,wdth,wght.ttf);
}
* {
font-family: "Google Sans Flex", sans-serif;
font-optical-sizing: auto;
font-style: normal;
font-variation-settings:
"slnt" 0,
"wdth" 100,
"GRAD" 0,
"ROND" 0;
}

Binary file not shown.

After

Width:  |  Height:  |  Size: 11 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 11 KiB

BIN
www/files/logo/icon.png Normal file

Binary file not shown.

After

Width:  |  Height:  |  Size: 200 KiB

BIN
www/files/music/piep.mp3 Normal file

Binary file not shown.

9
www/intern/.htaccess Normal file
View File

@@ -0,0 +1,9 @@
RewriteEngine On
# Do not interfere with real files or directories
RewriteCond %{REQUEST_FILENAME} !-f
RewriteCond %{REQUEST_FILENAME} !-d
# If a matching .php file exists, serve it
RewriteCond %{REQUEST_FILENAME}.php -f
RewriteRule ^(.+)$ $1.php [L]

View File

@@ -0,0 +1,79 @@
.msgDiv {
position: fixed;
bottom: 50px;
right: 20px;
display: flex;
align-items: end;
flex-direction: column-reverse;
z-index: 1000;
}
.msgDiv, .msgDiv > * {
box-sizing: border-box;
}
.msgBox,
.confirmBox {
transform: translateX(calc(100% + 40px)) scaleY(0);
height: 0;
margin-top: 0;
padding: 10px 15px;
color: #fff;
background-color: #0b0b0b;
border-left: 4px solid;
border-radius: 2px;
transition: all 1s ease;
}
.msgBox.show,
.confirmBox.show {
transform: translateX(0) scaleY(1);
height: 40px;
margin-top: 10px;
}
.msgBox.show {
height: 40px;
}
.confirmBox.show {
height: 100px;
}
.buttonConfirmDiv {
margin-top: 16px;
display: flex;
justify-content: space-around;
}
.confirmBox button {
padding: 8px 24px;
transition: background-color 0.3s ease, opacity 1s ease, height 1s ease;
color: #fff;
border: none;
border-radius: 8px;
opacity: 0;
height: 0;
font-size: 18px;
}
.confirmBox.show button {
opacity: 1;
height: auto;
}
.confirmYesButton {
background-color: rgba(0, 255, 0, 0.75);
}
.confirmNoButton {
background-color: rgba(255, 0, 0, 0.75);
}
.confirmYesButton:hover {
background-color: rgba(0, 255, 0, 1);
}
.confirmNoButton:hover {
background-color: rgba(255, 0, 0, 1);
}

View File

@@ -0,0 +1,91 @@
.customSelect {
position: relative;
}
.customSelect>* {
margin: 0;
}
.selectTrigger .selectArrow {
transition: rotate 0.6s ease;
}
table input {
height: 38px;
}
.selectTrigger,
.selectTriggerBulk {
background: none;
border: none;
padding: 0;
display: flex;
justify-content: space-between;
align-items: center;
cursor: pointer;
}
.selectOptions,
.selectOptionsBulk {
position: absolute;
top: calc(100% + 4px);
left: 0;
right: 0;
padding: 4px;
list-style: none;
border: 1px solid var(--color-border);
border-radius: 12px;
background: #fff;
z-index: 1000;
box-shadow: 0 4px 16px rgba(0, 0, 0, 0.08);
opacity: 0;
transform: scaleY(0);
transform-origin: top;
pointer-events: none;
transition: opacity 0.2s ease, transform 0.2s ease;
}
.customSelect.open .selectOptions,
.customSelect.open .selectOptionsBulk {
opacity: 1;
transform: scaleY(1);
pointer-events: auto;
}
.customSelect.open .selectArrow {
rotate: 180deg
}
.selectOptions li,
.selectOptionsBulk li {
padding: 10px 14px;
cursor: pointer;
border-radius: 8px;
margin-bottom: 2px;
transition: background-color 0.15s ease;
}
.selectOptions li:last-child,
.selectOptionsBulk li:last-child {
margin-bottom: 0;
}
.selectOptions li:hover,
.selectOptionsBulk li:hover {
background-color: #eee;
}
.selectOptions li.selected,
.selectOptionsBulk li.selected {
background-color: #ccc;
color: #000;
font-weight: 500;
}
.selectLabel {
font-size: 1rem;
}

View File

@@ -0,0 +1,175 @@
:root {
--main: #6e285f;
--bg-top-raw: 110 40 95;
--main-box-shadow: rgb(from var(--main) r g b / 0.05);
--accent: #737444;
--paddingSite: 40px;
--card-radius: 20px;
--card-bg: #ffffff;
--bg: #FDFDFD;
--card-shadow: 0 10px 30px rgba(15, 23, 42, 0.08);
--accent-soft: #f0f5ff;
--border-subtle: #d4d7e1;
--text-main: #191919;
--text-muted: #5e5e5e;
}
*,
*::before,
*::after {
box-sizing: border-box;
}
html,
body,
section {
margin: 0;
overscroll-behavior: none;
}
body {
margin: 0;
background-color: var(--bg);
color: var(--text-main);
}
.bgSection {
padding: var(--paddingSite);
}
.headerDivTrainer {
padding: var(--paddingSite);
background-color: var(--main);
color: var(--bg);
margin-bottom: var(--paddingSite);
display: flex;
justify-content: space-between;
align-items: center;
}
.headingPanel {
margin: 0;
font-weight: 200;
}
.controls-wrapper {
display: flex;
flex-direction: column;
gap: 20px;
align-items: center;
margin-bottom: var(--paddingSite);
flex-wrap: wrap;
}
.controls-wrapper>div,
.controls-wrapper>form {
display: flex;
flex-direction: row;
gap: 10px
}
/* From Trainer Dashboard - newBtn style */
button.change-type,
button[type="submit"] {
cursor: pointer;
font-weight: 700;
transition: all 0.2s;
padding: 10px 24px;
border-radius: 100px;
background: #cfef00;
border: 1px solid transparent;
display: flex;
align-items: center;
font-size: 15px;
color: #000;
}
button.change-type:hover,
button[type="submit"]:hover {
background: #c5e300;
transform: translateY(-1px);
}
button.change-type:active,
button[type="submit"]:active {
transform: scale(0.95);
}
.change-type-form {
display: flex;
align-items: center;
}
.change-type-form input {
padding: 10px 15px;
border-radius: 8px;
border: 1px solid var(--border-subtle);
background: #fff;
font-size: 15px;
width: 250px;
outline: none;
transition: border-color 0.2s;
}
.change-type-form input:focus {
border-color: var(--main);
}
.iframe-grid {
display: grid;
grid-template-columns: repeat(auto-fit, minmax(400px, 1fr));
gap: 30px;
}
.iframeWithTitle {
background: #000;
border-radius: 20px;
padding: 15px;
display: flex;
flex-direction: column;
align-items: center;
box-shadow: var(--card-shadow);
}
.iframeWithTitle h1 {
color: #fff;
font-size: 1.2rem;
margin-bottom: 15px;
font-weight: 400;
}
iframe {
width: 100%;
aspect-ratio: 16/9;
border: none;
border-radius: 15px;
background: #222;
}
.divSucsess {
display: flex;
opacity: 0;
position: fixed;
top: 20px;
right: 20px;
transform: translateX(400px);
background-color: #ffffff;
z-index: 10000;
border-radius: 12px;
box-shadow: var(--card-shadow);
transition: all 0.4s cubic-bezier(0.175, 0.885, 0.32, 1.275);
border-left: 5px solid #4ade80;
padding-right: 20px;
}
.divSucsess.show {
opacity: 1;
transform: translateX(0);
}
.textSucsess {
color: #137333;
margin: 15px;
font-weight: 600;
font-size: 14px;
}

File diff suppressed because it is too large Load Diff

File diff suppressed because one or more lines are too long

View File

@@ -0,0 +1,958 @@
:root {
--paddingSite: 40px;
--card-radius: 20px;
--card-bg: #ffffff;
--bg: #FDFDFD;
--card-shadow: 0 10px 30px rgba(15, 23, 42, 0.08);
--accent: #2d73ac;
--accent-soft: #f0f5ff;
--border-subtle: #d4d7e1;
--text-main: #191919;
--text-muted: #5e5e5e;
--disabled-bg: #f3f4f6;
--disabled-border: #cbd5f5;
}
/* Base */
*,
*::after,
*::before {
box-sizing: border-box;
-webkit-tap-highlight-color: transparent;
font-family: "Google Sans Flex", sans-serif;
font-optical-sizing: auto;
font-style: normal;
font-variation-settings:
"slnt" 0,
"wdth" 100,
"GRAD" 0,
"ROND" 0;
}
html,
body,
section {
margin: 0;
overscroll-behavior: none;
}
body {
margin: 0;
width: 100vw;
background: var(--bg);
}
::selection {
background: #0000003d;
color: #ffffffff;
}
::-moz-selection {
background: #a4bf4a99;
color: #000;
}
input {
border: none;
}
/* General numeric inputs in scoring area */
.bgSection input[type="number"] {
font-size: 16px;
}
.nopadding {
height: 40px;
}
/* Layout */
.bgSection {
position: relative;
margin-left: auto;
/*margin: var(--paddingSite);
width: calc(100vw - 2 * var(--paddingSite));*/
width: 100vw;
box-sizing: border-box !important;
background: none;
}
@media (min-width: 1000px) {
.bgSection.open {
width: calc(100vw - 380px);
/* - 2 * var(--paddingSite) */
}
}
/* Cards */
.headerDivKampfrichter {
padding: var(--paddingSite);
background-color: var(--bg-top);
margin-bottom: var(--paddingSite);
position: relative;
z-index: 3;
}
/* headings */
.heading_fv_selturnerin,
.heading_fv_selturnerin>* {
margin-top: 0;
font-weight: 400;
margin-bottom: 20px;
}
.divLiveSyncronisation {
padding: var(--paddingSite);
}
.heading_fv_alleturnerinnen {
margin-top: 0;
font-weight: 400;
}
.headingPanelDiv {
display: flex;
flex-direction: column;
}
.headingPanelDiv>* {
color: var(--bg);
}
.headingPanel {
margin-top: 0;
margin-bottom: 10px;
font-weight: 200;
}
.headingPanelGeraet {
margin: 0;
font-weight: 700;
}
#wsInfo {
margin: 0;
font-weight: 300;
opacity: 0;
transition: all 2s ease;
}
/* Kampfrichter header layout */
.headerDivKampfrichter {
display: flex;
justify-content: space-between;
align-items: center;
}
/* Turnerinnen table */
table {
border-collapse: collapse;
margin: 0;
padding: 0;
width: 100%;
}
.wkvsTabelle th {
color: #424242;
border-bottom: solid 1px #0000007d;
font-weight: 600;
padding: 14px 15px;
font-size: 16px;
}
.wkvsTabelle td {
background-color: #ffffff;
color: #191919;
font-weight: 400;
padding: 14px 15px;
background: none;
text-align: center;
border-bottom: solid 1px #6262624d;
}
.allTurnerinenDiv .widefat input {
min-width: 60px;
display: flex;
margin: auto;
background: none;
text-align: center;
}
.allTurnerinenDiv .editTurnerin,
.allTurnerinenDiv .editTurnerinAdmin {
background: none;
border: none;
cursor: pointer;
}
.allTurnerinenDiv .editTurnerin svg,
.allTurnerinenDiv .editTurnerinAdmin svg {
transition: transform 0.3s ease;
}
.allTurnerinenDiv .editTurnerin svg:hover,
.allTurnerinenDiv .editTurnerinAdmin svg:hover {
transform: scale(1.2);
animation-name: stiftWackler;
animation-duration: 0.5s;
}
@keyframes stiftWackler {
25% {
transform: rotate(-10deg) scale(1.05);
}
75% {
transform: rotate(10deg) scale(1.15);
}
100% {
transform: rotate(0deg) scale(1.2);
}
}
.allTurnerinenDiv tr:hover {
background-color: #f4f4f4;
}
/*.allTurnerinenDiv tr.notHeaderRow:hover td{
-webkit-text-stroke: 0.75px currentColor;
color: currentColor;
}*/
/* Panel with inputs (new style, light) */
.div_edit_values_user {
margin: 2rem auto;
padding: 1.6rem 1.8rem;
background: var(--card-bg);
color: var(--text-main);
flex-direction: column;
align-items: center;
}
/* Titles inside edit card */
.heading_fv_selturnerin {
display: flex;
flex-wrap: wrap;
gap: .35rem;
align-items: baseline;
font-size: 1.15rem;
letter-spacing: 0.01em;
}
.current-turnerin-name {
font-weight: 600;
color: var(--accent);
}
.heading_fv_nextturnerin {
margin: 1.5rem 0 0.75rem;
font-size: 0.9rem;
text-transform: uppercase;
color: var(--text-muted);
letter-spacing: 0.08em;
}
.fv_nextturnerin:hover {
font-size: 1.1rem;
}
/* Tables container inside edit card */
.all_vaules_div,
.all_edit_vaules_div {
display: inline-flex;
/* makes the box shrink to fit */
flex-wrap: wrap;
gap: 1rem;
margin-bottom: 1.25rem;
align-items: center;
}
.all_vaules_div {
flex-direction: column;
}
/* Individual small tables */
.editkampfrichter_user {
border-collapse: collapse;
background: #f9fafb;
border-radius: 12px;
overflow: hidden;
min-width: 180px;
box-shadow: 0 0 0 1px rgba(209, 213, 219, 0.9);
}
.editkampfrichter_user th,
.editkampfrichter_user td {
padding: 0.6rem 0.75rem;
text-align: center;
white-space: nowrap;
}
.editkampfrichter_user th {
font-size: 0.8rem;
text-transform: uppercase;
letter-spacing: 0.09em;
color: var(--text-muted);
background: #f3f4f6;
}
.table_endnote_edit {
margin-top: 1rem;
width: 100%;
}
/* Tight cell for pure input */
.nopadding {
padding: 0.25rem 0.5rem !important;
}
/* Inputs inside edit card */
.fullinput {
width: 100%;
box-sizing: border-box;
/*padding: 0.45rem 0.6rem;*/
border-radius: 8px;
border: 1px solid var(--border-subtle);
background: #ffffff;
color: var(--text-main);
font-size: 0.9rem;
line-height: 1.3;
outline: none;
transition: border-color 0.15s ease, box-shadow 0.15s ease, background-color 0.15s ease;
text-align: center;
}
.fullinput:focus {
border-color: var(--accent);
box-shadow: 0 0 0 1px rgba(45, 115, 172, 0.25);
background: #ffffff;
}
/* Strong & clear disabled style */
.fullinput:disabled,
.fullinput[readonly] {
background: none;
border: none;
color: #6b7280;
opacity: 1;
cursor: auto;
}
.fullinput:disabled:hover,
.fullinput:disabled:focus,
.fullinput[readonly]:hover,
.fullinput[readonly]:focus {
box-shadow: none;
border-color: var(--disabled-border);
}
/* Computed result fields even clearer */
/*[id^="e-note-"]:disabled {
background: #fff7d6;
background: repeating-linear-gradient(
135deg,
#ffefb0,
#ffefb0 6px,
#fff7d6 6px,
#fff7d6 12px
);
border-color: #f59e0b;
box-shadow: inset 0 0 0 1px rgba(245, 158, 11, 0.7);
color: #92400e;
font-weight: 800;
text-align: center;
}*/
[id^="note-user-"]:disabled {
background: none;
border: none;
color: var(--bg-top);
font-weight: 600;
text-align: center;
}
/* Remove number arrows where supported */
input[type="number"] {
-moz-appearance: textfield;
}
input[type="number"]::-webkit-inner-spin-button,
input[type="number"]::-webkit-outer-spin-button {
-webkit-appearance: none;
margin: 0;
}
/* Explanation text */
.editkampfrichter_user_text {
margin-top: 0.9rem;
font-size: 0.85rem;
color: var(--text-muted);
line-height: 1.4;
}
/* Next gymnast link */
.fv_nextturnerin {
display: inline-flex;
align-items: center;
gap: 0.4rem;
min-height: 1.75rem;
font-weight: 500;
color: var(--accent);
text-decoration: none;
border-bottom: 1px dashed rgba(45, 115, 172, 0.45);
padding-bottom: 0.05rem;
transition: all 0.3s;
}
/* Buttons near inputs */
.submit-display-turnerin,
.submit-display-start,
.submit-musik-start,
.submit-musik-stopp,
.submit-display-result {
appearance: none;
border: none;
border-radius: 999px;
padding: 0.5rem 1.1rem;
font-size: 0.9rem;
font-weight: 600;
cursor: pointer;
margin: 0.35rem 0.4rem 0 0;
transition: transform 0.08s ease, box-shadow 0.12s ease, background-color 0.12s ease, color 0.12s ease;
display: inline-flex;
align-items: center;
justify-content: center;
}
/* Variants */
.submit-display-turnerin {
background-color: #378cd243;
border: solid 1px #3382c3;
color: #256396;
}
.submit-display-result {
background-color: #c538d83d;
border: solid 1px #be3bcf;
color: #781467;
}
.submit-display-start,
.submit-musik-start {
background: #ecfdf3;
color: #15803d;
border: 1px solid #4ade80;
}
.submit-musik-stopp {
background: #fef2f2;
color: #b91c1c;
border: 1px solid #fca5a5;
}
/* Button interaction */
.submit-display-turnerin:hover,
.submit-display-start:hover,
.submit-musik-start:hover,
.submit-musik-stopp:hover,
.submit-display-result:hover {
transform: translateY(-1px);
box-shadow: 0 12px 30px rgba(15, 23, 42, 0.12);
}
.submit-display-turnerin:active,
.submit-display-start:active,
.submit-musik-start:active,
.submit-musik-stopp:active,
.submit-display-result:active {
transform: translateY(0);
box-shadow: 0 8px 18px rgba(15, 23, 42, 0.1);
}
/* Burger + menu (unchanged from your style) */
.kampfrichterBurgerMenuDiv {
display: flex;
align-items: center;
justify-content: center;
width: 28px;
height: 28px;
cursor: pointer;
z-index: 99;
color: var(--bg);
}
.kampfrichterBurgerMenuDiv svg {
width: 100%;
height: 100%;
stroke: currentColor;
transition: transform 0.3s ease;
}
.kampfrichterBurgerMenuDiv.open svg {
transform: rotate(45deg);
}
.internMenuDiv {
background-color: #fff;
box-shadow: none;
position: fixed;
left: 0;
top: 0;
height: 100svh;
width: 100%;
max-width: 400px;
transform: translateX(-100%);
z-index: 100;
padding: 20px;
transition: transform 0.45s cubic-bezier(.4, 0, .2, 1);
opacity: 1;
}
.internMenuDiv.open {
transform: translateX(0);
box-shadow: 4px 0 20px rgba(0, 0, 0, 0.15);
}
.innerInternMenuDiv {
display: flex;
flex-direction: column;
gap: 14px;
min-height: 100vh;
overflow-y: auto;
padding-bottom: 80px;
}
.innerInternMenuDiv h3 {
font-size: 1.1rem;
font-weight: 500;
margin: 10px 0;
color: #1a1a1a;
letter-spacing: 0.5px;
}
.text_akt_abt {
font-size: 1rem;
color: #555;
text-align: center;
line-height: 1.6;
}
.innerInternMenuDiv form {
margin: 0;
}
.innerInternMenuDiv input[type="submit"],
.innerInternMenuDiv select {
width: 100%;
padding: 12px 14px;
border-radius: 10px;
border: 1px solid #ccc;
font-size: 0.95rem;
transition: all 0.3s ease;
}
.innerInternMenuDiv input[type="submit"]:focus,
.innerInternMenuDiv select:focus {
outline: none;
border-color: #2d73ac;
box-shadow: 0 0 6px rgba(45, 115, 172, 0.3);
}
.innerInternMenuDiv .button-secondary {
background: linear-gradient(135deg, #2d73ac, #1f4f75);
color: #fff;
border: none;
border-radius: 12px;
font-weight: 600;
cursor: pointer;
padding: 12px 18px;
transition: transform 0.2s ease, background 0.3s ease;
box-shadow: 0 4px 10px rgba(0, 0, 0, 0.1);
}
.innerInternMenuDiv .button-secondary:hover {
background: linear-gradient(135deg, #245d8a, #163b5a);
transform: translateY(-2px);
}
.gruppennav {
display: flex;
align-items: center;
justify-content: center;
gap: 8px;
background: #f9fafc;
padding: 10px 16px;
border-radius: 12px;
box-shadow: inset 0 1px 3px rgba(0, 0, 0, 0.05);
}
.gruppennav p {
margin: 0 6px;
font-weight: 600;
color: #333;
}
.button_gruppe {
border: none;
background: #2d73ac;
color: white;
width: 36px;
height: 36px;
border-radius: 50%;
font-size: 1.1rem;
cursor: pointer;
transition: all 0.3s ease;
box-shadow: 0 2px 6px rgba(0, 0, 0, 0.1);
}
.button_gruppe:hover {
background: #245d8a;
transform: scale(1.05);
}
.labelnamekr {
font-size: 1rem;
font-weight: 500;
margin-top: 14px;
display: block;
color: #222;
}
.inputnamekr {
margin-bottom: 12px;
}
.footerInternMenu {
display: flex;
flex-direction: row;
justify-content: space-between;
position: absolute;
bottom: 12px;
gap: 40px;
width: calc(100% - 40px);
}
.footerInternMenu>* {
display: flex;
}
.abmeldenbutton {
width: 100%;
padding: 14px;
background: linear-gradient(135deg, #e53935, #b71c1c);
border: none;
border-radius: 12px;
font-weight: 600;
color: #fff;
cursor: pointer;
transition: transform 0.2s ease, background 0.3s ease;
box-shadow: 0 4px 10px rgba(0, 0, 0, 0.1);
}
.abmeldenbutton:hover {
background: linear-gradient(135deg, #c62828, #8e1919);
transform: translateY(-2px);
}
.menuBg {
position: fixed;
inset: 0;
z-index: 98;
user-select: none;
pointer-events: none;
opacity: 0;
/*background: rgba(0, 0, 0, 0.15);*/
}
.menuBg.menuTransition {
transition: opacity 0.6s ease-out;
}
/*.menuBg.open {
opacity: 1;
pointer-events: auto;
user-select: all;
}*/
.menuTransition {
transition: all 0.6s ease-out;
}
.menuTransition>.kampfrichterBurgerMenuLine {
transition: all 0.3s ease-out;
}
.closeInternMenuMobileDiv {
display: none;
width: 5vw;
height: 100px;
position: absolute;
top: 30px;
right: -5vw;
background-color: #09090966;
border-radius: 0 10px 10px 0;
}
/* Mobile tweaks */
@media (max-width: 480px) {
.internMenuDiv {
max-width: 95vw;
}
.internMenuDiv.open .closeInternMenuMobileDiv {
display: block;
}
}
@media (max-width: 600px) {
.div_edit_values_user,
.allTurnerinenDiv {
padding: var(--paddingSite) calc(var(--paddingSite) * 0.75);
margin-bottom: var(--paddingSite);
}
.notMobile {
display: none;
}
.allTurnerinenDiv th {
padding: 12px 6px;
}
.allTurnerinenDiv td {
padding: 10px 6px;
}
.ranglisteExportBMDesktop {
display: none;
}
.ranglisteExportBMMobile {
display: block;
}
}
@media (min-width: 601px) {
.div_edit_values_user,
.allTurnerinenDiv {
padding: var(--paddingSite) calc(var(--paddingSite) * 1.5);
margin-bottom: var(--paddingSite);
}
.ranglisteExportBMDesktop {
display: block;
}
.ranglisteExportBMMobile {
display: none;
}
}
.buttonNextAbt,
.buttonPrevAbt,
.button_gruppe {
line-height: 0;
}
.all_e_vaules_div {
display: grid;
gap: 1rem;
}
.titleWidthNormalInput {
width: 309.398px;
}
.flexRow {
display: flex;
flex-direction: row;
align-items: center;
gap: 5px;
}
.fullHeightRectangle {
display: flex;
}
.msgDiv {
position: fixed;
bottom: 50px;
right: 20px;
display: flex;
align-items: end;
flex-direction: column-reverse;
gap: 10px;
}
.msgBox {
transform: translateX(calc(100% + 40px));
padding: 10px 15px;
color: #fff;
background-color: #5b5b5b98;
border-left: 4px solid;
border-radius: 2px;
transition: all 0.5s ease;
}
.msgBox.show {
transform: translateX(0);
}
.playcontrolDiv {
display: flex;
justify-content: center;
margin: 20px 0;
}
.noKampfrichterDiv {
display: none;
justify-content: center;
align-items: center;
position: absolute;
top: 0;
left: 0;
width: 100%;
min-height: 100vh;
height: 100%;
background-color: #e9eef6a0;
backdrop-filter: blur(3px);
z-index: 2;
}
.noKampfrichterDiv>h1 {
color: var(--bg-top);
}
.adminButtonDiv input,
.buttonNewAdminStyle {
background-color: var(--bg-top);
color: #fff;
border: none;
border-radius: 5px;
font-weight: 200;
cursor: pointer;
padding: 12px 18px;
transition: all 0.3s ease;
box-shadow: 0 4px 10px rgba(0, 0, 0, 0.1);
}
.adminButtonDiv input {
margin: 10px 0 0 10px;
}
.adminButtonDiv input:hover {
filter: brightness(1.2);
}
.titleSingleAbt {
font-weight: 400;
color: var(--bg-top);
}
.adminButtonDiv {
display: block;
}
table.widefat {
table-layout: auto;
}
.singleAbtDiv:not(:last-child) {
margin-bottom: 60px;
}
.singleEXNoteAdminTable {
display: flex;
flex-direction: row;
}
.singleEXNoteAdminTableLable {
width: 40px;
margin: 3px 0 3px 10px;
text-align: end;
}
.tableWraperOverflowY {
overflow-x: auto;
overflow-y: hidden;
/* Prevent scroll chaining to body */
overscroll-behavior-x: contain;
/* Smooth scrolling on touch devices */
-webkit-overflow-scrolling: touch;
}
.div_edit_values_all_gereate {
display: flex;
flex-direction: row;
flex-wrap: wrap;
gap: 3rem;
width: 100%;
justify-content: space-around;
}
select {
appearance: none;
/* Standard */
-webkit-appearance: none;
/* WebKit */
-moz-appearance: none;
/* Firefox */
width: 100%;
padding: 12px 35px 12px 14px !important;
font-size: 16px;
border: 1px solid #ccc;
border-radius: 4px;
background-color: #fff;
background-image: url("data:image/svg+xml;utf8,\
<svg xmlns='http://www.w3.org/2000/svg' viewBox='0 0 24 24' fill='none'>\
<path d='M6 9L12 15L18 9' stroke='currentColor' stroke-width='2' stroke-linecap='round' stroke-linejoin='round'/>\
</svg>");
background-repeat: no-repeat;
background-position: right 10px center;
background-size: 20px;
cursor: pointer;
}
select:open {
background-image: url("data:image/svg+xml;utf8,\
<svg xmlns='http://www.w3.org/2000/svg' viewBox='0 0 24 24' fill='none'>\
<path d='M18 15L12 9L6 15' stroke='currentColor' stroke-width='2' stroke-linecap='round' stroke-linejoin='round'/>\
</svg>");
}

View File

@@ -0,0 +1,949 @@
:root {
--paddingSite: 40px;
--card-radius: 20px;
--card-bg: #ffffff;
--bg: #FDFDFD;
--bg-top: rgb(74, 85, 104);
--bg-top-raw: 74 85 104;
--card-shadow: 0 10px 30px rgba(15, 23, 42, 0.08);
--accent: #4a5568;
--accent-soft: #f0f5ff;
--border-subtle: #d4d7e1;
--text-main: #191919;
--text-muted: #5e5e5e;
--disabled-bg: #f3f4f6;
--disabled-border: #cbd5f5;
}
/* ── Base ─────────────────────────────────────────────── */
*,
*::after,
*::before {
box-sizing: border-box;
-webkit-tap-highlight-color: transparent;
font-family: "Google Sans Flex", sans-serif;
font-optical-sizing: auto;
font-style: normal;
font-variation-settings:
"slnt" 0,
"wdth" 100,
"GRAD" 0,
"ROND" 0;
}
html,
body,
section {
margin: 0;
overscroll-behavior: none;
}
body {
margin: 0;
width: 100vw;
background: var(--bg);
}
::selection {
background: #0000003d;
color: #ffffffff;
}
::-moz-selection {
background: #a4bf4a99;
color: #000;
}
input {
border: none;
}
/* ── Layout ───────────────────────────────────────────── */
.bgSection {
position: relative;
margin-left: auto;
width: 100vw;
box-sizing: border-box !important;
background: none;
}
@media (min-width: 1000px) {
.bgSection.open {
width: calc(100vw - 380px);
}
}
/* ── Header ───────────────────────────────────────────── */
.headerDivTrainer {
padding: var(--paddingSite);
background-color: var(--bg-top);
margin-bottom: var(--paddingSite);
position: relative;
z-index: 3;
display: flex;
justify-content: space-between;
align-items: center;
}
.headingPanelDiv {
display: flex;
flex-direction: column;
}
.headingPanelDiv>* {
color: var(--bg);
}
.headingPanel {
margin: 0;
font-weight: 200;
}
/* ── Actions bar (new user / new verein) ──────────────── */
.bg-erfassen {
display: flex;
flex-wrap: wrap;
gap: 12px;
padding: 0 var(--paddingSite) 10px;
}
.bg-erfassen button[type="submit"] {
appearance: none;
border: 1px dashed var(--accent);
background: none;
color: var(--text-main);
padding: 10px 22px;
border-radius: 8px;
font-size: 0.95rem;
font-weight: 500;
cursor: pointer;
transition: all 0.25s ease;
}
.bg-erfassen button[type="submit"]:hover {
background: var(--bg-top);
border-color: var(--bg-top);
color: #fff;
}
/* ── Section headings (Vereine / Benutzer) ────────────── */
h3.vereine,
h3.benutzer {
padding: 0 var(--paddingSite);
font-weight: 400;
font-size: 1.15rem;
color: var(--text-main);
margin: 30px 0 12px;
letter-spacing: 0.02em;
}
/* ── Inner section (card list) ────────────────────────── */
.inner-pw-set-bg {
padding: 0 var(--paddingSite);
display: flex;
flex-direction: column;
gap: 14px;
margin-bottom: 20px;
align-items: start;
}
/* ── User / Verein card ───────────────────────────────── */
.single_pwedit {
background: var(--card-bg);
border-radius: var(--card-radius);
box-shadow: var(--card-shadow);
padding: 24px 28px;
transition: box-shadow 0.25s ease;
}
.single_pwedit:hover {
box-shadow: 0 14px 40px rgba(15, 23, 42, 0.12);
}
.single_pwedit.verein {
border-left: 4px solid var(--bg-top);
}
/* ── Form fields inside user card ─────────────────────── */
.single_pwedit form {
display: flex;
flex-wrap: wrap;
gap: 14px 24px;
align-items: flex-end;
}
.single_pwedit label {
display: block;
font-size: 0.8rem;
font-weight: 500;
text-transform: uppercase;
letter-spacing: 0.06em;
color: var(--text-muted);
margin-bottom: 5px;
}
.single_pwedit .field-group {
flex: 1 1 200px;
min-width: 0;
}
.single_pwedit input[type="text"] {
width: 100%;
padding: 9px 12px;
border: 1px dashed #999;
border-radius: 6px;
font-size: 0.95rem;
font-weight: 300;
color: var(--text-main);
background: #fff;
transition: border-color 0.2s ease, box-shadow 0.2s ease;
}
.single_pwedit input[type="text"]:focus {
outline: none;
border: 1px solid var(--bg-top);
box-shadow: 0 0 0 3px rgba(var(--bg-top-raw) / 0.12);
}
.single_pwedit input[type="text"]::placeholder {
color: #b0b0b0;
font-style: italic;
}
/* ── Buttons inside cards ─────────────────────────────── */
.single_pwedit button[type="submit"] {
appearance: none;
border: 1px solid #7777778e;
background: #7777778e;
color: var(--bg);
padding: 9px 20px;
border-radius: 6px;
font-size: 0.9rem;
font-weight: 400;
cursor: pointer;
transition: all 0.25s ease;
white-space: nowrap;
}
.single_pwedit button[type="submit"]:hover {
background: var(--bg-top);
border-color: var(--bg-top);
color: #fff;
font-weight: 600;
}
.delete-user-btn,
.delete-verein-btn {
appearance: none;
background: none;
border: 1px solid #fca5a5;
color: #b91c1c;
padding: 8px 18px;
border-radius: 6px;
font-size: 0.85rem;
font-weight: 500;
cursor: pointer;
margin-top: 10px;
transition: all 0.25s ease;
}
.delete-user-btn:hover,
.delete-verein-btn:hover {
background: #fef2f2;
border-color: #ef4444;
color: #dc2626;
}
.createOturl {
appearance: none;
background: none;
border: 1px solid var(--border-subtle);
color: var(--text-muted);
padding: 8px 18px;
border-radius: 6px;
font-size: 0.85rem;
font-weight: 500;
cursor: pointer;
margin-top: 10px;
margin-left: 8px;
transition: all 0.25s ease;
}
.createOturl:hover {
background: var(--accent-soft);
border-color: var(--bg-top);
color: var(--bg-top);
}
/* ── Permission dropdown ──────────────────────────────── */
.perm-section {
width: 100%;
margin-top: 12px;
border: 1px solid #e5e7eb;
border-radius: 10px;
overflow: hidden;
transition: box-shadow 0.2s ease;
}
.perm-section:hover {
box-shadow: 0 2px 8px rgba(0, 0, 0, 0.04);
}
.perm-section-header {
display: flex;
align-items: center;
justify-content: space-between;
padding: 10px 16px;
background: #f9fafb;
cursor: pointer;
user-select: none;
transition: background 0.15s ease;
}
.perm-section-header:hover {
background: #f3f4f6;
}
.perm-section-title {
font-size: 0.85rem;
font-weight: 600;
color: var(--text-main);
display: flex;
align-items: center;
gap: 8px;
}
.perm-section-title .perm-badge {
display: inline-flex;
align-items: center;
justify-content: center;
min-width: 22px;
height: 22px;
padding: 0 6px;
border-radius: 11px;
background: var(--bg-top);
color: #fff;
font-size: 0.7rem;
font-weight: 700;
}
.perm-section-chevron {
width: 20px;
height: 20px;
transition: transform 0.3s ease;
color: var(--text-muted);
}
.perm-section.open .perm-section-chevron {
transform: rotate(180deg);
}
.perm-section-body {
max-height: 0;
overflow: hidden;
transition: max-height 0.35s cubic-bezier(0.4, 0, 0.2, 1),
padding 0.35s cubic-bezier(0.4, 0, 0.2, 1);
padding: 0 16px;
}
.perm-section.open .perm-section-body {
max-height: 500px;
padding: 12px 16px 16px;
}
.perm-section-body label {
display: flex;
align-items: center;
gap: 8px;
padding: 6px 0;
font-size: 0.9rem;
font-weight: 400;
color: var(--text-main);
text-transform: none;
letter-spacing: 0;
cursor: pointer;
transition: color 0.15s ease;
}
.perm-section-body label:hover {
color: var(--bg-top);
}
.perm-section-body input[type="checkbox"] {
width: 16px;
height: 16px;
accent-color: var(--bg-top);
cursor: pointer;
flex-shrink: 0;
}
/* ── Programme section ────────────────────────────────── */
section:has(> div > h1) {
padding: 0 var(--paddingSite) var(--paddingSite);
}
section h1 {
font-weight: 400;
font-size: 1.3rem;
color: var(--text-main);
margin-bottom: 16px;
}
.neuProgrammForm {
display: flex;
gap: 12px;
margin-bottom: 20px;
align-items: center;
}
.neuProgrammForm input[type="text"] {
padding: 9px 12px;
border: 1px dashed #999;
border-radius: 6px;
font-size: 0.95rem;
font-weight: 300;
color: var(--text-main);
min-width: 200px;
transition: border-color 0.2s ease;
}
.neuProgrammForm input[type="text"]:focus {
outline: none;
border-color: var(--bg-top);
}
.neuProgrammForm input[type="submit"] {
padding: 9px 20px;
border: 1px solid #7777778e;
background: #7777778e;
color: var(--bg);
border-radius: 6px;
font-size: 0.9rem;
cursor: pointer;
transition: all 0.25s ease;
}
.neuProgrammForm input[type="submit"]:hover {
background: var(--bg-top);
border-color: var(--bg-top);
color: #fff;
}
/* ── Programme table ──────────────────────────────────── */
table {
border-collapse: collapse;
margin: 0;
padding: 0;
width: 100%;
}
.wkvsTabelle th {
color: #424242;
border-bottom: solid 1px #0000007d;
font-weight: 600;
padding: 14px 15px;
font-size: 16px;
}
.wkvsTabelle td {
background: none;
color: #191919;
font-weight: 400;
padding: 10px 15px;
border-bottom: solid 1px #6262624d;
}
.wkvsTabelle.trainer td {
padding: 8px 15px;
}
.wkvsTabelle tr:hover {
background-color: #f4f4f4;
}
.inputPreisProgramm,
.inputAktivProgramm {
padding: 6px 10px;
border: 1px dashed #999;
border-radius: 4px;
font-size: 0.9rem;
transition: border-color 0.2s ease, background-color 0.4s ease;
}
.inputPreisProgramm:focus,
.inputAktivProgramm:focus {
outline: none;
border-color: var(--bg-top);
}
input[type="number"] {
-moz-appearance: textfield;
}
input[type="number"]::-webkit-inner-spin-button,
input[type="number"]::-webkit-outer-spin-button {
-webkit-appearance: none;
margin: 0;
}
.deleteProgramm {
appearance: none;
background: none;
border: none;
cursor: pointer;
}
select {
appearance: none;
-webkit-appearance: none;
-moz-appearance: none;
width: 100%;
padding: 8px 35px 8px 12px !important;
font-size: 14px;
border: 1px solid #ccc;
border-radius: 6px;
background-color: #fff;
background-image: url("data:image/svg+xml;utf8,<svg xmlns='http://www.w3.org/2000/svg' viewBox='0 0 24 24' fill='none'><path d='M6 9L12 15L18 9' stroke='currentColor' stroke-width='2' stroke-linecap='round' stroke-linejoin='round'/></svg>");
background-repeat: no-repeat;
background-position: right 10px center;
background-size: 18px;
cursor: pointer;
}
/* ── One-time URL Modal ───────────────────────────────── */
.ot-modal {
display: none;
position: fixed;
inset: 0;
background: rgba(0, 0, 0, 0.4);
backdrop-filter: blur(4px);
z-index: 9999;
align-items: center;
justify-content: center;
}
.ot-modal-content {
background: #fff;
border-radius: 16px;
padding: 28px 32px;
max-width: 520px;
width: 90%;
box-shadow: 0 20px 60px rgba(0, 0, 0, 0.2);
}
.ot-modal-top-content {
display: flex;
justify-content: space-between;
align-items: center;
margin-bottom: 16px;
}
.ot-title {
font-size: 1.1rem;
font-weight: 600;
color: var(--text-main);
}
.ot-close-btn {
appearance: none;
background: none;
border: none;
font-size: 1.3rem;
color: #888;
cursor: pointer;
transition: color 0.2s ease;
padding: 4px 8px;
}
.ot-close-btn:hover {
color: #d63638;
}
.ot-url {
display: block;
word-break: break-all;
padding: 12px 16px;
background: #f9fafb;
border: 1px solid #e5e7eb;
border-radius: 8px;
color: var(--bg-top);
font-size: 0.85rem;
font-weight: 500;
margin-bottom: 12px;
text-decoration: none;
transition: background 0.2s ease;
}
.ot-url:hover {
background: #f0f1f3;
}
#oturlGb {
font-size: 0.82rem;
color: var(--text-muted);
margin: 0 0 16px;
}
.ot-copy-btn {
appearance: none;
width: 100%;
padding: 10px;
background: var(--bg-top);
color: #fff;
border: none;
border-radius: 8px;
font-size: 0.95rem;
font-weight: 600;
cursor: pointer;
transition: filter 0.2s ease;
}
.ot-copy-btn:hover {
filter: brightness(1.15);
}
/* ── Success / Error Overlays ─────────────────────────── */
.divSucsess,
.divError {
position: fixed;
bottom: 30px;
right: 30px;
padding: 14px 28px;
border-radius: 10px;
font-weight: 600;
font-size: 0.95rem;
z-index: 10000;
transform: translateX(calc(100% + 60px));
transition: transform 0.4s cubic-bezier(0.4, 0, 0.2, 1);
box-shadow: 0 8px 24px rgba(0, 0, 0, 0.12);
}
.divSucsess {
background: #ecfdf3;
color: #15803d;
border-left: 4px solid #4ade80;
}
.divError {
background: #fef2f2;
color: #b91c1c;
border-left: 4px solid #fca5a5;
}
.divSucsess.show,
.divError.show {
transform: translateX(0);
}
/* ── Loading overlays ─────────────────────────────────── */
#loading-overlay,
#new-overlay,
#new-reload {
display: none;
position: fixed;
top: 0;
left: 0;
width: 100%;
height: 100%;
z-index: 9999;
text-align: center;
}
#loading-overlay,
#new-overlay {
background: rgba(0, 0, 0, 0.5);
}
#new-reload {
background: rgba(0, 100, 0, 0.5);
}
#loading-overlay>div,
#new-overlay>div,
#new-reload>div {
position: absolute;
top: 50%;
left: 50%;
transform: translate(-50%, -50%);
color: white;
font-size: 1.2rem;
font-weight: 400;
}
/* ── Burger / sidebar (shared with other pages) ───────── */
.trainerBurgerMenuDiv {
display: flex;
align-items: center;
justify-content: center;
width: 28px;
height: 28px;
cursor: pointer;
z-index: 99;
color: var(--bg);
}
.trainerBurgerMenuDiv svg {
width: 100%;
height: 100%;
stroke: currentColor;
transition: transform 0.3s ease;
}
.trainerBurgerMenuDiv.open svg {
transform: rotate(-90deg);
}
.internMenuDiv {
background-color: #fff;
box-shadow: none;
position: fixed;
left: 0;
top: 0;
height: 100svh;
width: 100%;
max-width: 380px;
transform: translateX(-100%);
z-index: 100;
padding: 20px;
transition: transform 0.45s cubic-bezier(.4, 0, .2, 1);
opacity: 1;
}
.internMenuDiv.open {
transform: translateX(0);
box-shadow: 4px 0 20px rgba(0, 0, 0, 0.15);
}
.innerInternMenuDiv {
display: flex;
flex-direction: column;
gap: 14px;
height: 100dvh;
overflow-y: auto;
padding-bottom: 80px;
}
.innerInternMenuDiv input[type="submit"],
.innerInternMenuDiv select {
width: 100%;
padding: 12px 14px;
border-radius: 10px;
border: 1px solid #ccc;
font-size: 0.95rem;
transition: all 0.3s ease;
}
.innerInternMenuDiv input[type="submit"]:focus,
.innerInternMenuDiv select:focus {
outline: none;
border-color: var(--bg-top);
box-shadow: 0 0 6px rgba(var(--bg-top-raw) / 0.3);
}
.innerInternMenuDiv .button-secondary {
background: linear-gradient(135deg, var(--bg-top), #1f4f75);
color: #fff;
border: none;
border-radius: 12px;
font-weight: 600;
cursor: pointer;
padding: 12px 18px;
transition: transform 0.2s ease, background 0.3s ease;
box-shadow: 0 4px 10px rgba(0, 0, 0, 0.1);
}
.innerInternMenuDiv .button-secondary:hover {
filter: brightness(0.9);
transform: translateY(-2px);
}
.footerInternMenu {
display: flex;
flex-direction: row;
justify-content: space-between;
position: absolute;
bottom: 12px;
gap: 40px;
width: calc(100% - 40px);
}
.footerInternMenu>* {
display: flex;
}
.menuBg {
position: fixed;
inset: 0;
z-index: 98;
user-select: none;
pointer-events: none;
opacity: 0;
}
.menuBg.menuTransition {
transition: opacity 0.6s ease-out;
}
.menuTransition {
transition: all 0.6s ease-out;
}
.closeInternMenuMobileDiv {
display: none;
width: 5vw;
height: 100px;
position: absolute;
top: 30px;
right: -5vw;
background-color: #09090966;
border-radius: 0 10px 10px 0;
}
/* ── Responsive ───────────────────────────────────────── */
@media (max-width: 480px) {
.internMenuDiv {
max-width: 95vw;
}
.internMenuDiv.open .closeInternMenuMobileDiv {
display: block;
}
}
@media (max-width: 600px) {
:root {
--paddingSite: 20px;
}
.single_pwedit {
padding: 18px 16px;
border-radius: 14px;
}
.single_pwedit form {
flex-direction: column;
}
.single_pwedit .field-group {
flex: 1 1 100%;
}
.bg-erfassen {
flex-direction: column;
}
}
@media (min-width: 768px) {
.inner-pw-set-bg {
display: grid;
grid-template-columns: repeat(auto-fill, minmax(420px, 1fr));
}
}
.checkbox {
display: inline-flex;
align-items: center;
gap: 8px;
cursor: pointer;
position: relative;
}
.checkbox input {
position: absolute;
top: 0;
left: 0;
width: 100%;
height: 100%;
margin: 0;
opacity: 0;
cursor: pointer;
pointer-events: all;
}
/* Custom box */
.checkbox-ui {
width: 16px;
height: 16px;
background: rgb(212, 212, 212);
border-radius: 3px;
display: inline-flex;
align-items: center;
justify-content: center;
transition: background 0.2s, border-color 0.2s;
}
/* Checked state */
.checkbox input:checked+.checkbox-ui,
.checkbox-ui.manuelChecked {
background: #1cde60ff;
}
/* Focus state */
.checkbox input:focus-visible+.checkbox-ui {
outline: 2px solid #93c5fd;
outline-offset: 2px;
}
.addRow input {
padding: 6px 10px;
border: 1px dashed var(--bg-top);
border-radius: 4px;
font-size: 0.9rem;
width: 100%;
}
.addRow button {
padding: 6px 14px;
border: 1px solid var(--bg-top);
background: var(--bg-top);
color: #fff;
border-radius: 4px;
font-size: 0.85rem;
font-weight: 500;
cursor: pointer;
transition: all 0.2s;
}
.containerSection {
padding: var(--paddingSite) calc(var(--paddingSite) * 1.5);
margin-bottom: var(--paddingSite);
}
#qrcode {
display: inline-flex;
padding: 12px 16px;
background: #f9fafb;
border: 1px solid #e5e7eb;
border-radius: 8px;
color: var(--bg-top);
font-size: 0.85rem;
font-weight: 500;
margin-bottom: 12px;
text-decoration: none;
transition: background 0.2s ease;
}
.qrcodeWrapper {
display: flex;
align-items: center;
justify-content: center;
margin: 30px 0;
}

File diff suppressed because it is too large Load Diff

View File

@@ -0,0 +1,509 @@
:root {
--main: #fe3f18;
--bg-top-raw: 254 63 24;
--main-box-shadow: rgb(from var(--main) r g b / 0.05);
--accent: #cfef00;
--accent-hover: #c5e300;
--paddingSite: 40px;
--card-radius: 20px;
--card-bg: #ffffff;
--bg: #FDFDFD;
--card-shadow: 0 10px 30px rgba(15, 23, 42, 0.08);
--border-subtle: #d4d7e1;
--text-main: #191919;
--text-muted: #5e5e5e;
}
/* --- BASE & TYPOGRAPHY --- */
*,
*::before,
*::after {
box-sizing: border-box;
-webkit-tap-highlight-color: transparent;
}
b {
font-weight: 600;
}
body {
margin: 0;
width: 100vw;
background: var(--bg);
color: var(--text-main);
overflow-x: hidden;
overscroll-behavior: none;
font-optical-sizing: auto;
}
/* --- LAYOUT WRAPPERS --- */
.bgSection {
position: relative;
width: 100vw;
margin-left: auto;
box-sizing: border-box;
background: none;
min-height: 100vh;
}
@media (min-width: 1200px) {
.bgSection.open {
width: calc(100vw - 450px);
}
}
.menuTransition {
transition: transform 0.45s cubic-bezier(.4, 0, .2, 1), width 0.45s cubic-bezier(.4, 0, .2, 1) !important;
}
/* --- HEADER --- */
.headerDivKampfrichter {
display: flex;
justify-content: space-between;
align-items: center;
padding: var(--paddingSite);
background: linear-gradient(135deg, var(--main), #d85a00);
color: #fff;
margin-bottom: var(--paddingSite);
position: relative;
z-index: 3;
}
.heading-pannel {
margin: 0;
font-weight: 300;
font-size: 2rem;
letter-spacing: -0.5px;
}
.menuWrapper {
display: flex;
align-items: center;
gap: 24px;
}
.allTurnerinenDiv {
padding: 0 var(--paddingSite);
}
/* --- FOOTER / LOGOUT --- */
.footerInternMenu {
margin-top: auto;
padding-top: 20px;
}
/* Burger + menu (unchanged from your style) */
.wk-leitungBurgerMenuDiv {
display: flex;
align-items: center;
justify-content: center;
width: 28px;
height: 28px;
cursor: pointer;
z-index: 99;
color: var(--bg);
}
.wk-leitungBurgerMenuDiv svg {
width: 100%;
height: 100%;
stroke: currentColor;
transition: transform 0.3s ease;
}
.wk-leitungBurgerMenuDiv.open svg {
transform: rotate(45deg);
}
.internMenuDiv {
background-color: #fff;
box-shadow: none;
position: fixed;
left: 0;
top: 0;
height: 100svh;
width: 100%;
max-width: 450px;
transform: translateX(-100%);
z-index: 100;
padding: 20px;
transition: transform 0.45s cubic-bezier(.4, 0, .2, 1);
opacity: 1;
}
.internMenuDiv.open {
transform: translateX(0);
box-shadow: 4px 0 20px rgba(0, 0, 0, 0.15);
}
.innerInternMenuDiv {
display: flex;
flex-direction: column;
gap: 14px;
height: 100dvh;
overflow-y: auto;
padding-bottom: 80px;
}
.text_akt_abt {
font-size: 1rem;
color: #555;
text-align: center;
line-height: 1.6;
}
.innerInternMenuDiv form {
margin: 0;
}
.innerInternMenuDiv input[type="submit"],
.innerInternMenuDiv select {
width: 100%;
padding: 12px 14px;
border-radius: 10px;
border: 1px solid #ccc;
font-size: 0.95rem;
transition: all 0.3s ease;
}
.innerInternMenuDiv input[type="submit"]:focus,
.innerInternMenuDiv select:focus {
outline: none;
border-color: #2d73ac;
box-shadow: 0 0 6px rgba(45, 115, 172, 0.3);
}
.innerInternMenuDiv .button-secondary {
background: linear-gradient(135deg, #2d73ac, #1f4f75);
color: #fff;
border: none;
border-radius: 12px;
font-weight: 600;
cursor: pointer;
padding: 12px 18px;
transition: transform 0.2s ease, background 0.3s ease;
box-shadow: 0 4px 10px rgba(0, 0, 0, 0.1);
}
.innerInternMenuDiv .button-secondary:hover {
background: linear-gradient(135deg, #245d8a, #163b5a);
transform: translateY(-2px);
}
/* Riegeneinteilung Specific Styles */
.headerAbt {
display: flex;
align-items: center;
gap: 16px;
margin-bottom: 8px;
}
.headerAbt h2 {
margin: 0;
font-weight: 400;
color: var(--main);
font-size: 1.5rem;
}
.deleteProgramm {
display: flex;
align-items: center;
justify-content: center;
background: #fff;
border: 1px solid #fee2e2;
border-radius: 50%;
width: 36px;
height: 36px;
cursor: pointer;
transition: all 0.2s ease;
box-shadow: 0 2px 4px rgba(244, 63, 94, 0.1);
}
.deleteProgramm:hover {
transform: scale(1.1);
background: #fee2e2;
box-shadow: 0 4px 8px rgba(244, 63, 94, 0.2);
}
.deleteProgramm svg,
.deleteProgramm path {
fill: #f43f5e;
}
#bin-lid {
transform-origin: 50% 100%;
transform-box: fill-box;
transition: transform 0.3s ease;
}
.deleteProgramm:hover #bin-lid {
transform: rotate(20deg) translateY(-100px);
}
/* Sidebar Menu Button Styling */
.header-text-conatiner {
display: flex;
flex-direction: column;
padding: 20px;
gap: 15px;
}
.header-text-conatiner button {
cursor: pointer;
font-weight: 600;
transition: all 0.2s ease;
padding: 12px 20px;
border-radius: 100px;
background: var(--accent);
border: 1px solid transparent;
font-size: 15px;
color: #000;
width: 100%;
box-shadow: 0 4px 6px rgba(207, 239, 0, 0.2);
}
.header-text-conatiner button:hover {
background: var(--accent-hover);
transform: translateY(-2px);
box-shadow: 0 6px 12px rgba(207, 239, 0, 0.3);
}
.header-text-conatiner button:active {
transform: scale(0.98) translateY(0);
}
.header-text-conatiner label {
font-weight: 400;
color: var(--text-main);
font-size: 0.9rem;
margin-bottom: -5px;
}
.header-text-conatiner input[type="number"] {
padding: 12px 15px;
border-radius: 12px;
border: 1px solid var(--border-subtle);
background: #fff;
font-size: 15px;
outline: none;
transition: all 0.2s ease;
width: 100%;
}
.header-text-conatiner input[type="number"]:focus {
border-color: var(--main);
box-shadow: 0 0 0 3px rgba(40, 102, 110, 0.1);
}
/* Custom Table / Drag and Drop Area */
.geraet-table {
background: var(--card-bg);
border: 1px solid var(--border-subtle);
border-radius: 16px;
box-shadow: var(--card-shadow);
min-width: 260px;
overflow: hidden;
margin-right: 15px;
transition: all 0.3s ease;
border-collapse: separate;
border-spacing: 0;
}
.geraet-table thead {
background: var(--main);
}
.geraet-table thead th {
display: flex;
justify-content: space-between;
color: #fff;
padding: 14px 20px;
font-weight: 300;
font-size: 1.05rem;
text-align: left;
letter-spacing: 0.5px;
border-bottom: 1px solid var(--border-subtle);
}
.geraet-table thead th i span {
font-size: 0.9rem;
opacity: 0.8;
font-weight: 400;
}
.geraet-table tbody {
display: block;
max-height: 480px;
overflow-y: auto;
overscroll-behavior-y: contain;
padding: 10px;
}
/* Custom Scrollbar for tbody */
.geraet-table tbody::-webkit-scrollbar {
width: 6px;
}
.geraet-table tbody::-webkit-scrollbar-track {
background: #f1f5f9;
border-radius: 10px;
}
.geraet-table tbody::-webkit-scrollbar-thumb {
background: #cbd5e1;
border-radius: 10px;
}
.geraet-table tbody::-webkit-scrollbar-thumb:hover {
background: #94a3b8;
}
.turnerin-row {
cursor: grab;
background: #fff;
border-radius: 8px;
margin-bottom: 8px;
transition: transform 0.2s cubic-bezier(0.34, 1.56, 0.64, 1), box-shadow 0.2s ease;
display: block;
border: 1px solid transparent;
user-select: none;
-webkit-user-select: none;
-webkit-touch-callout: none;
}
.turnerin-row:active {
cursor: grabbing;
}
.turnerin-row>td {
padding: 12px 16px;
border: none;
display: block;
width: 100%;
color: var(--text-main);
font-weight: 200;
}
.turnerin-row:hover {
box-shadow: 0 4px 12px rgba(0, 0, 0, 0.08);
transform: translateY(-2px);
z-index: 10;
position: relative;
border-color: #cbd5e1;
}
/* Drag State */
.dragging {
opacity: 0.9 !important;
box-shadow: 0 15px 30px rgba(0, 0, 0, 0.15) !important;
transform: scale(1.03) rotate(1deg) !important;
z-index: 9999 !important;
}
.drop-placeholder {
height: 54px;
background: #f8fafc;
border: 2px dashed #94a3b8;
border-radius: 8px;
margin: 8px 0;
}
.ui-sortable {
min-height: 120px;
}
.empty-drop-row td {
padding: 20px;
text-align: center;
color: var(--text-muted);
font-style: italic;
}
/* Grouping Row Styling */
.group-row {
background: transparent;
margin-bottom: 12px;
}
.group-row>td {
padding: 0;
display: block;
}
.group-header {
padding: 12px 16px;
cursor: grab;
gap: 18px;
border-radius: 10px;
font-weight: 200;
box-shadow: 0 2px 6px rgba(0, 0, 0, 0.05);
margin-bottom: 6px;
display: flex;
user-select: none;
-webkit-user-select: none;
-webkit-touch-callout: none;
justify-content: space-between;
align-items: center;
}
.group-header:active {
cursor: grabbing;
}
.group-inner {
width: 100%;
border-collapse: separate;
border-spacing: 0;
padding-left: 10px;
}
.group-row .group-inner {
display: none;
}
/* Invalid / Unassigned Wrapper */
.invalidAbtDiv {
padding: 20px;
border-radius: 12px;
margin: 20px 20px;
}
.invalidAbtDiv .geraet-table {
box-shadow: none;
border-color: #fecdd3;
width: 100%;
}
.invalidAbtDiv .geraet-table thead {
background: #ffe4e6;
}
.invalidAbtDiv .geraet-table thead th {
color: #e11d48;
}
/* Horizontal scroll area for departments */
.allTurnerinenDiv>div {
padding-bottom: 20px;
}
.allTurnerinenDiv>div>div:last-child {
overflow-x: auto;
padding: 10px 0 20px 0;
}
.allTurnerinenDiv>div>div:last-child::-webkit-scrollbar {
height: 8px;
}
.allTurnerinenDiv>div>div:last-child::-webkit-scrollbar-track {
background: #f1f5f9;
border-radius: 10px;
}
.allTurnerinenDiv>div>div:last-child::-webkit-scrollbar-thumb {
background: #cbd5e1;
border-radius: 10px;
}

341
www/intern/css/sidebar.css Normal file
View File

@@ -0,0 +1,341 @@
/* ─── Sidebar Navigation ─── */
:root {
--sidebar-width: 280px;
--sidebar-bg: #fafafa;
--sidebar-text: #363636;
--sidebar-hover: rgb(var(--bg-top-raw) / 0.2);
--sidebar-active: rgb(var(--bg-top-raw) / 0.35);
--sidebar-transition: 0.35s cubic-bezier(0.4, 0, 0.2, 1);
}
/* Sidebar Panel */
.sidebar-nav {
position: fixed;
top: 0;
left: 0;
width: var(--sidebar-width);
height: 100vh;
background: var(--sidebar-bg);
z-index: 10000;
transform: translateX(-100%);
transition: transform var(--sidebar-transition);
display: flex;
flex-direction: column;
overflow-y: auto;
box-shadow: 4px 0 24px rgba(0, 0, 0, 0.25);
}
.sidebar-nav.open {
transform: translateX(0);
}
/* Sidebar Header */
.sidebar-header {
padding: 28px 24px 20px;
border-bottom: 1px solid rgba(255, 255, 255, 0.08);
display: flex;
align-items: center;
justify-content: space-between;
}
.sidebar-header h3 {
margin: 0;
font-size: 16px;
font-weight: 600;
color: #111;
letter-spacing: 0.5px;
}
.sidebar-close-btn {
background: none;
border: none;
color: var(--sidebar-text);
cursor: pointer;
padding: 4px;
display: flex;
align-items: center;
border-radius: 6px;
transition: background 0.2s;
}
.sidebar-close-btn:hover {
background: var(--sidebar-hover);
}
/* Section Labels */
.sidebar-section-label {
padding: 20px 24px 8px;
font-size: 11px;
font-weight: 700;
text-transform: uppercase;
letter-spacing: 1.2px;
color: rgba(45, 45, 45, 0.35);
}
/* Links */
.sidebar-links {
list-style: none;
margin: 0;
padding: 0;
flex: 1;
}
.sidebar-links a {
display: flex;
align-items: center;
gap: 14px;
padding: 12px 24px;
color: var(--sidebar-text);
text-decoration: none;
font-size: 14px;
font-weight: 500;
transition: all 0.2s;
border-left: 3px solid transparent;
}
.sidebar-links a:hover {
background: var(--sidebar-hover);
color: #222;
}
.sidebar-links a.active {
background: var(--sidebar-active);
color: #111;
border-left-color: var(--bg-top);
}
.sidebar-links a svg {
width: 20px;
height: 20px;
flex-shrink: 0;
stroke: currentColor;
fill: none;
stroke-width: 1.8;
stroke-linecap: round;
stroke-linejoin: round;
}
/* Overlay */
.sidebar-overlay {
position: fixed;
inset: 0;
background: rgba(0, 0, 0, 0.2);
backdrop-filter: blur(2px);
z-index: 9999;
opacity: 0;
pointer-events: none;
transition: opacity var(--sidebar-transition);
}
.sidebar-overlay.open {
opacity: 1;
pointer-events: auto;
}
/* Hamburger Toggle */
.sidebar-toggle {
background: var(--sidebar-bg);
border: none;
border-radius: 10px;
width: 44px;
height: 44px;
cursor: pointer;
display: flex;
flex-direction: column;
align-items: center;
justify-content: center;
gap: 5px;
box-shadow: 0 2px 12px rgba(0, 0, 0, 0.2);
transition: all var(--sidebar-transition);
padding: 0;
}
.sidebar-toggle span {
display: block;
width: 20px;
height: 2px;
background: #111;
border-radius: 2px;
transition: all 0.3s;
}
.sidebar-toggle.open span:nth-child(1) {
transform: rotate(45deg) translate(5px, 5px);
}
.sidebar-toggle.open span:nth-child(2) {
opacity: 0;
}
.sidebar-toggle.open span:nth-child(3) {
transform: rotate(-45deg) translate(5px, -5px);
}
/* Footer */
.sidebar-footer {
padding: 16px 24px;
border-top: 1px solid rgba(42, 42, 42, 0.222);
font-size: 11px;
color: rgba(42, 42, 42, 0.485);
}
.menuWrapper {
display: flex;
align-items: center;
gap: 16px;
}
.abmeldenbutton {
width: 100%;
padding: 14px;
background: linear-gradient(135deg, #e53935, #b71c1c);
border: none;
border-radius: 12px;
font-weight: 600;
color: #fff;
cursor: pointer;
transition: transform 0.2s ease, background 0.3s ease;
box-shadow: 0 4px 10px rgba(0, 0, 0, 0.1);
}
.abmeldenbutton:hover {
background: linear-gradient(135deg, #c62828, #8e1919);
transform: translateY(-2px);
}
.sidebarUsername {
padding: 20px 24px 8px;
font-size: 14px;
font-weight: 400;
color: rgba(45, 45, 45, 0.85);
}
.customSelect {
position: relative;
}
.customSelect>* {
margin: 0;
}
.selectTrigger .selectArrow {
transition: rotate 0.6s ease;
}
table input {
height: 38px;
}
.selectTrigger,
.selectTriggerBulk {
background: none;
border: none;
padding: 0;
display: flex;
justify-content: space-between;
align-items: center;
cursor: pointer;
}
.sidebar-nav .selectOptions,
.sidebar-nav .selectOptionsBulk {
position: absolute;
top: calc(100% + 4px);
left: 0;
right: 0;
padding: 4px;
list-style: none;
border: 1px solid;
border-radius: 12px;
background: var(--sidebar-bg);
z-index: 1000;
box-shadow: 0 4px 16px rgba(0, 0, 0, 0.08);
opacity: 0;
transform: scaleY(0);
transform-origin: top;
pointer-events: none;
transition: opacity 0.2s ease, transform 0.2s ease;
}
.sidebar-nav .customSelect.open .selectOptions,
.sidebar-nav .customSelect.open .selectOptionsBulk {
opacity: 1;
transform: scaleY(1);
pointer-events: auto;
}
.customSelect.open .selectArrow {
rotate: 180deg
}
.selectOptions li,
.selectOptionsBulk li {
padding: 10px 14px;
cursor: pointer;
border-radius: 8px;
margin-bottom: 2px;
transition: background-color 0.15s ease;
}
.selectOptions li:last-child,
.selectOptionsBulk li:last-child {
margin-bottom: 0;
}
/* ─── Sidebar Freigaben ─── */
.sidebar-li-freigaben {
padding: 0 24px 16px 42px;
/* Indented under the icon of the active link */
margin-top: 4px;
}
.sidebar-freigaben-label {
display: block;
font-size: 10px;
font-weight: 600;
text-transform: uppercase;
color: rgba(45, 45, 45, 0.45);
margin-bottom: 6px;
letter-spacing: 0.5px;
}
.sidebar-li-freigaben .selectTrigger {
width: 100%;
padding: 9px 12px;
background: #fff;
border: 1px solid rgba(0, 0, 0, 0.08);
border-radius: 8px;
font-size: 13px;
font-weight: 500;
color: var(--sidebar-text);
transition: all 0.2s ease;
box-shadow: 0 1px 3px rgba(0, 0, 0, 0.02);
}
.sidebar-li-freigaben .selectTrigger:hover {
border-color: rgba(0, 0, 0, 0.15);
background: #fcfcfc;
box-shadow: 0 2px 4px rgba(0, 0, 0, 0.04);
}
.sidebar-li-freigaben .selectOptions {
background: #fff;
border: 1px solid rgba(0, 0, 0, 0.1);
box-shadow: 0 8px 24px rgba(0, 0, 0, 0.12);
margin-top: 2px;
}
.sidebar-li-freigaben .selectOptions li {
font-size: 13px;
padding: 8px 12px;
}
.sidebar-li-freigaben .selectOptions li.selected {
background: var(--sidebar-active);
color: #111;
font-weight: 600;
}

1609
www/intern/css/trainer.css Normal file

File diff suppressed because it is too large Load Diff

77
www/intern/css/wkvs.css Normal file
View File

@@ -0,0 +1,77 @@
.welcomeScreen{
position: fixed;
top: 0;
left: 0;
width: 100vw;
height: 100vh;
z-index: 10000;
background-color: #fff;
display: flex;
align-items: center;
justify-content: center;
}
.welcomeScreen{
animation: fadeOut 0.9s forwards;
animation-delay: 3s;
}
.innerWelcomeScreen{
display: flex;
flex-direction: column;
}
.textWelcomeScreen{
text-align: center;
}
.textWelcomeScreen.text span {
display: inline-block;
opacity: 0;
transform: translateY(20px);
animation: rise 0.5s forwards;
font-size: 60px;
font-weight: 100;
color: #8044A6;
}
.textWelcomeScreen.title span {
display: inline-block;
opacity: 0;
transform: translateY(20px);
animation: fall 0.9s forwards;
font-size: 120px;
}
@keyframes rise {
0% {
opacity: 0;
transform: translateY(20px);
}
100% {
opacity: 1;
transform: translateY(0);
}
}
@keyframes fadeOut {
0% {
opacity: 1;
}
99% {
opacity: 0;
}
100% {
display: none;
}
}
@keyframes fall {
0% {
opacity: 0;
transform: translateY(-20px);
}
100% {
opacity: 1;
transform: translateY(0);
}
}

BIN
www/intern/img/icon.png Normal file

Binary file not shown.

After

Width:  |  Height:  |  Size: 53 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 155 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 127 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 399 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 11 KiB

View File

@@ -0,0 +1,5 @@
Alle Bilder für Intern müssen nach folgendem Schema benennt werden:
"Bg" + $typ ".webp"
für $typ gilt: _ sowie ucfirst

Binary file not shown.

After

Width:  |  Height:  |  Size: 53 KiB

1
www/intern/img/readme.md Normal file
View File

@@ -0,0 +1 @@
Die Intern Seiten suchen das Icon in diesem Order mit dem Namen icon.png

View File

@@ -0,0 +1,97 @@
function getCookie(cname) {
let name = cname + "=";
let decodedCookie = decodeURIComponent(document.cookie);
let ca = decodedCookie.split(';');
for (let i = 0; i < ca.length; i++) {
let c = ca[i];
while (c.charAt(0) == ' ') {
c = c.substring(1);
}
if (c.indexOf(name) == 0) {
return true;
}
}
return false;
}
function displayCookieBanner(link) {
const div = document.createElement('div');
const h4 = document.createElement('h4');
const p = document.createElement('p');
const buttonJa = document.createElement('button');
const buttonNein = document.createElement('button');
div.classList.add('cookieBanner');
h4.classList.add('cookieBanner-title');
p.classList.add('cookieBanner-text');
buttonJa.classList.add('cookieBanner-btn', 'cookieBanner-btn-primary');
buttonNein.classList.add('cookieBanner-btn', 'cookieBanner-btn-secondary');
h4.innerHTML = "Cookie Hinweis";
p.innerHTML = "Die Seite, zu welcher dieser Link führt, nutzt einen technisch notwendigen Cookie. Es werden keine Cookies von Drittanbietern verwendet.";
div.append(h4, p);
const buttonsDiv = document.createElement('div');
buttonsDiv.classList.add('cookieBanner-buttons');
buttonJa.innerHTML = "Fortfahren";
buttonNein.innerHTML = "Abbrechen";
buttonJa.addEventListener('click', (el) => {
window.location.assign(link);
});
buttonNein.addEventListener('click', (el) => {
deleteCookieBanner();
});
buttonsDiv.append(buttonNein, buttonJa);
div.append(buttonsDiv);
$('body').append(div);
setTimeout(() => {
div.classList.add('show');
}, 10);
}
function deleteCookieBanner() {
const $div = $('.cookieBanner');
if ($div.length === 0) { return; }
$div.removeClass('show');
setTimeout(() => {
$div.remove();
}, 400);
}
/* function hasSessionCookie(callback) {
$.ajax({
url: '/myjupa/api/check-php-session.php',
method: 'GET',
cache: false, // Ensure we don't get a cached result
success: function(response) {
callback(response.cookieExists);
},
error: function() {
callback(false);
}
});
}
// Usage in your click handler
$(document).on('click', 'a[href*="/myjupa/"]', function (el) {
el.preventDefault();
const target = $(this).attr("href");
hasSessionCookie(function(exists) {
if (exists) {
window.location.assign(target);
} else {
deleteCookieBanner();
displayCookieBanner(target);
}
});
}); */

View File

@@ -0,0 +1,90 @@
let lastMsgTime = 0;
let lastMsgContent = '';
const MSG_COOLDOWN = 500;
function fadeOutDiv(div) {
div.removeClass('show');
setTimeout(() => div.remove(), 1500);
}
let $msgDiv = $('.msgDiv');
jQuery(document).ready(function ($) {
if ($msgDiv.length > 1) {
$msgDiv.not(':first').remove();
$msgDiv = $msgDiv.first();
}
if ($msgDiv.length === 0) {
$msgDiv = $('<div class="msgDiv"></div>');
$('body').append($msgDiv);
}
});
function displayMsg(type, msg) {
const now = Date.now();
if ($msgDiv.length === 0) {
$msgDiv = $('.msgDiv');
}
if (now - lastMsgTime < MSG_COOLDOWN && lastMsgContent === msg) {
return; // ignore spam
}
lastMsgTime = now;
lastMsgContent = msg;
const colors = ["rgb(255, 0, 0)", "rgb(0, 255, 0)", "#ff9d00"];
if (type !== 0 && type !== 1 && type !== 2) return;
const d = new Date();
console.group("MsgDivLog:");
console.log("Type:", type);
console.log("Nachricht:", msg);
console.log("Timestamp:", d);
console.groupEnd();
const $div = $('<div class="msgBox"></div>')
.css({ 'border-color': colors[type] })
.text(msg);
$msgDiv.append($div);
setTimeout(() => $div.addClass('show'), 50);
setTimeout(() => fadeOutDiv($div), 5000);
}
function displayConfirm(type, msg) {
return new Promise((resolve) => {
const colors = ["rgb(255, 0, 0)", "rgb(0, 255, 0)", "#ff9d00"];
if (![0, 1, 2].includes(type)) return resolve(false);
const $div = $('<div class="confirmBox"></div>')
.css({ 'border-color': colors[type] })
.text(msg);
const $buttonDiv = $('<div class="buttonConfirmDiv"></div>');
const $buttonYes = $('<button class="confirmYesButton">Ja</button>');
const $buttonNo = $('<button class="confirmNoButton">Nein</button>');
$buttonDiv.append($buttonNo, $buttonYes);
$div.append($buttonDiv);
$msgDiv.append($div);
$buttonYes.on('click', function () {
fadeOutDiv($div);
resolve(true);
});
$buttonNo.on('click', function () {
fadeOutDiv($div);
resolve(false);
});
setTimeout(() => $div.addClass('show'), 50);
});
}

View File

@@ -0,0 +1,68 @@
$(document).on('click', '.selectTrigger', function (e) {
e.stopPropagation();
$(this).closest('.customSelect').toggleClass('open');
});
$(document).on('click', '.selectOptions li', function (e) {
e.stopPropagation();
const $item = $(this);
const $container = $item.closest('.customSelect');
const val = $item.data('value');
const text = $item.text();
const $input = $container.find('.selectValue');
const $label = $container.find('.selectLabel');
const $allOptions = $container.find('.selectOptions li');
$allOptions.removeClass('selected');
$item.addClass('selected');
$input.val(val);
$label.text(text);
$label.removeClass('placeholder');
$container.removeClass('open');
});
/* ── Multi-select trigger ─────────────────── */
$(document).on('click', '.selectTriggerBulk', function (e) {
e.stopPropagation();
$(this).closest('.customSelect').toggleClass('open');
});
$(document).on('click', '.selectOptionsBulk li', function (e) {
e.stopPropagation();
const $item = $(this);
const $container = $item.closest('.customSelect');
const val = $item.data('value');
const text = $item.text();
const $label = $container.find('.selectLabel');
const $input = $container.find('.selectValue');
let inputArr = $input.val() ? JSON.parse($input.val()) : [];
let containerArr = Array.isArray($container.data('value')) ? $container.data('value') : [];
if ($item.hasClass('selected')) {
$item.removeClass('selected');
inputArr = inputArr.filter(i => i !== val);
containerArr = containerArr.filter(i => i !== text);
} else {
$item.addClass('selected');
inputArr.push(val);
containerArr.push(text);
}
$container.data('value', containerArr);
$input.val(JSON.stringify(inputArr));
$input.trigger('change');
if (containerArr.length > 0) {
$label.removeClass('placeholder').text(containerArr.join(', '));
} else {
$label.addClass('placeholder').text('Bitte auswählen…');
}
});
$(document).on('click', () => $('.customSelect').removeClass('open'));

1
www/intern/js/flatpickr/de.min.js vendored Normal file
View File

@@ -0,0 +1 @@
!function(e,n){"object"==typeof exports&&"undefined"!=typeof module?n(exports):"function"==typeof define&&define.amd?define(["exports"],n):n((e="undefined"!=typeof globalThis?globalThis:e||self).de={})}(this,function(e){"use strict";var n="undefined"!=typeof window&&void 0!==window.flatpickr?window.flatpickr:{l10ns:{}},t={weekdays:{shorthand:["So","Mo","Di","Mi","Do","Fr","Sa"],longhand:["Sonntag","Montag","Dienstag","Mittwoch","Donnerstag","Freitag","Samstag"]},months:{shorthand:["Jan","Feb","Mär","Apr","Mai","Jun","Jul","Aug","Sep","Okt","Nov","Dez"],longhand:["Januar","Februar","März","April","Mai","Juni","Juli","August","September","Oktober","November","Dezember"]},firstDayOfWeek:1,weekAbbreviation:"KW",rangeSeparator:" bis ",scrollTitle:"Zum Ändern scrollen",toggleTitle:"Zum Umschalten klicken",time_24hr:!0};n.l10ns.de=t;n=n.l10ns;e.German=t,e.default=n,Object.defineProperty(e,"__esModule",{value:!0})});

File diff suppressed because one or more lines are too long

1
www/intern/js/flatpickr/fr.min.js vendored Normal file
View File

@@ -0,0 +1 @@
!function(e,o){"object"==typeof exports&&"undefined"!=typeof module?o(exports):"function"==typeof define&&define.amd?define(["exports"],o):o((e="undefined"!=typeof globalThis?globalThis:e||self).it={})}(this,function(e){"use strict";var o="undefined"!=typeof window&&void 0!==window.flatpickr?window.flatpickr:{l10ns:{}},n={weekdays:{shorthand:["Dom","Lun","Mar","Mer","Gio","Ven","Sab"],longhand:["Domenica","Lunedì","Martedì","Mercoledì","Giovedì","Venerdì","Sabato"]},months:{shorthand:["Gen","Feb","Mar","Apr","Mag","Giu","Lug","Ago","Set","Ott","Nov","Dic"],longhand:["Gennaio","Febbraio","Marzo","Aprile","Maggio","Giugno","Luglio","Agosto","Settembre","Ottobre","Novembre","Dicembre"]},firstDayOfWeek:1,ordinal:function(){return"°"},rangeSeparator:" al ",weekAbbreviation:"Se",scrollTitle:"Scrolla per aumentare",toggleTitle:"Clicca per cambiare",time_24hr:!0};o.l10ns.it=n;o=o.l10ns;e.Italian=n,e.default=o,Object.defineProperty(e,"__esModule",{value:!0})});

1
www/intern/js/flatpickr/it.min.js vendored Normal file
View File

@@ -0,0 +1 @@
!function(e,n){"object"==typeof exports&&"undefined"!=typeof module?n(exports):"function"==typeof define&&define.amd?define(["exports"],n):n((e="undefined"!=typeof globalThis?globalThis:e||self).de={})}(this,function(e){"use strict";var n="undefined"!=typeof window&&void 0!==window.flatpickr?window.flatpickr:{l10ns:{}},t={weekdays:{shorthand:["So","Mo","Di","Mi","Do","Fr","Sa"],longhand:["Sonntag","Montag","Dienstag","Mittwoch","Donnerstag","Freitag","Samstag"]},months:{shorthand:["Jan","Feb","Mär","Apr","Mai","Jun","Jul","Aug","Sep","Okt","Nov","Dez"],longhand:["Januar","Februar","März","April","Mai","Juni","Juli","August","September","Oktober","November","Dezember"]},firstDayOfWeek:1,weekAbbreviation:"KW",rangeSeparator:" bis ",scrollTitle:"Zum Ändern scrollen",toggleTitle:"Zum Umschalten klicken",time_24hr:!0};n.l10ns.de=t;n=n.l10ns;e.German=t,e.default=n,Object.defineProperty(e,"__esModule",{value:!0})});

24
www/intern/js/gallery.js Normal file
View File

@@ -0,0 +1,24 @@
jQuery(document).ready(function ($) {
$('.justified').justifiedGallery({
rowHeight: 250,
margins: 5,
lastRow: 'center',
captions: false
}).on('jg.complete', function () {
$('.justified').css('opacity', 1);
const leftArrowSVGString = '<svg aria-hidden="true" class="pswp__icn" viewBox="0 0 100 125" width="100" height="125"><path d="M5,50L50,5l3,3L11,50l42,42l-3,3L5,50z M92,95l3-3L53,50L95,8l-3-3L47,50L92,95z"/></svg>';
const lightbox = new PhotoSwipeLightbox({
arrowPrevSVG: leftArrowSVGString,
arrowNextSVG: leftArrowSVGString,
gallery: '.imgGallery',
children: 'a.imgLink',
pswpModule: PhotoSwipe,
captionContent: (slide) => {
return slide.data.element.dataset.pswpCaption || '';
}
});
lightbox.init();
});
});

52
www/intern/js/header.js Normal file
View File

@@ -0,0 +1,52 @@
$(document).ready(function () {
$('.menuLinksDiv>div').hover(function () {
const $this = $(this);
clearTimeout($this.data('hoverTimeout'));
$this.find('.dropdown').stop(true, false).slideDown(200);
$this.addClass('open');
}, function () {
const $this = $(this);
const timeout = setTimeout(function () {
$this.find('.dropdown').stop(true, false).slideUp(200);
$this.removeClass('open');
}, 200); // Small delay to prevent flickering
$this.data('hoverTimeout', timeout);
});
$('.sidebar>div').on('click', function (e) {
if ($(e.target).closest('.dropdown').length) {
return;
}
if (!$(this).hasClass('open')) {
$('.sidebar>div.open').removeClass('open').find('.dropdown').slideUp();
$(this).addClass('open');
$(this).find('.dropdown').slideDown();
} else {
$(this).find('.dropdown').slideUp();
$(this).removeClass('open');
}
});
$(document).on('click', function (e) {
// If sidebar is not active, do nothing
if ($(e.target).closest('.burgerMenuDiv').length) {
$('.burgerMenuDiv').toggleClass('active');
$('.sidebar').toggleClass('active');
return;
}
if (!$('.sidebar').hasClass('active')) {
return;
}
// If click is inside the sidebar or burger menu, do nothing
if (
$(e.target).closest('.sidebar').length ||
$(e.target).closest('.burgerMenuDiv').length
) {
return;
}
// Otherwise, close the sidebar
$('.sidebar').removeClass('active');
$('.burgerMenuDiv').removeClass('active');
});
});

11
www/intern/js/img.js Normal file
View File

@@ -0,0 +1,11 @@
jQuery(document).ready(function($) {
const lightbox = new PhotoSwipeLightbox({
gallery: '.imgGallery',
children: 'a.imgLink',
pswpModule: PhotoSwipe,
captionContent: (slide) => {
return slide.data.element.dataset.pswpCaption || '';
}
});
lightbox.init();
});

File diff suppressed because one or more lines are too long

6
www/intern/js/jquery/jquery-ui.min.js vendored Normal file

File diff suppressed because one or more lines are too long

View File

@@ -0,0 +1,12 @@
/*!
* jQuery UI Touch Punch 0.2.3
*
* Copyright 20112014, Dave Furfero
* Dual licensed under the MIT or GPL Version 2 licenses.
*
* Depends:
* jquery.ui.widget.js
* jquery.ui.mouse.js
*/
!function (a) { function f(a, b) { if (!(a.originalEvent.touches.length > 1)) { a.preventDefault(); var c = a.originalEvent.changedTouches[0], d = document.createEvent("MouseEvents"); d.initMouseEvent(b, !0, !0, window, 1, c.screenX, c.screenY, c.clientX, c.clientY, !1, !1, !1, !1, 0, null), a.target.dispatchEvent(d) } } if (a.support.touch = "ontouchend" in document, a.support.touch) { var e, b = a.ui.mouse.prototype, c = b._mouseInit, d = b._mouseDestroy; b._touchStart = function (a) { var b = this; !e && b._mouseCapture(a.originalEvent.changedTouches[0]) && (e = !0, b._touchMoved = !1, f(a, "mouseover"), f(a, "mousemove"), f(a, "mousedown")) }, b._touchMove = function (a) { e && (this._touchMoved = !0, f(a, "mousemove")) }, b._touchEnd = function (a) { e && (f(a, "mouseup"), f(a, "mouseout"), this._touchMoved || f(a, "click"), e = !1) }, b._mouseInit = function () { var b = this; b.element.bind({ touchstart: a.proxy(b, "_touchStart"), touchmove: a.proxy(b, "_touchMove"), touchend: a.proxy(b, "_touchEnd") }), c.call(b) }, b._mouseDestroy = function () { var b = this; b.element.unbind({ touchstart: a.proxy(b, "_touchStart"), touchmove: a.proxy(b, "_touchMove"), touchend: a.proxy(b, "_touchEnd") }), d.call(b) } } }(jQuery);

File diff suppressed because one or more lines are too long

File diff suppressed because one or more lines are too long

File diff suppressed because one or more lines are too long

View File

@@ -0,0 +1,14 @@
The MIT License (MIT)
---------------------
Copyright (c) 2012 davidshimjs
Permission is hereby granted, free of charge,
to any person obtaining a copy of this software and associated documentation files (the "Software"),
to deal in the Software without restriction,
including without limitation the rights to use, copy, modify, merge, publish, distribute, sublicense,
and/or sell copies of the Software, and to permit persons to whom the Software is furnished to do so,
subject to the following conditions:
The above copyright notice and this permission notice shall be included in all copies or substantial portions of the Software.
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.

View File

@@ -0,0 +1,46 @@
# QRCode.js
QRCode.js is javascript library for making QRCode. QRCode.js supports Cross-browser with HTML5 Canvas and table tag in DOM.
QRCode.js has no dependencies.
## Basic Usages
```
<div id="qrcode"></div>
<script type="text/javascript">
new QRCode(document.getElementById("qrcode"), "http://jindo.dev.naver.com/collie");
</script>
```
or with some options
```
<div id="qrcode"></div>
<script type="text/javascript">
var qrcode = new QRCode(document.getElementById("qrcode"), {
text: "http://jindo.dev.naver.com/collie",
width: 128,
height: 128,
colorDark : "#000000",
colorLight : "#ffffff",
correctLevel : QRCode.CorrectLevel.H
});
</script>
```
and you can use some methods
```
qrcode.clear(); // clear the code.
qrcode.makeCode("http://naver.com"); // make another code.
```
## Browser Compatibility
IE6~10, Chrome, Firefox, Safari, Opera, Mobile Safari, Android, Windows Mobile, ETC.
## License
MIT License
## Contact
twitter @davidshimjs
[![Bitdeli Badge](https://d2weczhvl823v0.cloudfront.net/davidshimjs/qrcodejs/trend.png)](https://bitdeli.com/free "Bitdeli Badge")

View File

@@ -0,0 +1,18 @@
{
"name": "qrcode.js",
"version": "0.0.1",
"homepage": "https://github.com/davidshimjs/qrcodejs",
"authors": [
"Sangmin Shim", "Sangmin Shim <ssm0123@gmail.com> (http://jaguarjs.com)"
],
"description": "Cross-browser QRCode generator for javascript",
"main": "qrcode.js",
"ignore": [
"bower_components",
"node_modules",
"index.html",
"index.svg",
"jquery.min.js",
"qrcode.min.js"
]
}

View File

@@ -0,0 +1,47 @@
<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN" "http://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd">
<html xmlns="http://www.w3.org/1999/xhtml" xml:lang="ko" lang="ko">
<head>
<title>Cross-Browser QRCode generator for Javascript</title>
<meta http-equiv="Content-Type" content="text/html; charset=UTF-8" />
<meta name="viewport" content="width=device-width,initial-scale=1,user-scalable=no" />
<script type="text/javascript" src="jquery.min.js"></script>
<script type="text/javascript" src="qrcode.js"></script>
</head>
<body>
<input id="text" type="text" value="http://jindo.dev.naver.com/collie" style="width:80%" />
<svg xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink">
<g id="qrcode"/>
</svg>
<script type="text/javascript">
var qrcode = new QRCode(document.getElementById("qrcode"), {
width : 100,
height : 100,
useSVG: true
});
function makeCode () {
var elText = document.getElementById("text");
if (!elText.value) {
alert("Input a text");
elText.focus();
return;
}
qrcode.makeCode(elText.value);
}
makeCode();
$("#text").
on("blur", function () {
makeCode();
}).
on("keydown", function (e) {
if (e.keyCode == 13) {
makeCode();
}
});
</script>
</body>
</html>

View File

@@ -0,0 +1,44 @@
<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN" "http://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd">
<html xmlns="http://www.w3.org/1999/xhtml" xml:lang="ko" lang="ko">
<head>
<title>Cross-Browser QRCode generator for Javascript</title>
<meta http-equiv="Content-Type" content="text/html; charset=UTF-8" />
<meta name="viewport" content="width=device-width,initial-scale=1,user-scalable=no" />
<script type="text/javascript" src="jquery.min.js"></script>
<script type="text/javascript" src="qrcode.js"></script>
</head>
<body>
<input id="text" type="text" value="http://jindo.dev.naver.com/collie" style="width:80%" /><br />
<div id="qrcode" style="width:100px; height:100px; margin-top:15px;"></div>
<script type="text/javascript">
var qrcode = new QRCode(document.getElementById("qrcode"), {
width : 100,
height : 100
});
function makeCode () {
var elText = document.getElementById("text");
if (!elText.value) {
alert("Input a text");
elText.focus();
return;
}
qrcode.makeCode(elText.value);
}
makeCode();
$("#text").
on("blur", function () {
makeCode();
}).
on("keydown", function (e) {
if (e.keyCode == 13) {
makeCode();
}
});
</script>
</body>

Some files were not shown because too many files have changed in this diff Show More