Как сделать так, чтобы при выборе какого-то события из списка, менялся код таймера (сколько остается дней до этого события)?
Например: Человек выбрал их списка событие 'Лето', тогда у него появляется таймер отсчета времени до 1 июня; человек вновь выбирает из списка событие, но уже другое '8 марта', тогда старый таймер удаляется, а появляется новый, показывающий сколько осталось дней до этого события (8 марта). Если что-то непонятно, обязательно задавайте вопрос в комментариях. Постараюсь объяснить то, что вы не поняли.
<!-- Показывается 1 таймер отсчета (до 1 июня): -->
<div class="timer" id="timer">
<div class="timer__items">
<div class="timer__item timer__days">00</div>
<div class="timer__item timer__hours">00</div>
<div class="timer__item timer__minutes">00</div>
<div class="timer__item timer__seconds">00</div>
</div>
</div>
<!-- Показывается 2 таймер отсчета (до 8 марта): -->
<div class="timer__two" id="timer__two">
<div class="timer__items__two">
<div class="timer__item__two days__two">00</div>
<div class="timer__item__two hours__two">00</div>
<div class="timer__item__two minutes__two">00</div>
<div class="timer__item__two seconds__two">00</div>
</div>
</div>
<!-- Показывается 3 таймер (до 1 сентября): -->
<div class="timer__three" id="timer__three">
<div class="timer__items__three">
<div class="timer__item__three days__three">00</div>
<div class="timer__item__three hours__three">00</div>
<div class="timer__item__three minutes__three">00</div>
<div class="timer__item__three seconds__three">00</div>
</div>
</div>
<style>
.timer__two{
display: none;
}
.timer__three{
display: none;
}
</style>
<!-- Список, из которого пользователь выбирает событие, чтобы узнать сколько остается дней до него: -->
<select name="cities" id="select">
<option value="Summer">Лето</option>
<option value="Spring">8 марта</option>
<option value="Autumn">1 сентября</option>
</select>
<button id="btn">Подсчитать</button>
<!-- Это код таймера (в данном случае отсчитывающий до 1 июня): -->
<!-- Нужно сделать так, чтобы в этом скрипте менялась переменная до какого числа нужно вести отсчет времени (сколько дней осталось)-->
<!-- Например: если человек выбрал из событий 8 марта, то меняется код, так, чтобы велся отсчет до 8 марта, а не до какого-то другого события -->
<script>
document.addEventListener('DOMContentLoaded', function() {
// конечная дата
const deadline = new Date(2022, 05, 01);
// id таймера
let timerId = null;
// склонение числительных
function declensionNum(num, words) {
return words[(num % 100 > 4 && num % 100 < 20) ? 2 : [2, 0, 1, 1, 1, 2][(num % 10 < 5) ? num % 10 : 5]];
}
// вычисляем разницу дат и устанавливаем оставшееся времени в качестве содержимого элементов
function countdownTimer() {
const diff = deadline - new Date();
if (diff <= 0) {
clearInterval(timerId);
}
const days = diff > 0 ? Math.floor(diff / 1000 / 60 / 60 / 24) : 0;
const hours = diff > 0 ? Math.floor(diff / 1000 / 60 / 60) % 24 : 0;
const minutes = diff > 0 ? Math.floor(diff / 1000 / 60) % 60 : 0;
const seconds = diff > 0 ? Math.floor(diff / 1000) % 60 : 0;
$days.textContent = days < 10 ? '0' + days : days;
$hours.textContent = hours < 10 ? '0' + hours : hours;
$minutes.textContent = minutes < 10 ? '0' + minutes : minutes;
$seconds.textContent = seconds < 10 ? '0' + seconds : seconds;
$days.dataset.title = declensionNum(days, ['день', 'дня', 'дней']);
$hours.dataset.title = declensionNum(hours, ['час', 'часа', 'часов']);
$minutes.dataset.title = declensionNum(minutes, ['минута', 'минуты', 'минут']);
$seconds.dataset.title = declensionNum(seconds, ['секунда', 'секунды', 'секунд']);
}
// получаем элементы, содержащие компоненты даты
const $days = document.querySelector('.timer__days');
const $hours = document.querySelector('.timer__hours');
const $minutes = document.querySelector('.timer__minutes');
const $seconds = document.querySelector('.timer__seconds');
// вызываем функцию countdownTimer
countdownTimer();
// вызываем функцию countdownTimer каждую секунду
timerId = setInterval(countdownTimer, 1000);
});
</script>
<script>
const cities = document.getElementById('select');
const btn = document.getElementById('btn');
const time_one = document.getElementById('timer');
const time_two = document.getElementById('timer__two');
const time_three = document.getElementById('timer__three');
// Условия, по которым появляется нужный таймер для отсчета времени до нужного события:
btn.onclick = event => {
let checkedCityText = cities.options[cities.selectedIndex].text;
if (checkedCityText == 'Лето') {
time_one.style.display = 'block';
time_two.style.display = 'none';
time_three.style.display = 'none';
}
if (checkedCityText == '8 марта') {
time_one.style.display = 'none';
time_two.style.display = 'block';
time_three.style.display = 'none';
}
if (checkedCityText == '1 сентября') {
time_one.style.display = 'none';
time_two.style.display = 'none';
time_three.style.display = 'block';
}
}
</script>
Ответы (2 шт):
У Вас deadline константа объявленная в функции. От того у вас сложности с тем, чтобы обновить значение. Просто вынесите её в более доступную область видимости, да даже в глобальный объект, и сделайте изменяемой. В функцию counterTime передавайте как аргумент.
Та же проблема с анонимной функцией объявленной в обработчике события DOMContentLoaded — Вы просто не можете использовать её множество раз, а также передавать аргументы.
Вариант с тем, чтобы обновлять таймер при смене события:
- Вынесите анонимную функцию во вне, а внутри DOMContentLoaded вызывайте её.
- Вместо константного значения
new Date(2022, 05, 01)создайте и используйте аргумент, например,date - Вызывайте функцию, которую вынесли на этапе 1 каждый раз, когда пользователь меняет "событие"
- Очищайте предыдущий таймер
Вариант через изменение deadline:
- Вынести её и сделать изменяемой
- При каждом
countdownTimer()высчитывайте diff основываясь на текущем значенииdeadline
function countdownTimer() {
const diff = globalThis.deadline - new Date();
if (diff <= 0) {
// Если останавливать интервал, то при окончании одного события таймер остановиться и для других
return;
}
const days = diff > 0 ? Math.floor(diff / 1000 / 60 / 60 / 24) : 0;
const hours = diff > 0 ? Math.floor(diff / 1000 / 60 / 60) % 24 : 0;
const minutes = diff > 0 ? Math.floor(diff / 1000 / 60) % 60 : 0;
const seconds = diff > 0 ? Math.floor(diff / 1000) % 60 : 0;
$days.textContent = days < 10 ? '0' + days : days;
$hours.textContent = hours < 10 ? '0' + hours : hours;
$minutes.textContent = minutes < 10 ? '0' + minutes : minutes;
$seconds.textContent = seconds < 10 ? '0' + seconds : seconds;
$days.dataset.title = declensionNum(days, ['день', 'дня', 'дней']);
$hours.dataset.title = declensionNum(hours, ['час', 'часа', 'часов']);
$minutes.dataset.title = declensionNum(minutes, ['минута', 'минуты', 'минут']);
$seconds.dataset.title = declensionNum(seconds, ['секунда', 'секунды', 'секунд']);
}
btn.onclick = event => {
let checkedCityText = cities.options[cities.selectedIndex].text;
if (checkedCityText == 'Лето') {
time_one.style.display = 'block';
time_two.style.display = 'none';
time_three.style.display = 'none';
globalThis.deadline = new Date (<дата>);
}
if (checkedCityText == '8 марта') {
time_one.style.display = 'none';
time_two.style.display = 'block';
time_three.style.display = 'none';
globalThis.deadline = new Date (<дата>);
}
if (checkedCityText == '1 сентября') {
time_one.style.display = 'none';
time_two.style.display = 'none';
time_three.style.display = 'block';
globalThis.deadline = new Date (<дата>);
}
}
Основное, что я сделал — это заменил diff = deadline - new Date() на globalThis.deadline, что решало вашу проблему
Все остальное в демонстративных целях, чтобы "работало":
- Вынес смену таймера в отдельную функцию
setDeadline - Оставил всего один таймер вместо
- Изменил метку по умолчанию с 2022, 05, 01 т.к. эта дата прошла и таймер отображал 0.00.00
<div class="timer" id="timer">
<!-- Не знаю имели ли смысл несколько таймеров. -->
<div class="timer__items">
<div class="timer__item timer__days">00</div>
<div class="timer__item timer__hours">00</div>
<div class="timer__item timer__minutes">00</div>
<div class="timer__item timer__seconds">00</div>
</div>
</div>
<style>
/* Для демонстрации того, как по необходимости для каждого таймера указывать особый стиль */
.timer[data-style="summer"] {
background: rgba(238, 193, 156, 0.4);
}
.timer[data-style="spring"] {
background: rgb(241, 194, 218, 0.4);
}
.timer[data-style="autumn"] {
background: rgb(110, 81, 112, 0.4);
}
</style>
<select name="cities" id="select">
<option value="Summer">Лето</option>
<option value="Spring">8 марта</option>
<option value="Autumn">1 сентября</option>
</select>
<button id="btn">Подсчитать</button>
<script>
document.addEventListener('DOMContentLoaded', function() {
setDeadline("Лето");
// id таймера
let timerId = null;
// склонение числительных
function declensionNum(num, words) {
return words[(num % 100 > 4 && num % 100 < 20) ? 2 : [2, 0, 1, 1, 1, 2][(num % 10 < 5) ? num % 10 : 5]];
}
// вычисляем разницу дат и устанавливаем оставшееся времени в качестве содержимого элементов
function countdownTimer() {
const diff = globalThis.deadline - new Date();
if (diff <= 0) {
clearInterval(timerId);
}
const days = diff > 0 ? Math.floor(diff / 1000 / 60 / 60 / 24) : 0;
const hours = diff > 0 ? Math.floor(diff / 1000 / 60 / 60) % 24 : 0;
const minutes = diff > 0 ? Math.floor(diff / 1000 / 60) % 60 : 0;
const seconds = diff > 0 ? Math.floor(diff / 1000) % 60 : 0;
$days.textContent = days < 10 ? '0' + days : days;
$hours.textContent = hours < 10 ? '0' + hours : hours;
$minutes.textContent = minutes < 10 ? '0' + minutes : minutes;
$seconds.textContent = seconds < 10 ? '0' + seconds : seconds;
$days.dataset.title = declensionNum(days, ['день', 'дня', 'дней']);
$hours.dataset.title = declensionNum(hours, ['час', 'часа', 'часов']);
$minutes.dataset.title = declensionNum(minutes, ['минута', 'минуты', 'минут']);
$seconds.dataset.title = declensionNum(seconds, ['секунда', 'секунды', 'секунд']);
}
// получаем элементы, содержащие компоненты даты
const $days = document.querySelector('.timer__days');
const $hours = document.querySelector('.timer__hours');
const $minutes = document.querySelector('.timer__minutes');
const $seconds = document.querySelector('.timer__seconds');
// вызываем функцию countdownTimer
countdownTimer();
// вызываем функцию countdownTimer каждую секунду
timerId = setInterval(countdownTimer, 1000);
});
</script>
<script>
const cities = document.getElementById('select');
const btn = document.getElementById('btn');
const time_one = document.getElementById('timer');
// Условия, по которым появляется нужный таймер для отсчета времени до нужного события:
btn.onclick = event => {
let checkedCityText = cities.options[cities.selectedIndex].text;
// Я вынес в отдельную функцию, чтобы её можно было вызвать другими способами, например при загрузке страницы
setDeadline(checkedCityText);
}
function setDeadline(id){
if (id == 'Лето') {
time_one.setAttribute("data-style", "summer");
globalThis.deadline = new Date(2023, 06, 01);
}
if (id == '8 марта') {
time_one.setAttribute("data-style", "spring");
globalThis.deadline = new Date(2023, 03, 08);
}
if (id == '1 сентября') {
time_one.setAttribute("data-style", "autumn");
globalThis.deadline = new Date(2023, 09, 01);
}
}
</script>