alpha-base3_pass2
This commit is contained in:
parent
c7011b706f
commit
9f4d000c39
@ -27,6 +27,9 @@ const app = {
|
||||
// Relay State
|
||||
currentParticipant: 1,
|
||||
participantNames: [],
|
||||
relayParticipantStartTime: 0,
|
||||
relayParticipantElapsed: 0,
|
||||
relayColors: ['#3b82f6', '#10b981', '#ef4444', '#f59e0b', '#8b5cf6', '#ec4899', '#06b6d4', '#f97316', '#14b8a6', '#6366f1', '#a855f7', '#d946ef'],
|
||||
|
||||
// Custom State
|
||||
customActivities: [
|
||||
@ -63,6 +66,7 @@ const app = {
|
||||
landingClock: document.getElementById('landing-clock'),
|
||||
mainTimer: document.getElementById('main-timer'),
|
||||
subTimer: document.getElementById('sub-timer'),
|
||||
relayParticipantTimer: document.getElementById('relay-participant-timer'),
|
||||
viewLanding: document.getElementById('view-landing'),
|
||||
viewTimer: document.getElementById('view-timer'),
|
||||
timerTitle: document.getElementById('timer-title'),
|
||||
@ -135,6 +139,7 @@ const app = {
|
||||
init() {
|
||||
console.log('Timer App Initializing...');
|
||||
this.initDarkMode();
|
||||
this.shuffleRelayColors();
|
||||
this.updateLandingClock();
|
||||
this.bindEvents();
|
||||
this.renderCustomBuilder();
|
||||
@ -143,6 +148,13 @@ const app = {
|
||||
this.bindKeyboardShortcuts();
|
||||
},
|
||||
|
||||
shuffleRelayColors() {
|
||||
for (let i = this.relayColors.length - 1; i > 0; i--) {
|
||||
const j = Math.floor(Math.random() * (i + 1));
|
||||
[this.relayColors[i], this.relayColors[j]] = [this.relayColors[j], this.relayColors[i]];
|
||||
}
|
||||
},
|
||||
|
||||
bindKeyboardShortcuts() {
|
||||
document.addEventListener('keydown', (e) => {
|
||||
if (this.currentView !== 'timer' || !this.currentMode) return;
|
||||
@ -155,10 +167,18 @@ const app = {
|
||||
|
||||
if (e.key === ' ' || e.code === 'Space') {
|
||||
e.preventDefault();
|
||||
if (!this.isRunning || this.isPaused) {
|
||||
this.handleStartClick();
|
||||
if (this.currentMode === 'lap') {
|
||||
if (!this.isRunning || this.isPaused) {
|
||||
this.handleStartClick();
|
||||
} else {
|
||||
this.recordLap();
|
||||
}
|
||||
} else {
|
||||
this.pauseTimer();
|
||||
if (!this.isRunning || this.isPaused) {
|
||||
this.handleStartClick();
|
||||
} else {
|
||||
this.pauseTimer();
|
||||
}
|
||||
}
|
||||
} else if (e.key === 'Escape' || e.code === 'Escape') {
|
||||
e.preventDefault();
|
||||
@ -232,7 +252,15 @@ const app = {
|
||||
}
|
||||
});
|
||||
|
||||
this.el.toggleDisplayMode.addEventListener('change', () => this.updateDisplay());
|
||||
this.el.toggleDisplayMode.addEventListener('change', () => {
|
||||
const label = this.el.displayModeContainer.querySelector('label');
|
||||
if (this.el.toggleDisplayMode.checked) {
|
||||
label.textContent = 'Activity Progress';
|
||||
} else {
|
||||
label.textContent = 'Timer Progress';
|
||||
}
|
||||
this.updateDisplay();
|
||||
});
|
||||
},
|
||||
|
||||
updateLandingClock() {
|
||||
@ -286,6 +314,10 @@ const app = {
|
||||
this.el.savedTimersContainer.classList.remove('d-none');
|
||||
this.el.relayConfig.classList.add('d-none');
|
||||
this.el.displayModeContainer.classList.remove('d-none');
|
||||
|
||||
// Set initial label based on toggle state
|
||||
const label = this.el.displayModeContainer.querySelector('label');
|
||||
label.textContent = this.el.toggleDisplayMode.checked ? 'Activity Progress' : 'Timer Progress';
|
||||
} else if (mode.hasRelay) {
|
||||
this.el.customBuilder.classList.add('d-none');
|
||||
this.el.relayConfig.classList.remove('d-none');
|
||||
@ -310,6 +342,7 @@ const app = {
|
||||
this.el.restAlertContainer.classList.toggle('d-none', !mode.isCustom);
|
||||
this.el.activeActivityName.classList.add('d-none');
|
||||
this.el.relayActiveParticipantContainer.classList.add('d-none');
|
||||
this.el.relayParticipantTimer.classList.add('d-none');
|
||||
|
||||
// Options Dropdown visibility logic
|
||||
this.el.optionsDropdown.classList.toggle('d-none', modeKey === 'time-watch');
|
||||
@ -367,9 +400,8 @@ const app = {
|
||||
this.el.participantCount.value = count;
|
||||
|
||||
let html = '';
|
||||
const colors = ['#3b82f6', '#10b981', '#ef4444', '#f59e0b', '#8b5cf6', '#ec4899', '#06b6d4', '#f97316', '#14b8a6', '#6366f1', '#a855f7', '#d946ef'];
|
||||
for (let i = 1; i <= count; i++) {
|
||||
const defaultColor = colors[(i - 1) % colors.length];
|
||||
const defaultColor = this.relayColors[(i - 1) % this.relayColors.length];
|
||||
html += `
|
||||
<div class="input-group input-group-sm">
|
||||
<span class="input-group-text fs-tiny">#${i}</span>
|
||||
@ -482,13 +514,23 @@ const app = {
|
||||
this.el.relayActiveParticipantContainer.classList.remove('d-none');
|
||||
this.el.relayParticipantCountBox.classList.add('d-none');
|
||||
this.updateRelayActiveDisplay();
|
||||
this.relayParticipantStartTime = now;
|
||||
this.relayParticipantElapsed = 0;
|
||||
this.el.relayParticipantTimer.classList.add('d-none');
|
||||
}
|
||||
|
||||
if (this.isPaused) {
|
||||
const offset = (isCountdownMode) ? (this.countdownStartValue - this.elapsedTime) : this.elapsedTime;
|
||||
this.startTime = now - offset;
|
||||
|
||||
if (mode.hasRelay) {
|
||||
this.relayParticipantStartTime = now - this.relayParticipantElapsed;
|
||||
}
|
||||
} else {
|
||||
this.startTime = now;
|
||||
if (mode.hasRelay) {
|
||||
this.relayParticipantStartTime = now;
|
||||
}
|
||||
}
|
||||
|
||||
this.isRunning = true;
|
||||
@ -520,6 +562,9 @@ const app = {
|
||||
|
||||
pauseTimer() {
|
||||
if (!this.isRunning || this.isPaused) return;
|
||||
|
||||
const mode = this.modes[this.currentMode];
|
||||
if (mode && !mode.allowPause) return;
|
||||
|
||||
this.isPaused = true;
|
||||
this.pausedTime = this.elapsedTime;
|
||||
@ -551,6 +596,7 @@ const app = {
|
||||
this.el.btnReset.disabled = false;
|
||||
this.el.mainTimer.classList.remove('timer-alert');
|
||||
this.el.relayActiveParticipantContainer.classList.add('d-none');
|
||||
this.el.relayParticipantTimer.classList.add('d-none');
|
||||
|
||||
if (this.currentMode === 'countdown') {
|
||||
this.el.countdownInputs.classList.remove('d-none');
|
||||
@ -584,6 +630,8 @@ const app = {
|
||||
this.currentParticipant = 1;
|
||||
this.currentActivityIndex = 0;
|
||||
this.lastPlayedSecond = -1;
|
||||
this.relayParticipantStartTime = 0;
|
||||
this.relayParticipantElapsed = 0;
|
||||
|
||||
this.el.listBody.innerHTML = '';
|
||||
this.el.mainTimer.classList.remove('timer-finish');
|
||||
@ -598,6 +646,7 @@ const app = {
|
||||
this.el.btnRelaySplit.disabled = false;
|
||||
this.el.activeActivityName.classList.add('d-none');
|
||||
this.el.relayActiveParticipantContainer.classList.add('d-none');
|
||||
this.el.relayParticipantTimer.classList.add('d-none');
|
||||
this.el.relayParticipantCountBox.classList.remove('d-none');
|
||||
this.el.sessionTitle.disabled = false;
|
||||
|
||||
@ -697,6 +746,10 @@ const app = {
|
||||
} else {
|
||||
// Standard count up
|
||||
this.elapsedTime = now - this.startTime;
|
||||
|
||||
if (mode.hasRelay) {
|
||||
this.relayParticipantElapsed = now - this.relayParticipantStartTime;
|
||||
}
|
||||
}
|
||||
|
||||
this.updateDisplay();
|
||||
@ -782,6 +835,10 @@ const app = {
|
||||
this.el.mainTimer.textContent = this.formatTime(ms, format);
|
||||
}
|
||||
this.el.subTimer.classList.add('d-none');
|
||||
|
||||
if (this.currentMode === 'relay' && !this.el.relayParticipantTimer.classList.contains('d-none')) {
|
||||
this.el.relayParticipantTimer.textContent = this.formatTime(this.relayParticipantElapsed, 'hh:mm:ss.ms');
|
||||
}
|
||||
},
|
||||
|
||||
getTotalProgress() {
|
||||
@ -854,6 +911,7 @@ const app = {
|
||||
const maxParticipants = parseInt(this.el.participantCount.value) || 1;
|
||||
if (this.currentParticipant > maxParticipants) {
|
||||
this.el.relayActiveParticipantContainer.classList.add('d-none');
|
||||
this.el.relayParticipantTimer.classList.add('d-none');
|
||||
return;
|
||||
}
|
||||
|
||||
@ -882,6 +940,11 @@ const app = {
|
||||
const colorInput = document.querySelector(`.participant-color-input[data-index="${this.currentParticipant}"]`);
|
||||
const color = colorInput ? colorInput.value : '#3b82f6';
|
||||
|
||||
// Show secondary timer after first split
|
||||
if (this.history.length >= 0) {
|
||||
this.el.relayParticipantTimer.classList.remove('d-none');
|
||||
}
|
||||
|
||||
// If it's the last participant, mark as final but keep their name
|
||||
if (this.currentParticipant === maxParticipants) {
|
||||
isFinal = true;
|
||||
@ -901,6 +964,8 @@ const app = {
|
||||
if (!isFinal) {
|
||||
this.currentParticipant++;
|
||||
this.updateRelayActiveDisplay();
|
||||
this.relayParticipantStartTime = performance.now();
|
||||
this.relayParticipantElapsed = 0;
|
||||
} else {
|
||||
this.stopTimer();
|
||||
this.el.btnRelaySplit.disabled = true;
|
||||
@ -1283,4 +1348,4 @@ const app = {
|
||||
};
|
||||
|
||||
// Start the app
|
||||
document.addEventListener('DOMContentLoaded', () => app.init());
|
||||
document.addEventListener('DOMContentLoaded', () => app.init());
|
||||
|
||||
@ -293,13 +293,14 @@ $projectImage = $_SERVER['PROJECT_IMAGE_URL'] ?? '';
|
||||
</div>
|
||||
|
||||
<div class="timer-display font-tabular mb-2" id="main-timer">00:00:00</div>
|
||||
<div class="timer-relay-participant font-tabular mb-4 d-none" id="relay-participant-timer" style="font-size: 2.5rem; opacity: 0.8;">00:00:00.00</div>
|
||||
<div class="timer-sub-display font-tabular mb-4 d-none" id="sub-timer">00:00:00</div>
|
||||
|
||||
<!-- Controls -->
|
||||
<!-- Toggle Display Mode -->
|
||||
<div id="display-mode-container" class="form-check form-switch d-flex justify-content-center mb-3 d-none">
|
||||
<input class="form-check-input me-2" type="checkbox" id="toggle-display-mode">
|
||||
<label class="form-check-label small text-muted text-uppercase tracking-wider" for="toggle-display-mode">Show Total Progress</label>
|
||||
<label class="form-check-label small text-muted text-uppercase tracking-wider" for="toggle-display-mode">Activity Progress</label>
|
||||
</div>
|
||||
<div class="d-flex justify-content-center flex-wrap gap-2 mb-5">
|
||||
<button id="btn-start" class="btn btn-primary btn-precise px-4">Start</button>
|
||||
|
||||
Loading…
x
Reference in New Issue
Block a user