
Som robil svoju prvú vlastnú webovú aplikáciu určenú, pre odpočet dní a hodín do ďalších Vianoc. Áno, inšpirovala vianočná nálada mojej ženy.
Vymyslel som si zadanie:
- Nastaviť 5 pozadí, ktoré sa budú meniť po 10 minútach
- V pozadí bude hrať vianočná hudba – (Viac playlistov)
- Bude tam možnosť si zvoliť časové pásmo
- Zvoliť si prepočet na dni a hodiny
- Bude možné hudbu zastaviť, stíšiť, znovu spustiť
- Tlačidlo bude buď zelené -(Hudba hrá)
- Tlačidlo bude červené – (hudba nehrá)
- Vyvorenei favicon
Vytvoril som priečinok
mdkir christmas-countdown
Do priečinka som vytvoril textové súbory
- Dockerfile
- docker-compose.yaml
- index.html
- script.js
- style.css
- citaj
A zložky, do ktorých som vložil obrázky a hudbu
- jpg som pomenoval: christmas1.jpg, christmas2.jpg, christmas3.jpg, christmas4.jpg, christmas5.jpg
- mp3 som urobil niekoľko hodinový súbor a pomenoval christmas01.mp3.
- favicon uložil som favicon.png
Ďalej do vytvorených súborov som napísal kódy prostredníctvom buď vim, alebo nano:
Dockerfile
FROM nginx:alpine
# Skopíruj všetky súbory do Nginxu
COPY . /usr/share/nginx/html/
# Tento riadok zabezpečí, že Nginx bude posielať správne hlavičky pre JS
RUN sed -i '/types {/a \ application/javascript js;' /etc/nginx/nginx.conf
docker-compose.yaml
services:
web:
image: nginx:alpine
ports:
- "3010:80" # port Vianoce
volumes:
- /home/ivan/christmas-countdown:/usr/share/nginx/html:ro
restart: always
script.js
document.addEventListener('DOMContentLoaded', () => {
console.log("Vianočný web: Plná verzia so všetkými funkciami.");
// --- ELEMENTY ---
const timerDisplay = document.getElementById('timer');
const musicBtn = document.getElementById('music-btn');
const audio = document.getElementById('bg-music');
const playlistSelect = document.getElementById('playlist-select');
const volumeSlider = document.getElementById('volume-slider');
const btnDays = document.getElementById('btn-days');
const btnHours = document.getElementById('btn-hours');
const timezoneSelect = document.getElementById('timezone-select');
// --- 1. NÁHODNÉ POZADIE ---
const backgrounds = ['jpg/christmas1.jpg', 'jpg/christmas2.jpg', 'jpg/christmas3.jpg', 'jpg/christmas4.jpg', 'jpg/christmas5.jpg'];
document.body.style.backgroundImage = `url('${backgrounds[Math.floor(Math.random() * backgrounds.length)]}')`;
// --- 2. HUDBA A PLAYLISTY ---
const updateButtonUI = () => {
if (!musicBtn) return;
if (audio.paused) {
musicBtn.innerText = "🎶 ZAPNÚŤ HUDBU";
musicBtn.style.setProperty('background-color', '#ff4d4d', 'important');
} else {
musicBtn.innerText = "⏸ POZASTAVIŤ";
musicBtn.style.setProperty('background-color', '#28a745', 'important');
}
};
// Obsluha tlačidla Play/Pause
musicBtn.addEventListener('click', () => {
if (!audio.src || audio.src.endsWith('/')) {
audio.src = playlistSelect.value;
}
if (audio.paused) {
audio.play().then(updateButtonUI).catch(() => alert("Klikni najprv na plochu!"));
} else {
audio.pause();
updateButtonUI();
}
});
// OPRAVA PREKLIKÁVANIA PLAYLISTOV
playlistSelect.addEventListener('change', () => {
const wasPlaying = !audio.paused;
audio.src = playlistSelect.value;
audio.load();
if (wasPlaying) {
audio.play().then(updateButtonUI);
} else {
updateButtonUI();
}
});
// Hlasitosť
if (volumeSlider) {
audio.volume = volumeSlider.value;
volumeSlider.addEventListener('input', (e) => {
audio.volume = e.target.value;
});
}
// --- 3. ODPOČET A ČASOVÉ PÁSMA ---
let viewMode = 'days';
const updateCountdown = () => {
if (!timerDisplay) return;
// Funkčné časové pásmo
const tz = timezoneSelect ? timezoneSelect.value : "Europe/Bratislava";
const now = new Date(new Date().toLocaleString("en-US", {timeZone: tz}));
let target = new Date(now.getFullYear(), 11, 24, 0, 0, 0);
if (now > target) target.setFullYear(target.getFullYear() + 1);
const diff = target - now;
if (viewMode === 'days') {
const d = Math.floor(diff / 86400000);
const h = Math.floor((diff / 3600000) % 24);
const m = Math.floor((diff / 60000) % 60);
const s = Math.floor((diff / 1000) % 60);
timerDisplay.innerText = `${d}d ${h}h ${m}m ${s}s`;
} else {
const hTotal = Math.floor(diff / 3600000);
const m = Math.floor((diff / 60000) % 60);
const s = Math.floor((diff / 1000) % 60);
timerDisplay.innerText = `${hTotal.toLocaleString()}h ${m}m ${s}s`;
}
};
if (timezoneSelect) timezoneSelect.addEventListener('change', updateCountdown);
btnDays.addEventListener('click', () => {
viewMode = 'days';
btnDays.classList.add('active');
btnHours.classList.remove('active');
updateCountdown();
});
btnHours.addEventListener('click', () => {
viewMode = 'hours';
btnHours.classList.add('active');
btnDays.classList.remove('active');
updateCountdown();
});
setInterval(updateCountdown, 1000);
updateCountdown();
// --- 4. SNEŽENIE ---
setInterval(() => {
const snow = document.createElement('div');
snow.className = 'snowflake';
snow.innerHTML = '❄';
snow.style.left = Math.random() * 100 + 'vw';
snow.style.animation = `fall ${Math.random() * 3 + 2}s linear forwards`;
document.body.appendChild(snow);
setTimeout(() => snow.remove(), 5000);
}, 200);
});
index.html
<!DOCTYPE html>
<html lang="sk">
<head>
<meta charset="UTF-8">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<title>Vianočný Odpočet — ibasterisk.eu</title>
<link rel="stylesheet" href="style.css">
<link rel="icon" type="image/png" href="favicon/favicon.png">
</head>
<body>
<div id="snow-container"></div>
<div class="container">
<h1>🎅 Vianočný Odpočet</h1>
<div id="countdown">
<span id="timer">Načítavam...</span>
</div>
<div class="view-toggle">
<button id="btn-days" class="active">Dni</button>
<button id="btn-hours">Hodiny</button>
</div>
<div class="controls-group">
<label>Časové pásmo:</label>
<select id="timezone-select">
<option value="Europe/Bratislava">🇸🇰 Slovensko</option>
<option value="Asia/Tokyo">🇯🇵 Tokio (Japonsko)</option>
<option value="Europe/Moscow">🇷🇺 Moskva (Rusko)</option>
<option value="Australia/Sydney">🇦🇺 Sydney (Austrália)</option>
</select>
</div>
<div class="controls-group">
<label>Vyber Playlist:</label>
<select id="playlist-select">
<option value="mp3/christmas01.mp3">Vianočný Mix 01</option>
<option value="mp3/buble1.mp3">Michael Bublé 1</option>
<option value="mp3/buble2.mp3">Michael Bublé 2</option>
<option value="mp3/top20.mp3">Vianočná Top 20</option>
</select>
</div>
<button id="music-btn" class="btn-stopped">🎶 Zapnúť hudbu</button>
<div class="volume-container">
<label>Hlasitosť</label>
<input type="range" id="volume-slider" min="0" max="1" step="0.1" value="0.5">
</div>
<audio id="bg-music" loop></audio>
</div>
<script src="script.js"></script>
</body>
</html>
style.css
body {
margin: 0; padding: 0;
width: 100vw; height: 100vh;
display: flex; justify-content: center; align-items: center;
background-size: cover; background-position: center;
background-color: #1a1a1a;
font-family: 'Segoe UI', Arial, sans-serif;
transition: background-image 2s ease-in-out;
overflow: hidden;
}
.container {
background: rgba(0, 0, 0, 0.8);
backdrop-filter: blur(10px);
padding: 30px; border-radius: 25px;
color: white; text-align: center; width: 350px;
position: relative; z-index: 10;
box-shadow: 0 10px 30px rgba(0,0,0,0.5);
}
#timer {
font-size: 2rem; font-weight: bold; color: #ff4d4d;
display: block; margin: 20px 0;
}
.view-toggle { display: flex; justify-content: center; margin-bottom: 20px; }
.view-toggle button {
background: #444; color: white; border: none;
padding: 10px 20px; cursor: pointer; transition: 0.3s;
}
.view-toggle button.active { background: #ff4d4d !important; }
.view-toggle button:first-child { border-radius: 10px 0 0 10px; }
.view-toggle button:last-child { border-radius: 0 10px 10px 0; }
select {
width: 100%; padding: 12px; border-radius: 10px;
background: #222; color: white; margin-bottom: 15px; border: 1px solid #444;
}
#music-btn {
width: 100%; padding: 15px; border-radius: 15px;
border: none; color: white; font-weight: bold;
cursor: pointer; text-transform: uppercase;
}
.btn-stopped { background-color: #ff4d4d !important; }
.btn-playing { background-color: #28a745 !important; }
.snowflake {
position: fixed; top: -10px; color: white !important;
z-index: 1000; pointer-events: none;
animation: fall linear forwards;
}
@keyframes fall {
to { transform: translateY(105vh); }
}
.volume-container input { width: 100%; accent-color: #ff4d4d; margin-top: 10px;
}
citaj
Tento súbor, nieje dôležitý na koľko sú to len moje poznámky
Následne som spustil kontajner
sudo docker-compose down
sudo docker-compose up --build -d
