Version 2.1: Klicker-Fix für Agenda + Sprechernotizen im Steuerpult
Präsentations-Klicker funktioniert jetzt durchgängig über die gesamte Agenda-Sequenz, auch wenn der Tastatur-Fokus auf dem Display-Fenster statt dem Steuerpult liegt (ArrowRight/Leertaste), plus ein dezenter Klick-Button unten rechts im Display für Klicker mit Mausklick-Signal. Zusätzlich: manuell gepflegte Sprechernotizen pro Agenda-Punkt, die ausschließlich im Steuerpult angezeigt werden, nie im Display/Beamer.
This commit is contained in:
@@ -341,6 +341,8 @@
|
||||
<input type="text" id="ai-embed-url" placeholder="https://show.zoho.eu/publish/...">
|
||||
<p style="font-size:0.78rem;color:var(--muted);margin-top:4px;">In Zoho Show: Datei → Freigeben/Veröffentlichen → Einbetten, Link hier einfügen.</p>
|
||||
</div>
|
||||
<label>Notizen — nur im Steuerpult sichtbar, nie auf dem Display</label>
|
||||
<textarea id="ai-notes" rows="4" placeholder="z.B. Stichpunkte, was hier gesagt werden soll"></textarea>
|
||||
<div class="modal-footer">
|
||||
<button class="btn btn-danger btn-sm" id="ai-delete-btn" onclick="deleteAgendaItem()" style="display:none;margin-right:auto;">Löschen</button>
|
||||
<button class="btn btn-ghost" onclick="closeAdminModal('modal-agenda-item')">Abbrechen</button>
|
||||
@@ -887,6 +889,7 @@ function openAddAgendaItem() {
|
||||
document.getElementById('ai-label').value = '';
|
||||
document.getElementById('ai-type').value = 'image';
|
||||
document.getElementById('ai-embed-url').value = '';
|
||||
document.getElementById('ai-notes').value = '';
|
||||
document.getElementById('ai-delete-btn').style.display = 'none';
|
||||
_agendaImageDataUrl = null; _agendaImageChanged = false;
|
||||
document.getElementById('ai-image-thumb').style.display = 'none';
|
||||
@@ -904,6 +907,7 @@ function editAgendaItem(id) {
|
||||
document.getElementById('ai-label').value = it.label || '';
|
||||
document.getElementById('ai-type').value = it.type || 'image';
|
||||
document.getElementById('ai-embed-url').value = it.embedUrl || '';
|
||||
document.getElementById('ai-notes').value = it.notes || '';
|
||||
document.getElementById('ai-delete-btn').style.display = 'inline-flex';
|
||||
_agendaImageDataUrl = null; _agendaImageChanged = false;
|
||||
const thumb = document.getElementById('ai-image-thumb');
|
||||
@@ -992,7 +996,9 @@ async function saveAgendaItem() {
|
||||
id = candidate;
|
||||
}
|
||||
const existing = state.agendaCatalog.find(a => a.id === id) || {};
|
||||
const notes = document.getElementById('ai-notes').value.trim();
|
||||
const item = { id, label, type };
|
||||
if (notes) item.notes = notes;
|
||||
|
||||
if (type === 'embed') {
|
||||
const url = document.getElementById('ai-embed-url').value.trim();
|
||||
|
||||
@@ -832,6 +832,19 @@
|
||||
<p style="font-size:0.88rem;color:var(--muted);">Der rote „Weiter"-Button oben führt automatisch zum jeweils nächsten Punkt in der festgelegten Reihenfolge — egal ob als Nächstes eine Folie, die Mitglieder-Vorstellungsrunde oder die Besucherrunde kommt. Bei einer Live-Einbettung kann „Weiter" nicht innerhalb der eingebetteten Folie selbst blättern (das bleibt Sache von Zoho Show), sondern springt direkt zum nächsten Agenda-Punkt.</p>
|
||||
</div>
|
||||
|
||||
<div class="info">
|
||||
<strong>Mit Präsentations-Klicker durchklicken:</strong> Pfeiltaste rechts (→) oder Leertaste lösen „Weiter" aus — das funktioniert jetzt sowohl im Steuerpult- als auch im Display-Fenster, je nachdem, welches Fenster gerade den Tastatur-Fokus hat. Zusätzlich gibt es unten rechts im Display-Fenster einen unsichtbaren Klick-Button (erscheint bei Hover), falls der Klicker statt einer Taste einen Mausklick sendet.
|
||||
</div>
|
||||
|
||||
<div class="tip">
|
||||
<strong>Grenze bei mehrseitigen Einbettungen:</strong> Sobald mit dem Klicker in eine eingebettete Folie mit mehreren internen Seiten hineingeklickt wird, um dort zu blättern, übernimmt Zoho Show den Tastatur-Fokus vollständig — von dort aus kann der Klicker nicht mehr automatisch zum nächsten Agenda-Punkt springen. Am Ende einer solchen Datei einmal bewusst „Weiter" im Steuerpult klicken oder den Klick-Button im Display nutzen. Am zuverlässigsten bleibt weiterhin: ein Zoho-Show-File pro Agenda-Punkt.
|
||||
</div>
|
||||
|
||||
<div class="card">
|
||||
<p style="font-weight:700;font-size:0.9rem;margin-bottom:10px;">Sprechernotizen (nur im Steuerpult sichtbar)</p>
|
||||
<p style="font-size:0.88rem;color:var(--muted);">Wie bei PowerPoint lässt sich pro Agenda-Punkt ein Notiz-Text hinterlegen (Admin-Panel → Agenda-Punkt bearbeiten → Feld „Notizen"). Ist ein Punkt mit Notizen live geschaltet, erscheint direkt unter der Kopfzeile im Steuerpult ein gelber Hinweiskasten mit dem Text — unabhängig davon, welcher Reiter (Agenda/Mitglieder/Besucher) gerade offen ist. Im Display-/Beamer-Fenster erscheinen diese Notizen zu keinem Zeitpunkt, das sieht nur die Person am Steuerpult.</p>
|
||||
</div>
|
||||
|
||||
<div class="mockup">
|
||||
<div class="mockup-bar">
|
||||
<div class="mockup-dot" style="background:#ff5f57;"></div>
|
||||
|
||||
96
index.html
96
index.html
@@ -730,6 +730,27 @@
|
||||
}
|
||||
.absent-section-title + .absent-section-title { margin-top: 10px; }
|
||||
|
||||
/* Notizen-Leiste im Steuerpult: warmer Hinweis-Kasten für Sprecher-Notizen des aktuell
|
||||
live geschalteten Agenda-Punkts. Nur im Steuerpult, nie im Display gerendert. */
|
||||
.agenda-notes-panel {
|
||||
padding: 10px 24px;
|
||||
background: #fef3c7;
|
||||
border-bottom: 1px solid #fde68a;
|
||||
color: #78350f;
|
||||
font-size: 0.88rem;
|
||||
line-height: 1.4;
|
||||
white-space: pre-wrap;
|
||||
}
|
||||
.agenda-notes-panel strong {
|
||||
display: block;
|
||||
font-size: 0.7rem;
|
||||
font-weight: 700;
|
||||
text-transform: uppercase;
|
||||
letter-spacing: 1px;
|
||||
color: #92400e;
|
||||
margin-bottom: 4px;
|
||||
}
|
||||
|
||||
/* Display: Absent summary overlay */
|
||||
#display-absent-summary {
|
||||
position: fixed; inset: 0; z-index: 5;
|
||||
@@ -1310,6 +1331,17 @@
|
||||
<iframe id="agenda-item-embed" src="" title="Agenda" allow="fullscreen" style="display:none;width:100%;height:100%;border:0;"></iframe>
|
||||
<div id="agenda-item-error" style="display:none;color:rgba(255,255,255,0.6);font-size:1.3rem;text-align:center;padding:40px;">⚠ Bild nicht gefunden – bitte im Admin-Panel neu hochladen.</div>
|
||||
</div>
|
||||
<!-- Klicker-Ersatz: unauffälliger Klick-Button zum Weiterschalten direkt vom Display aus,
|
||||
für Klicker, die einen Mausklick statt eines Tastendrucks senden, oder falls der
|
||||
Tastatur-Fokus in eine eingebettete Folie gerutscht ist. Bewusst nur in der Ecke,
|
||||
unsichtbar bis Hover/Fokus, damit die Zuschauer-Ansicht nicht gestört wird. -->
|
||||
<button id="display-advance-btn" onclick="displayAdvanceClick()" title="Weiter"
|
||||
style="position:fixed;right:0;bottom:0;z-index:30;width:64px;height:64px;border:none;
|
||||
background:rgba(0,0,0,0.35);color:rgba(255,255,255,0.35);font-size:1.6rem;
|
||||
line-height:1;cursor:pointer;border-top-left-radius:14px;opacity:0;
|
||||
transition:opacity 0.15s ease, color 0.15s ease, background 0.15s ease;"
|
||||
onmouseover="this.style.opacity='1';this.style.background='rgba(0,0,0,0.55)';this.style.color='#fff';"
|
||||
onmouseout="this.style.opacity='0';this.style.background='rgba(0,0,0,0.35)';this.style.color='rgba(255,255,255,0.35)';">▶</button>
|
||||
<!-- Startbild: außerhalb der Karte, damit es unabhängig angezeigt werden kann -->
|
||||
<div id="display-empty" style="position:fixed;inset:0;display:flex;align-items:center;justify-content:center;z-index:10;">
|
||||
<img id="display-logo-empty" src="logo.jpeg" alt="BNI" style="width:min(520px,72vw);height:auto;border-radius:24px;box-shadow:0 8px 60px rgba(0,0,0,0.5);">
|
||||
@@ -1397,6 +1429,11 @@
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<!-- Notizen-Leiste: Sprecher-Notizen des aktuell live geschalteten Agenda-Punkts, unabhängig
|
||||
vom gerade aktiven Reiter (Agenda/Mitglieder/Besucher) links. Wird von renderControl()
|
||||
über renderAgendaNotesPanel() befüllt/versteckt — NUR im Steuerpult, nie im Display-View. -->
|
||||
<div id="agenda-notes-panel" style="display:none;"></div>
|
||||
|
||||
<!-- Body -->
|
||||
<div class="ctrl-body">
|
||||
|
||||
@@ -1906,7 +1943,7 @@
|
||||
// ============================================================
|
||||
// CONSTANTS & CHAPTER CONFIG
|
||||
// ============================================================
|
||||
const APP_VERSION = '2.0';
|
||||
const APP_VERSION = '2.1';
|
||||
const GITEA_RAW = 'http://72.60.134.73:3000/api/v1/repos/cheubaum/BNI-Vorstellungsrunde/raw';
|
||||
const GITEA_API = 'http://72.60.134.73:3000/api/v1/repos/cheubaum/BNI-Vorstellungsrunde';
|
||||
function giteaUrl(path) { return `${GITEA_RAW}/${path}?ref=main`; }
|
||||
@@ -1956,7 +1993,8 @@ function defaultState() {
|
||||
memberTimers: {}, // { memberId: customSeconds }
|
||||
showTimer: true, // false = timer completely hidden
|
||||
coordinatorReportData: null,
|
||||
agendaCatalog: [], // { id, label, type: 'image'|'embed', imagePath?, embedUrl? } — geladen aus chapters/<code>/agenda.json
|
||||
agendaCatalog: [], // { id, label, type: 'image'|'embed', imagePath?, embedUrl?, notes? } — geladen aus chapters/<code>/agenda.json
|
||||
// notes: optionaler Freitext, nur im Steuerpult sichtbar (nie im Display/Beamer-View)
|
||||
agendaOrder: [], // Reihenfolge von IDs (Katalog-Punkte + eingebaute Vorstellungsrunden), aktiv für dieses Meeting (wie meetingOrder)
|
||||
agendaKnownIds: [], // IDs, die schon einmal automatisch in agendaOrder eingefügt wurden (verhindert, dass bewusst ausgeblendete Punkte zurückkehren)
|
||||
currentAgendaItemId: null,
|
||||
@@ -2945,10 +2983,32 @@ function renderControl() {
|
||||
renderInvitedBySelect();
|
||||
renderAdminPanel();
|
||||
renderStammvertreterSection();
|
||||
renderAgendaNotesPanel();
|
||||
updateNextButton();
|
||||
syncDot = document.getElementById('sync-dot');
|
||||
}
|
||||
|
||||
// Zeigt die Sprecher-Notizen des aktuell live geschalteten Agenda-Punkts im Steuerpult an —
|
||||
// unabhängig vom gerade gewählten linken Reiter (Agenda/Mitglieder/Besucher), damit die
|
||||
// Moderatorin die Notizen auch sieht, während sie z.B. die Mitglieder-Queue pflegt. Bewusst aus
|
||||
// renderControl() heraus aufgerufen (nicht nur aus showAgendaItem/closeAgendaItem), damit der
|
||||
// Zustand bei jeder State-Synchronisierung korrekt bleibt. renderDisplay() kennt dieses Element
|
||||
// nicht — Notizen erscheinen dadurch garantiert nie auf dem Display/Beamer.
|
||||
function renderAgendaNotesPanel() {
|
||||
const panel = document.getElementById('agenda-notes-panel');
|
||||
if (!panel) return;
|
||||
const it = state.mode === 'agenda-item' ? getAgendaItem(state.currentAgendaItemId) : null;
|
||||
const notes = it && it.notes ? it.notes.trim() : '';
|
||||
if (!notes) {
|
||||
panel.style.display = 'none';
|
||||
panel.innerHTML = '';
|
||||
return;
|
||||
}
|
||||
panel.className = 'agenda-notes-panel';
|
||||
panel.style.display = 'block';
|
||||
panel.innerHTML = `<strong>Notiz — ${escHtml(it.label || it.id)}</strong>${escHtml(notes)}`;
|
||||
}
|
||||
|
||||
function renderInvitedBySelect() {
|
||||
const sel = document.getElementById('v-invited-by');
|
||||
if (!sel) return;
|
||||
@@ -3666,6 +3726,25 @@ function goNext() {
|
||||
renderDisplay();
|
||||
}
|
||||
|
||||
// Klick-Ersatz für die Display-Seite (siehe #display-advance-btn): delegiert 1:1 an dieselbe
|
||||
// Weiter-Logik/Disabled-Prüfung wie der "Weiter"-Button im Steuerpult, keine zweite Zustandsquelle.
|
||||
// Ob "Weiter" gerade sinnvoll etwas tut. Bewusst auf `state` statt auf dem DOM-Element
|
||||
// #btn-next geprüft: #btn-next existiert zwar in beiden Fenstern (Steuerpult + Display sind
|
||||
// dasselbe Dokument), aber sein disabled-Attribut wird nur von updateNextButton() gepflegt,
|
||||
// und das läuft laut renderCurrentView() ausschließlich im Steuerpult-Kontext — im
|
||||
// Display-Fenster bliebe #btn-next.disabled sonst dauerhaft auf dem statischen HTML-Anfangswert
|
||||
// stehen. Einziger echter "nichts zu tun"-Fall (siehe updateNextButton() ~Zeile 3599): Meeting
|
||||
// noch nicht gestartet und keine Mitglieder in der Warteschlange.
|
||||
function canAdvance() {
|
||||
const hasStarted = state.currentIndex >= 0 || state.mode === 'visitors' || state.mode !== 'members';
|
||||
if (hasStarted) return true;
|
||||
return state.meetingOrder.length > 0;
|
||||
}
|
||||
|
||||
function displayAdvanceClick() {
|
||||
if (canAdvance()) goNext();
|
||||
}
|
||||
|
||||
function resetMeeting() {
|
||||
if (!confirm('Vorstellungsrunde neu starten? Der Fortschritt wird zurückgesetzt.')) return;
|
||||
stopTimer();
|
||||
@@ -4082,13 +4161,20 @@ function uid() {
|
||||
// KEYBOARD SHORTCUTS
|
||||
// ============================================================
|
||||
document.addEventListener('keydown', (e) => {
|
||||
if (getView() !== 'control') return;
|
||||
// Bewusst NICHT mehr auf getView()==='control' beschränkt: ein Präsentations-Klicker kann
|
||||
// ArrowRight/Space senden, während der OS-Fokus auf dem Display-(Beamer)-Fenster liegt statt
|
||||
// auf dem Steuerpult. #btn-next existiert als reales DOM-Element unabhängig davon, welche
|
||||
// View gerade sichtbar ist. Funktioniert weiterhin nur, solange der Fokus auf unserer eigenen
|
||||
// Seite liegt — sobald in eine eingebettete Zoho-Show-Folie geklickt wurde, verschluckt deren
|
||||
// eigenes (fremdes) Dokument die Tastendrücke; das lässt sich aus Sicherheitsgründen
|
||||
// (Cross-Origin-iframe) von hier aus nicht abfangen.
|
||||
if (e.target.tagName === 'INPUT' || e.target.tagName === 'TEXTAREA') return;
|
||||
|
||||
if (e.key === 'ArrowRight' || e.key === ' ') {
|
||||
e.preventDefault();
|
||||
const btn = document.getElementById('btn-next');
|
||||
if (btn && !btn.disabled) goNext();
|
||||
// canAdvance() statt #btn-next.disabled: dessen disabled-Attribut wird nur im
|
||||
// Steuerpult-Kontext von updateNextButton() gepflegt (siehe canAdvance()-Kommentar).
|
||||
if (canAdvance()) goNext();
|
||||
}
|
||||
});
|
||||
|
||||
|
||||
@@ -1,4 +1,4 @@
|
||||
{
|
||||
"version": "2.0",
|
||||
"notes": "Agenda-Folien für Online-Meetings (Hybrid-Chapter): Bild- oder Live-Einbettungs-Folien frei in die Reihenfolge einsortieren, inkl. Mitglieder-/Besucher-Vorstellungsrunde und neuer Marketing-/Ergebnisrunde (ohne Timer). \"Weiter\" folgt jetzt der Agenda."
|
||||
"version": "2.1",
|
||||
"notes": "Agenda-Folien: Präsentations-Klicker funktioniert jetzt auch dann weiter, wenn der Fokus auf dem Display-(Beamer)-Fenster liegt statt im Steuerpult (Pfeiltaste rechts/Leertaste), zusätzlich ein dezenter Klick-Button unten rechts im Display. Außerdem: Sprechernotizen pro Agenda-Punkt, die nur im Steuerpult sichtbar sind, nie auf dem Display/Beamer."
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user