Fix date selection position preservation in calendar carousel
This commit is contained in:
@@ -36,10 +36,46 @@ class DateCarousel {
|
|||||||
this.maxInputId = maxInputId;
|
this.maxInputId = maxInputId;
|
||||||
this.minInput = document.getElementById(minInputId);
|
this.minInput = document.getElementById(minInputId);
|
||||||
this.maxInput = document.getElementById(maxInputId);
|
this.maxInput = document.getElementById(maxInputId);
|
||||||
this.centerDate = new Date(); // Центральная дата (по умолчанию сегодня)
|
|
||||||
this.today = new Date();
|
this.today = new Date();
|
||||||
this.today.setHours(0, 0, 0, 0);
|
this.today.setHours(0, 0, 0, 0);
|
||||||
this.daysCount = 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() {
|
init() {
|
||||||
this.calculateDaysCount();
|
this.calculateDaysCount();
|
||||||
this.loadSelectedDate(); // Загрузить выбранную дату из фильтра
|
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.render();
|
||||||
this.attachNavHandlers();
|
this.attachNavHandlers();
|
||||||
}
|
}
|
||||||
@@ -56,7 +130,7 @@ class DateCarousel {
|
|||||||
* Загрузка выбранной даты из скрытых полей фильтра
|
* Загрузка выбранной даты из скрытых полей фильтра
|
||||||
*/
|
*/
|
||||||
loadSelectedDate() {
|
loadSelectedDate() {
|
||||||
// Если есть выбранная дата в фильтре, центрируем на ней, чтобы она была видна
|
// Если есть выбранная дата в фильтре
|
||||||
if (this.minInput.value && this.maxInput.value &&
|
if (this.minInput.value && this.maxInput.value &&
|
||||||
this.minInput.value === this.maxInput.value) {
|
this.minInput.value === this.maxInput.value) {
|
||||||
const parts = this.minInput.value.split('-');
|
const parts = this.minInput.value.split('-');
|
||||||
@@ -68,9 +142,17 @@ class DateCarousel {
|
|||||||
);
|
);
|
||||||
selectedDate.setHours(0, 0, 0, 0);
|
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 {
|
} else {
|
||||||
// Если фильтра нет, центрируем на сегодняшнем дне
|
// Если фильтра нет, центрируем на сегодняшнем дне
|
||||||
@@ -252,18 +334,19 @@ class DateCarousel {
|
|||||||
this.minInput.value = formattedDate;
|
this.minInput.value = formattedDate;
|
||||||
this.maxInput.value = formattedDate;
|
this.maxInput.value = formattedDate;
|
||||||
|
|
||||||
// Обновляем центральную дату, чтобы выбранная дата была в центре
|
// Вычисляем смещение выбранной даты от центра
|
||||||
this.centerDate = new Date(date);
|
const offset = this.calculateDateOffset(date);
|
||||||
this.centerDate.setHours(0, 0, 0, 0);
|
// Сохраняем центральную дату и смещение перед отправкой формы
|
||||||
|
this.saveCenterDate(offset);
|
||||||
|
|
||||||
// Визуальная обратная связь
|
// Визуальная обратная связь
|
||||||
btn.classList.add('clicked');
|
btn.classList.add('clicked');
|
||||||
setTimeout(() => btn.classList.remove('clicked'), 300);
|
setTimeout(() => btn.classList.remove('clicked'), 300);
|
||||||
|
|
||||||
// Обновление визуального состояния
|
// Обновление визуального состояния (без изменения центральной даты)
|
||||||
this.render();
|
this.render();
|
||||||
|
|
||||||
console.log(`Selected date: ${formattedDate}`);
|
console.log(`Selected date: ${formattedDate}, offset: ${offset}`);
|
||||||
|
|
||||||
// Автоматическая отправка формы
|
// Автоматическая отправка формы
|
||||||
const form = this.minInput.closest('form');
|
const form = this.minInput.closest('form');
|
||||||
@@ -288,11 +371,81 @@ class DateCarousel {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Сохранение центральной даты и смещения в 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 дней
|
* Сдвиг диапазона дней на N дней
|
||||||
*/
|
*/
|
||||||
shiftDays(offset) {
|
shiftDays(offset) {
|
||||||
this.centerDate.setDate(this.centerDate.getDate() + offset);
|
this.centerDate.setDate(this.centerDate.getDate() + offset);
|
||||||
|
this.saveCenterDate(); // Сохраняем новую центральную дату (без смещения для прокрутки)
|
||||||
this.render();
|
this.render();
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
Reference in New Issue
Block a user