Fix date selection position preservation in calendar carousel
This commit is contained in:
@@ -36,10 +36,46 @@ class DateCarousel {
|
||||
this.maxInputId = maxInputId;
|
||||
this.minInput = document.getElementById(minInputId);
|
||||
this.maxInput = document.getElementById(maxInputId);
|
||||
this.centerDate = new Date(); // Центральная дата (по умолчанию сегодня)
|
||||
this.today = new Date();
|
||||
this.today.setHours(0, 0, 0, 0);
|
||||
this.daysCount = 0; // Будет рассчитано динамически
|
||||
|
||||
// Загружаем сохранённую дату из localStorage или устанавливаем сегодня
|
||||
const savedData = this.loadSavedCenterDate();
|
||||
if (savedData) {
|
||||
// Если есть смещение, это означает, что дата была выбрана пользователем
|
||||
if (savedData.offset !== 0) {
|
||||
// Проверяем, есть ли выбранная дата в фильтрах
|
||||
if (this.minInput && this.minInput.value && this.maxInput.value &&
|
||||
this.minInput.value === this.maxInput.value) {
|
||||
// Получаем выбранную дату из фильтра
|
||||
const parts = this.minInput.value.split('-');
|
||||
if (parts.length === 3) {
|
||||
const selectedDate = new Date(
|
||||
parseInt(parts[0]),
|
||||
parseInt(parts[1]) - 1,
|
||||
parseInt(parts[2])
|
||||
);
|
||||
selectedDate.setHours(0, 0, 0, 0);
|
||||
|
||||
// Вычисляем центральную дату: выбранная дата минус смещение
|
||||
this.centerDate = new Date(selectedDate);
|
||||
this.centerDate.setDate(this.centerDate.getDate() - savedData.offset);
|
||||
} else {
|
||||
// Если дата в фильтре некорректна, используем сохранённую центральную дату
|
||||
this.centerDate = savedData.centerDate;
|
||||
}
|
||||
} else {
|
||||
// Если нет фильтра с одной датой, используем сохранённую центральную дату
|
||||
this.centerDate = savedData.centerDate;
|
||||
}
|
||||
} else {
|
||||
// Если смещения нет, используем сохранённую центральную дату
|
||||
this.centerDate = savedData.centerDate;
|
||||
}
|
||||
} else {
|
||||
this.centerDate = new Date();
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
@@ -48,6 +84,44 @@ class DateCarousel {
|
||||
init() {
|
||||
this.calculateDaysCount();
|
||||
this.loadSelectedDate(); // Загрузить выбранную дату из фильтра
|
||||
|
||||
// Если в localStorage есть сохраненные данные
|
||||
const savedData = this.loadSavedCenterDate();
|
||||
if (savedData) {
|
||||
// Если есть смещение, это означает, что дата была выбрана пользователем
|
||||
if (savedData.offset !== 0) {
|
||||
// Проверяем, есть ли выбранная дата в фильтрах
|
||||
if (this.minInput.value && this.maxInput.value &&
|
||||
this.minInput.value === this.maxInput.value) {
|
||||
// Получаем выбранную дату из фильтра
|
||||
const parts = this.minInput.value.split('-');
|
||||
if (parts.length === 3) {
|
||||
const selectedDate = new Date(
|
||||
parseInt(parts[0]),
|
||||
parseInt(parts[1]) - 1,
|
||||
parseInt(parts[2])
|
||||
);
|
||||
selectedDate.setHours(0, 0, 0, 0);
|
||||
|
||||
// Вычисляем центральную дату: выбранная дата минус смещение
|
||||
// (т.к. смещение показывает, на сколько дней выбранная дата
|
||||
// смещена вправо от центра)
|
||||
this.centerDate = new Date(selectedDate);
|
||||
this.centerDate.setDate(this.centerDate.getDate() - savedData.offset);
|
||||
} else {
|
||||
// Если дата в фильтре некорректна, используем сохранённую центральную дату
|
||||
this.centerDate = savedData.centerDate;
|
||||
}
|
||||
} else {
|
||||
// Если нет фильтра с одной датой, используем сохранённую центральную дату
|
||||
this.centerDate = savedData.centerDate;
|
||||
}
|
||||
} else {
|
||||
// Если смещения нет, используем сохранённую центральную дату
|
||||
this.centerDate = savedData.centerDate;
|
||||
}
|
||||
}
|
||||
|
||||
this.render();
|
||||
this.attachNavHandlers();
|
||||
}
|
||||
@@ -56,7 +130,7 @@ class DateCarousel {
|
||||
* Загрузка выбранной даты из скрытых полей фильтра
|
||||
*/
|
||||
loadSelectedDate() {
|
||||
// Если есть выбранная дата в фильтре, центрируем на ней, чтобы она была видна
|
||||
// Если есть выбранная дата в фильтре
|
||||
if (this.minInput.value && this.maxInput.value &&
|
||||
this.minInput.value === this.maxInput.value) {
|
||||
const parts = this.minInput.value.split('-');
|
||||
@@ -68,9 +142,17 @@ class DateCarousel {
|
||||
);
|
||||
selectedDate.setHours(0, 0, 0, 0);
|
||||
|
||||
// Центрируем на выбранной дате, чтобы она всегда была видна
|
||||
this.centerDate = selectedDate;
|
||||
console.log(`Centering on selected date: ${this.formatDate(selectedDate)}`);
|
||||
// Устанавливаем центральную дату на выбранную дату только если фильтр отличается от сегодняшней даты
|
||||
// Это позволяет определить, был ли фильтр установлен до посещения страницы
|
||||
const todayFormatted = this.formatDate(this.today);
|
||||
if (this.minInput.value !== todayFormatted) {
|
||||
// Возможно, фильтр уже был установлен, но мы всё равно не хотим центрировать
|
||||
// для согласованности с поведением после выбора даты
|
||||
console.log(`Selected date in filter: ${this.formatDate(selectedDate)}, keeping current view`);
|
||||
} else {
|
||||
// Если фильтр равен сегодняшней дате, можно центрировать на сегодня
|
||||
console.log(`Filter is today: ${this.formatDate(selectedDate)}, keeping current view`);
|
||||
}
|
||||
}
|
||||
} else {
|
||||
// Если фильтра нет, центрируем на сегодняшнем дне
|
||||
@@ -252,18 +334,19 @@ class DateCarousel {
|
||||
this.minInput.value = formattedDate;
|
||||
this.maxInput.value = formattedDate;
|
||||
|
||||
// Обновляем центральную дату, чтобы выбранная дата была в центре
|
||||
this.centerDate = new Date(date);
|
||||
this.centerDate.setHours(0, 0, 0, 0);
|
||||
// Вычисляем смещение выбранной даты от центра
|
||||
const offset = this.calculateDateOffset(date);
|
||||
// Сохраняем центральную дату и смещение перед отправкой формы
|
||||
this.saveCenterDate(offset);
|
||||
|
||||
// Визуальная обратная связь
|
||||
btn.classList.add('clicked');
|
||||
setTimeout(() => btn.classList.remove('clicked'), 300);
|
||||
|
||||
// Обновление визуального состояния
|
||||
// Обновление визуального состояния (без изменения центральной даты)
|
||||
this.render();
|
||||
|
||||
console.log(`Selected date: ${formattedDate}`);
|
||||
console.log(`Selected date: ${formattedDate}, offset: ${offset}`);
|
||||
|
||||
// Автоматическая отправка формы
|
||||
const form = this.minInput.closest('form');
|
||||
@@ -287,12 +370,82 @@ class DateCarousel {
|
||||
nextBtn.addEventListener('click', () => this.shiftDays(1));
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Сохранение центральной даты и смещения в localStorage
|
||||
*/
|
||||
saveCenterDate(offset = 0) {
|
||||
const key = `date_carousel_center_${this.minInputId}`;
|
||||
const centerDateStr = this.centerDate.toISOString().split('T')[0]; // Формат YYYY-MM-DD
|
||||
const saveData = {
|
||||
centerDate: centerDateStr,
|
||||
offset: offset
|
||||
};
|
||||
localStorage.setItem(key, JSON.stringify(saveData));
|
||||
}
|
||||
|
||||
/**
|
||||
* Загрузка центральной даты из localStorage
|
||||
*/
|
||||
loadSavedCenterDate() {
|
||||
const key = `date_carousel_center_${this.minInputId}`;
|
||||
const savedDataStr = localStorage.getItem(key);
|
||||
|
||||
if (savedDataStr) {
|
||||
try {
|
||||
const savedData = JSON.parse(savedDataStr);
|
||||
const savedDate = new Date(savedData.centerDate);
|
||||
savedDate.setHours(0, 0, 0, 0);
|
||||
return {
|
||||
centerDate: savedDate,
|
||||
offset: savedData.offset || 0
|
||||
};
|
||||
} catch (e) {
|
||||
console.error('Error parsing saved date data', e);
|
||||
// В случае ошибки возвращаем старый формат для совместимости
|
||||
const savedDateStr = localStorage.getItem(key);
|
||||
if (savedDateStr && !savedDateStr.includes('{')) {
|
||||
const savedDate = new Date(savedDateStr);
|
||||
savedDate.setHours(0, 0, 0, 0);
|
||||
return {
|
||||
centerDate: savedDate,
|
||||
offset: 0
|
||||
};
|
||||
}
|
||||
return null;
|
||||
}
|
||||
}
|
||||
|
||||
return null;
|
||||
}
|
||||
|
||||
/**
|
||||
* Вычисление смещения выбранной даты от центральной
|
||||
*/
|
||||
calculateDateOffset(selectedDate) {
|
||||
// Генерируем дни с текущей центральной датой
|
||||
const days = this.generateDays();
|
||||
// Находим индекс выбранной даты
|
||||
const selectedIndex = days.findIndex(day =>
|
||||
day.date.getTime() === selectedDate.getTime()
|
||||
);
|
||||
|
||||
if (selectedIndex !== -1) {
|
||||
// Находим центральный индекс
|
||||
const centerIndex = Math.floor(this.daysCount / 2);
|
||||
// Вычисляем смещение от центра
|
||||
return selectedIndex - centerIndex;
|
||||
}
|
||||
|
||||
return 0; // Если дата не найдена, возвращаем 0
|
||||
}
|
||||
|
||||
/**
|
||||
* Сдвиг диапазона дней на N дней
|
||||
*/
|
||||
shiftDays(offset) {
|
||||
this.centerDate.setDate(this.centerDate.getDate() + offset);
|
||||
this.saveCenterDate(); // Сохраняем новую центральную дату (без смещения для прокрутки)
|
||||
this.render();
|
||||
}
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user