Skip to content

Commit

Permalink
fix(datepicker): infinity loop
Browse files Browse the repository at this point in the history
  • Loading branch information
mlmoravek authored Oct 15, 2023
1 parent 860d083 commit fc45dcf
Show file tree
Hide file tree
Showing 2 changed files with 36 additions and 35 deletions.
41 changes: 20 additions & 21 deletions packages/oruga-next/src/components/datepicker/DatepickerTable.vue
Original file line number Diff line number Diff line change
@@ -1,7 +1,7 @@
<script setup lang="ts">
import { computed, ref, type PropType } from "vue";
import ODatepickerTableRow from "./DatepickerTableRow.vue";
import { useComputedClass } from "@/composables";
import { useComputedClass, usePropBinding } from "@/composables";
import {
useDatepickerShare,
type DatepickerProps,
Expand Down Expand Up @@ -48,6 +48,8 @@ const hoveredEndDate = ref<Date>();
const datepicker = computed<DatepickerProps>(() => props.pickerProps);
const focusedDate = usePropBinding<FocusedDate>("focusedDate", props, emits);
const visibleDayNames = computed(() => {
const visibleDayNames = [];
let index = datepicker.value.firstDayOfWeek;
Expand All @@ -69,16 +71,16 @@ const eventsInThisMonth = computed(() => {
)
.filter(
(event) =>
event.date.getMonth() === props.focusedDate.month &&
event.date.getFullYear() === props.focusedDate.year,
event.date.getMonth() === focusedDate.value.month &&
event.date.getFullYear() === focusedDate.value.year,
);
});
/** Return array of all weeks in the specified month */
const weeksInThisMonth = computed(() => {
validateFocusedDay();
const month = props.focusedDate.month;
const year = props.focusedDate.year;
const month = focusedDate.value.month;
const year = focusedDate.value.year;
const weeksInThisMonth = [];
let startingDay = 1;
Expand Down Expand Up @@ -117,36 +119,34 @@ const hoveredDateRange = computed(() => {
});
function validateFocusedDay(): void {
const focusedDate = new Date(
props.focusedDate.year,
props.focusedDate.month,
props.focusedDate.day,
const currentDate = new Date(
focusedDate.value.year,
focusedDate.value.month,
focusedDate.value.day,
);
if (isDateSelectable(focusedDate, props.focusedDate.month)) return;
if (isDateSelectable(currentDate, focusedDate.value.month)) return;
let day = 0;
// Number of days in the current month
const monthDays = new Date(
props.focusedDate.year,
props.focusedDate.month + 1,
focusedDate.value.year,
focusedDate.value.month + 1,
0,
).getDate();
let firstFocusable = null;
while (!firstFocusable && ++day < monthDays) {
const date = new Date(
props.focusedDate.year,
props.focusedDate.month,
focusedDate.value.year,
focusedDate.value.month,
day,
);
if (isDateSelectable(date, props.focusedDate.month)) {
firstFocusable = focusedDate;
const focused = {
if (isDateSelectable(date, focusedDate.value.month)) {
firstFocusable = currentDate;
focusedDate.value = {
day: date.getDate(),
month: date.getMonth(),
year: date.getFullYear(),
};
emits("update:focusedDate", focused);
}
}
}
Expand Down Expand Up @@ -222,12 +222,11 @@ function onRangeHoverEndDate(date: Date): void {
}
function onChangeFocus(date: Date): void {
const focused = {
focusedDate.value = {
day: date.getDate(),
month: date.getMonth(),
year: date.getFullYear(),
};
emits("update:focusedDate", focused);
}
// --- Computed Component Classes ---
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -60,22 +60,22 @@ function setDayRef(date: Date, el: Element | ComponentPublicInstance): void {
watch(
() => props.day,
(day) => {
const refKey = `day-${props.month}-${day}`;
nextTick(() => {
// $nextTick is needed when month is changed
const ref = dayRefs.value.get(refKey);
if (ref?.length > 0 && ref[0]) {
ref[0].focus();
}
});
// if day is in week
if (props.week.map((d) => d.getDate()).includes(day))
nextTick(() => {
// $nextTick is needed when month is changed
const refKey = `day-${props.month}-${day}`;
const ref = dayRefs.value.get(refKey);
if (ref) ref.focus();
});
},
);
function clickWeekNumber(week: number): void {
if (datepicker.value.weekNumberClickable) emits("week-number-click", week);
}
function getSetDayOfYear(input): number {
function getDayOfYear(input): number {
return (
Math.round(
(input.getTime() - new Date(input.getFullYear(), 0, 1).getTime()) /
Expand All @@ -89,7 +89,7 @@ function getWeekNumber(mom): number {
// Rules for the first week : 1 for the 1st January, 4 for the 4th January
const doy = datepicker.value.rulesForFirstWeek;
const weekOffset = firstWeekOffset(mom.getFullYear(), dow, doy);
const week = Math.floor((getSetDayOfYear(mom) - weekOffset - 1) / 7) + 1;
const week = Math.floor((getDayOfYear(mom) - weekOffset - 1) / 7) + 1;
let resWeek;
let resYear;
if (week < 1) {
Expand Down Expand Up @@ -160,12 +160,14 @@ function selectDate(date: Date): void {
function changeFocus(day, inc): void {
const nextDay = new Date(day.getTime());
nextDay.setDate(day.getDate() + inc);
// if next day is out of range or not selectable, move to next selectable date
while (
(!datepicker.value.minDate || nextDay > datepicker.value.minDate) &&
(!datepicker.value.maxDate || nextDay < datepicker.value.maxDate) &&
!isDateSelectable(nextDay, props.month)
(datepicker.value.minDate && nextDay < datepicker.value.minDate) ||
(datepicker.value.maxDate && nextDay > datepicker.value.maxDate) ||
!isDateSelectable(nextDay, nextDay.getMonth())
) {
nextDay.setDate(day.getDate() + Math.sign(inc));
// revert day selection until selectable day is reached
nextDay.setDate(nextDay.getDate() - Math.sign(inc));
}
setRangeHoverEndDate(nextDay);
emits("change-focus", nextDay);
Expand Down

0 comments on commit fc45dcf

Please sign in to comment.