<template> <span ref="container" :id="id" :class="cx('root')" :style="sx('root')" v-bind="ptm('root')" data-pc-name="calendar"> <input v-if="!inline" :ref="inputRef" :id="inputId" type="text" role="combobox" :class="[cx('input'), inputClass]" :style="inputStyle" :placeholder="placeholder" autocomplete="off" aria-autocomplete="none" aria-haspopup="dialog" :aria-expanded="overlayVisible" :aria-controls="panelId" :aria-labelledby="ariaLabelledby" :aria-label="ariaLabel" inputmode="none" :disabled="disabled" :readonly="!manualInput || readonly" :tabindex="0" @input="onInput" @click="onInputClick" @focus="onFocus" @blur="onBlur" @keydown="onKeyDown" v-bind="{ ...inputProps, ...ptm('input') }" /> <CalendarButton v-if="showIcon" :class="cx('dropdownButton')" :disabled="disabled" @click="onButtonClick" type="button" :aria-label="$primevue.config.locale.chooseDate" aria-haspopup="dialog" :aria-expanded="overlayVisible" :aria-controls="panelId" :unstyled="unstyled" :pt="ptm('dropdownButton')" data-pc-section="dropdownbutton" > <template #icon> <slot name="dropdownicon" :class="icon"> <component :is="icon ? 'span' : 'CalendarIcon'" :class="icon" v-bind="ptm('dropdownButton')['icon']" data-pc-section="dropdownicon" /> </slot> </template> </CalendarButton> <Portal :appendTo="appendTo" :disabled="inline"> <transition name="p-connected-overlay" @enter="onOverlayEnter($event)" @after-enter="onOverlayEnterComplete" @after-leave="onOverlayAfterLeave" @leave="onOverlayLeave" v-bind="ptm('transition')"> <div v-if="inline || overlayVisible" :ref="overlayRef" :id="panelId" :class="[cx('panel'), panelClass]" :style="panelStyle" :role="inline ? null : 'dialog'" :aria-modal="inline ? null : 'true'" :aria-label="$primevue.config.locale.chooseDate" @click="onOverlayClick" @keydown="onOverlayKeyDown" @mouseup="onOverlayMouseUp" v-bind="{ ...panelProps, ...ptm('panel') }" > <template v-if="!timeOnly"> <div :class="cx('groupContainer')" v-bind="ptm('groupContainer')"> <div v-for="(month, groupIndex) of months" :key="month.month + month.year" :class="cx('group')" v-bind="ptm('group')"> <div :class="cx('header')" v-bind="ptm('header')"> <slot name="header"></slot> <button v-show="showOtherMonths ? groupIndex === 0 : false" :ref="previousButtonRef" v-ripple :class="cx('previousButton')" @click="onPrevButtonClick" type="button" @keydown="onContainerButtonKeydown" :disabled="disabled" :aria-label="currentView === 'year' ? $primevue.config.locale.prevDecade : currentView === 'month' ? $primevue.config.locale.prevYear : $primevue.config.locale.prevMonth" v-bind="ptm('previousButton')" data-pc-group-section="navigator" > <slot name="previousicon" :class="cx('previousIcon')"> <component :is="previousIcon ? 'span' : 'ChevronLeftIcon'" :class="[cx('previousIcon'), previousIcon]" v-bind="ptm('previousIcon')" /> </slot> </button> <div :class="cx('title')" v-bind="ptm('title')"> <template v-if="$primevue.config.locale.showMonthAfterYear"> <button v-if="currentView !== 'year'" type="button" @click="switchToYearView" @keydown="onContainerButtonKeydown" :class="cx('yearTitle')" :disabled="switchViewButtonDisabled" :aria-label="$primevue.config.locale.chooseYear" v-bind="ptm('yearTitle')" data-pc-group-section="view" > {{ getYear(month) }} </button> <button v-if="currentView === 'date'" type="button" @click="switchToMonthView" @keydown="onContainerButtonKeydown" :class="cx('monthTitle')" :disabled="switchViewButtonDisabled" :aria-label="$primevue.config.locale.chooseMonth" v-bind="ptm('monthTitle')" data-pc-group-section="view" > {{ getMonthName(month.month) }} </button> </template> <template v-else> <button v-if="currentView === 'date'" type="button" @click="switchToMonthView" @keydown="onContainerButtonKeydown" :class="cx('monthTitle')" :disabled="switchViewButtonDisabled" :aria-label="$primevue.config.locale.chooseMonth" v-bind="ptm('monthTitle')" data-pc-group-section="view" > {{ getMonthName(month.month) }} </button> <button v-if="currentView !== 'year'" type="button" @click="switchToYearView" @keydown="onContainerButtonKeydown" :class="cx('yearTitle')" :disabled="switchViewButtonDisabled" :aria-label="$primevue.config.locale.chooseYear" v-bind="ptm('yearTitle')" data-pc-group-section="view" > {{ getYear(month) }} </button> </template> <span v-if="currentView === 'year'" :class="cx('decadeTitle')" v-bind="ptm('decadeTitle')"> <slot name="decade" :years="yearPickerValues"> {{ yearPickerValues[0].value }} - {{ yearPickerValues[yearPickerValues.length - 1].value }} </slot> </span> </div> <button v-show="showOtherMonths ? (numberOfMonths === 1 ? true : groupIndex === numberOfMonths - 1) : false" :ref="nextButtonRef" v-ripple :class="cx('nextButton')" @click="onNextButtonClick" type="button" @keydown="onContainerButtonKeydown" :disabled="disabled" :aria-label="currentView === 'year' ? $primevue.config.locale.nextDecade : currentView === 'month' ? $primevue.config.locale.nextYear : $primevue.config.locale.nextMonth" v-bind="ptm('nextButton')" data-pc-group-section="navigator" > <slot name="nexticon" :class="cx('nextIcon')"> <component :is="nextIcon ? 'span' : 'ChevronRightIcon'" :class="[cx('nextIcon'), nextIcon]" v-bind="ptm('nextIcon')" /> </slot> </button> </div> <div v-if="currentView === 'date'" :class="cx('container')" v-bind="ptm('container')"> <table :class="cx('table')" role="grid" v-bind="ptm('table')"> <thead v-bind="ptm('tableHeader')"> <tr v-bind="ptm('tableHeaderRow')"> <th v-if="showWeek" scope="col" :class="cx('weekHeader')" v-bind="ptm('weekHeader', { context: { disabled: showWeek } })" :data-p-disabled="showWeek" data-pc-group-section="tableheadercell"> <span v-bind="ptm('weekLabel')" data-pc-group-section="tableheadercelllabel">{{ weekHeaderLabel }}</span> </th> <th v-for="weekDay of weekDays" :key="weekDay" scope="col" :abbr="weekDay" v-bind="ptm('tableHeaderCell')" data-pc-group-section="tableheadercell"> <span v-bind="ptm('weekDay')" data-pc-group-section="tableheadercelllabel">{{ weekDay }}</span> </th> </tr> </thead> <tbody v-bind="ptm('tableBody')"> <tr v-for="(week, i) of month.dates" :key="week[0].day + '' + week[0].month" v-bind="ptm('tableBodyRow')"> <td v-if="showWeek" :class="cx('weekNumber')" v-bind="ptm('weekNumber')" data-pc-group-section="tablebodycell"> <span :class="cx('weekLabelContainer')" v-bind="ptm('weekLabelContainer', { context: { disabled: showWeek } })" :data-p-disabled="showWeek" data-pc-group-section="tablebodycelllabel"> <span v-if="month.weekNumbers[i] < 10" style="visibility: hidden" v-bind="ptm('weekLabel')">0</span> {{ month.weekNumbers[i] }} </span> </td> <td v-for="date of week" :key="date.day + '' + date.month" :aria-label="date.day" :class="cx('day', { date })" v-bind=" ptm('day', { context: { date, today: date.today, otherMonth: date.otherMonth } }) " :data-p-today="date.today" :data-p-other-month="date.otherMonth" data-pc-group-section="tablebodycell" > <span v-ripple :class="cx('dayLabel', { date })" @click="onDateSelect($event, date)" draggable="false" @keydown="onDateCellKeydown($event, date, groupIndex)" :aria-selected="isSelected(date)" :aria-disabled="!date.selectable" v-bind=" ptm('dayLabel', { context: { date, selected: isSelected(date), disabled: !date.selectable } }) " :data-p-disabled="!date.selectable" :data-p-highlight="isSelected(date)" data-pc-group-section="tablebodycelllabel" > <slot name="date" :date="date">{{ date.day }}</slot> </span> <div v-if="isSelected(date)" class="p-hidden-accessible" aria-live="polite" v-bind="ptm('hiddenSelectedDay')" :data-p-hidden-accessible="true"> {{ date.day }} </div> </td> </tr> </tbody> </table> </div> </div> </div> <div v-if="currentView === 'month'" :class="cx('monthPicker')" v-bind="ptm('monthPicker')"> <span v-for="(m, i) of monthPickerValues" :key="m" v-ripple @click="onMonthSelect($event, { month: m, index: i })" @keydown="onMonthCellKeydown($event, { month: m, index: i })" :class="cx('month', { month: m, index: i })" v-bind=" ptm('month', { context: { month: m, monthIndex: i, selected: isMonthSelected(i), disabled: !m.selectable } }) " :data-p-disabled="!m.selectable" :data-p-highlight="isMonthSelected(i)" > {{ m.value }} <div v-if="isMonthSelected(i)" class="p-hidden-accessible" aria-live="polite" v-bind="ptm('hiddenMonth')" :data-p-hidden-accessible="true"> {{ m.value }} </div> </span> </div> <div v-if="currentView === 'year'" :class="cx('yearPicker')" v-bind="ptm('yearPicker')"> <span v-for="y of yearPickerValues" :key="y.value" v-ripple @click="onYearSelect($event, y)" @keydown="onYearCellKeydown($event, y)" :class="cx('year', { year: y })" v-bind=" ptm('year', { context: { year: y, selected: isYearSelected(y.value), disabled: !y.selectable } }) " :data-p-disabled="!y.selectable" :data-p-highlight="isYearSelected(y.value)" > {{ y.value }} <div v-if="isYearSelected(y.value)" class="p-hidden-accessible" aria-live="polite" v-bind="ptm('hiddenYear')" :data-p-hidden-accessible="true"> {{ y.value }} </div> </span> </div> </template> <div v-if="(showTime || timeOnly) && currentView === 'date'" :class="cx('timePicker')" v-bind="ptm('timePicker')"> <div :class="cx('hourPicker')" v-bind="ptm('hourPicker')" data-pc-group-section="timepickerContainer"> <button v-ripple :class="cx('incrementButton')" :aria-label="$primevue.config.locale.nextHour" @mousedown="onTimePickerElementMouseDown($event, 0, 1)" @mouseup="onTimePickerElementMouseUp($event)" @keydown="onContainerButtonKeydown" @mouseleave="onTimePickerElementMouseLeave()" @keydown.enter="onTimePickerElementMouseDown($event, 0, 1)" @keydown.space="onTimePickerElementMouseDown($event, 0, 1)" @keyup.enter="onTimePickerElementMouseUp($event)" @keyup.space="onTimePickerElementMouseUp($event)" type="button" v-bind="ptm('incrementButton')" data-pc-group-section="timepickerbutton" > <slot name="incrementicon"> <component :is="incrementIcon ? 'span' : 'ChevronUpIcon'" :class="incrementIcon" v-bind="ptm('incrementIcon')" data-pc-group-section="timepickerlabel" /> </slot> </button> <span v-bind="ptm('hour')" data-pc-group-section="timepickerlabel">{{ formattedCurrentHour }}</span> <button v-ripple :class="cx('decrementButton')" :aria-label="$primevue.config.locale.prevHour" @mousedown="onTimePickerElementMouseDown($event, 0, -1)" @mouseup="onTimePickerElementMouseUp($event)" @keydown="onContainerButtonKeydown" @mouseleave="onTimePickerElementMouseLeave()" @keydown.enter="onTimePickerElementMouseDown($event, 0, -1)" @keydown.space="onTimePickerElementMouseDown($event, 0, -1)" @keyup.enter="onTimePickerElementMouseUp($event)" @keyup.space="onTimePickerElementMouseUp($event)" type="button" v-bind="ptm('decrementButton')" data-pc-group-section="timepickerbutton" > <slot name="decrementicon"> <component :is="decrementIcon ? 'span' : 'ChevronDownIcon'" :class="decrementIcon" v-bind="ptm('decrementIcon')" data-pc-group-section="timepickerlabel" /> </slot> </button> </div> <div :class="cx('separatorContainer')" v-bind="ptm('separatorContainer')" data-pc-group-section="timepickerContainer"> <span v-bind="ptm('separator')" data-pc-group-section="timepickerlabel">{{ timeSeparator }}</span> </div> <div :class="cx('minutePicker')" v-bind="ptm('minutePicker')" data-pc-group-section="timepickerContainer"> <button v-ripple :class="cx('incrementButton')" :aria-label="$primevue.config.locale.nextMinute" @mousedown="onTimePickerElementMouseDown($event, 1, 1)" @mouseup="onTimePickerElementMouseUp($event)" @keydown="onContainerButtonKeydown" :disabled="disabled" @mouseleave="onTimePickerElementMouseLeave()" @keydown.enter="onTimePickerElementMouseDown($event, 1, 1)" @keydown.space="onTimePickerElementMouseDown($event, 1, 1)" @keyup.enter="onTimePickerElementMouseUp($event)" @keyup.space="onTimePickerElementMouseUp($event)" type="button" v-bind="ptm('incrementButton')" data-pc-group-section="timepickerbutton" > <slot name="incrementicon"> <component :is="incrementIcon ? 'span' : 'ChevronUpIcon'" :class="incrementIcon" v-bind="ptm('incrementIcon')" data-pc-group-section="timepickerlabel" /> </slot> </button> <span v-bind="ptm('minute')" data-pc-group-section="timepickerlabel">{{ formattedCurrentMinute }}</span> <button v-ripple :class="cx('decrementButton')" :aria-label="$primevue.config.locale.prevMinute" @mousedown="onTimePickerElementMouseDown($event, 1, -1)" @mouseup="onTimePickerElementMouseUp($event)" @keydown="onContainerButtonKeydown" :disabled="disabled" @mouseleave="onTimePickerElementMouseLeave()" @keydown.enter="onTimePickerElementMouseDown($event, 1, -1)" @keydown.space="onTimePickerElementMouseDown($event, 1, -1)" @keyup.enter="onTimePickerElementMouseUp($event)" @keyup.space="onTimePickerElementMouseUp($event)" type="button" v-bind="ptm('decrementButton')" data-pc-group-section="timepickerbutton" > <slot name="decrementicon"> <component :is="decrementIcon ? 'span' : 'ChevronDownIcon'" :class="decrementIcon" v-bind="ptm('decrementIcon')" data-pc-group-section="timepickerlabel" /> </slot> </button> </div> <div v-if="showSeconds" :class="cx('separatorContainer')" v-bind="ptm('separatorContainer')" data-pc-group-section="timepickerContainer"> <span v-bind="ptm('separator')" data-pc-group-section="timepickerlabel">{{ timeSeparator }}</span> </div> <div v-if="showSeconds" :class="cx('secondPicker')" v-bind="ptm('secondPicker')" data-pc-group-section="timepickerContainer"> <button v-ripple :class="cx('incrementButton')" :aria-label="$primevue.config.locale.nextSecond" @mousedown="onTimePickerElementMouseDown($event, 2, 1)" @mouseup="onTimePickerElementMouseUp($event)" @keydown="onContainerButtonKeydown" :disabled="disabled" @mouseleave="onTimePickerElementMouseLeave()" @keydown.enter="onTimePickerElementMouseDown($event, 2, 1)" @keydown.space="onTimePickerElementMouseDown($event, 2, 1)" @keyup.enter="onTimePickerElementMouseUp($event)" @keyup.space="onTimePickerElementMouseUp($event)" type="button" v-bind="ptm('incrementButton')" data-pc-group-section="timepickerbutton" > <slot name="incrementicon"> <component :is="incrementIcon ? 'span' : 'ChevronUpIcon'" :class="incrementIcon" v-bind="ptm('incrementIcon')" data-pc-group-section="timepickerlabel" /> </slot> </button> <span v-bind="ptm('second')" data-pc-group-section="timepickerlabel">{{ formattedCurrentSecond }}</span> <button v-ripple :class="cx('decrementButton')" :aria-label="$primevue.config.locale.prevSecond" @mousedown="onTimePickerElementMouseDown($event, 2, -1)" @mouseup="onTimePickerElementMouseUp($event)" @keydown="onContainerButtonKeydown" :disabled="disabled" @mouseleave="onTimePickerElementMouseLeave()" @keydown.enter="onTimePickerElementMouseDown($event, 2, -1)" @keydown.space="onTimePickerElementMouseDown($event, 2, -1)" @keyup.enter="onTimePickerElementMouseUp($event)" @keyup.space="onTimePickerElementMouseUp($event)" type="button" v-bind="ptm('decrementButton')" data-pc-group-section="timepickerbutton" > <slot name="decrementicon"> <component :is="decrementIcon ? 'span' : 'ChevronDownIcon'" :class="decrementIcon" v-bind="ptm('decrementIcon')" data-pc-group-section="timepickerlabel" /> </slot> </button> </div> <div v-if="hourFormat == '12'" :class="cx('separatorContainer')" v-bind="ptm('separatorContainer')" data-pc-group-section="timepickerContainer"> <span v-bind="ptm('separator')" data-pc-group-section="timepickerlabel">{{ timeSeparator }}</span> </div> <div v-if="hourFormat == '12'" :class="cx('ampmPicker')" v-bind="ptm('ampmPicker')"> <button v-ripple :class="cx('incrementButton')" :aria-label="$primevue.config.locale.am" @click="toggleAMPM($event)" @keydown="onContainerButtonKeydown" type="button" :disabled="disabled" v-bind="ptm('incrementButton')" data-pc-group-section="timepickerbutton" > <slot name="incrementicon" :class="cx('incrementIcon')"> <component :is="incrementIcon ? 'span' : 'ChevronUpIcon'" :class="cx('incrementIcon')" v-bind="ptm('incrementIcon')" data-pc-group-section="timepickerlabel" /> </slot> </button> <span v-bind="ptm('ampm')" data-pc-group-section="timepickerlabel">{{ pm ? $primevue.config.locale.pm : $primevue.config.locale.am }}</span> <button v-ripple :class="cx('decrementButton')" :aria-label="$primevue.config.locale.pm" @click="toggleAMPM($event)" @keydown="onContainerButtonKeydown" type="button" :disabled="disabled" v-bind="ptm('decrementButton')" data-pc-group-section="timepickerbutton" > <slot name="decrementicon" :class="cx('decrementIcon')"> <component :is="decrementIcon ? 'span' : 'ChevronDownIcon'" :class="cx('decrementIcon')" v-bind="ptm('decrementIcon')" data-pc-group-section="timepickerlabel" /> </slot> </button> </div> </div> <div v-if="showButtonBar" :class="cx('buttonbar')" v-bind="ptm('buttonbar')"> <CalendarButton type="button" :label="todayLabel" @click="onTodayButtonClick($event)" :class="cx('todayButton')" @keydown="onContainerButtonKeydown" :unstyled="unstyled" :pt="ptm('todayButton')" data-pc-section="todaybutton" data-pc-group-section="button" /> <CalendarButton type="button" :label="clearLabel" @click="onClearButtonClick($event)" :class="cx('clearButton')" @keydown="onContainerButtonKeydown" :unstyled="unstyled" :pt="ptm('clearButton')" data-pc-section="clearbutton" data-pc-group-section="button" /> </div> <slot name="footer"></slot> </div> </transition> </Portal> </span> </template> <script> import Button from 'primevue/button'; import CalendarIcon from 'primevue/icons/calendar'; import ChevronDownIcon from 'primevue/icons/chevrondown'; import ChevronLeftIcon from 'primevue/icons/chevronleft'; import ChevronRightIcon from 'primevue/icons/chevronright'; import ChevronUpIcon from 'primevue/icons/chevronup'; import OverlayEventBus from 'primevue/overlayeventbus'; import Portal from 'primevue/portal'; import Ripple from 'primevue/ripple'; import { ConnectedOverlayScrollHandler, DomHandler, UniqueComponentId, ZIndexUtils } from 'primevue/utils'; import BaseCalendar from './BaseCalendar.vue'; export default { name: 'Calendar', extends: BaseCalendar, emits: ['show', 'hide', 'input', 'month-change', 'year-change', 'date-select', 'update:modelValue', 'today-click', 'clear-click', 'focus', 'blur', 'keydown'], navigationState: null, timePickerChange: false, scrollHandler: null, outsideClickListener: null, maskClickListener: null, resizeListener: null, overlay: null, input: null, mask: null, previousButton: null, nextButton: null, timePickerTimer: null, preventFocus: false, typeUpdate: false, data() { return { currentMonth: null, currentYear: null, currentHour: null, currentMinute: null, currentSecond: null, pm: null, focused: false, overlayVisible: false, currentView: this.view }; }, watch: { modelValue(newValue) { this.updateCurrentMetaData(); if (!this.typeUpdate && !this.inline && this.input) { this.input.value = this.formatValue(newValue); } this.typeUpdate = false; }, showTime() { this.updateCurrentMetaData(); }, months() { if (this.overlay) { if (!this.focused) { if (this.inline) { this.preventFocus = true; } setTimeout(this.updateFocus, 0); } } }, numberOfMonths() { this.destroyResponsiveStyleElement(); this.createResponsiveStyle(); }, responsiveOptions() { this.destroyResponsiveStyleElement(); this.createResponsiveStyle(); }, currentView() { Promise.resolve(null).then(() => this.alignOverlay()); } }, created() { this.updateCurrentMetaData(); }, mounted() { this.createResponsiveStyle(); if (this.inline) { this.overlay && this.overlay.setAttribute(this.attributeSelector, ''); if (!this.disabled) { this.preventFocus = true; this.initFocusableCell(); if (this.numberOfMonths === 1) { this.overlay.style.width = DomHandler.getOuterWidth(this.$el) + 'px'; } } } else { this.input.value = this.formatValue(this.modelValue); } }, updated() { if (this.overlay) { this.preventFocus = true; setTimeout(this.updateFocus, 0); } if (this.input && this.selectionStart != null && this.selectionEnd != null) { this.input.selectionStart = this.selectionStart; this.input.selectionEnd = this.selectionEnd; this.selectionStart = null; this.selectionEnd = null; } }, beforeUnmount() { if (this.timePickerTimer) { clearTimeout(this.timePickerTimer); } if (this.mask) { this.destroyMask(); } this.destroyResponsiveStyleElement(); this.unbindOutsideClickListener(); this.unbindResizeListener(); if (this.scrollHandler) { this.scrollHandler.destroy(); this.scrollHandler = null; } if (this.overlay && this.autoZIndex) { ZIndexUtils.clear(this.overlay); } this.overlay = null; }, methods: { isComparable() { return this.modelValue != null && typeof this.modelValue !== 'string'; }, isSelected(dateMeta) { if (!this.isComparable()) { return false; } if (this.modelValue) { if (this.isSingleSelection()) { return this.isDateEquals(this.modelValue, dateMeta); } else if (this.isMultipleSelection()) { let selected = false; for (let date of this.modelValue) { selected = this.isDateEquals(date, dateMeta); if (selected) { break; } } return selected; } else if (this.isRangeSelection()) { if (this.modelValue[1]) return this.isDateEquals(this.modelValue[0], dateMeta) || this.isDateEquals(this.modelValue[1], dateMeta) || this.isDateBetween(this.modelValue[0], this.modelValue[1], dateMeta); else { return this.isDateEquals(this.modelValue[0], dateMeta); } } } return false; }, isMonthSelected(month) { if (this.isComparable()) { let value = this.isRangeSelection() ? this.modelValue[0] : this.modelValue; if (this.isMultipleSelection()) { return value.some((currentValue) => currentValue.getMonth() === month && currentValue.getFullYear() === this.currentYear); } else { return value.getMonth() === month && value.getFullYear() === this.currentYear; } } return false; }, isYearSelected(year) { if (this.isComparable()) { let value = this.isRangeSelection() ? this.modelValue[0] : this.modelValue; if (this.isMultipleSelection()) { return value.some((currentValue) => currentValue.getFullYear() === year); } else { return value.getFullYear() === year; } } return false; }, isDateEquals(value, dateMeta) { if (value) return value.getDate() === dateMeta.day && value.getMonth() === dateMeta.month && value.getFullYear() === dateMeta.year; else return false; }, isDateBetween(start, end, dateMeta) { let between = false; if (start && end) { let date = new Date(dateMeta.year, dateMeta.month, dateMeta.day); return start.getTime() <= date.getTime() && end.getTime() >= date.getTime(); } return between; }, getFirstDayOfMonthIndex(month, year) { let day = new Date(); day.setDate(1); day.setMonth(month); day.setFullYear(year); let dayIndex = day.getDay() + this.sundayIndex; return dayIndex >= 7 ? dayIndex - 7 : dayIndex; }, getDaysCountInMonth(month, year) { return 32 - this.daylightSavingAdjust(new Date(year, month, 32)).getDate(); }, getDaysCountInPrevMonth(month, year) { let prev = this.getPreviousMonthAndYear(month, year); return this.getDaysCountInMonth(prev.month, prev.year); }, getPreviousMonthAndYear(month, year) { let m, y; if (month === 0) { m = 11; y = year - 1; } else { m = month - 1; y = year; } return { month: m, year: y }; }, getNextMonthAndYear(month, year) { let m, y; if (month === 11) { m = 0; y = year + 1; } else { m = month + 1; y = year; } return { month: m, year: y }; }, daylightSavingAdjust(date) { if (!date) { return null; } date.setHours(date.getHours() > 12 ? date.getHours() + 2 : 0); return date; }, isToday(today, day, month, year) { return today.getDate() === day && today.getMonth() === month && today.getFullYear() === year; }, isSelectable(day, month, year, otherMonth) { let validMin = true; let validMax = true; let validDate = true; let validDay = true; if (otherMonth && !this.selectOtherMonths) { return false; } if (this.minDate) { if (this.minDate.getFullYear() > year) { validMin = false; } else if (this.minDate.getFullYear() === year) { if (this.minDate.getMonth() > month) { validMin = false; } else if (this.minDate.getMonth() === month) { if (this.minDate.getDate() > day) { validMin = false; } } } } if (this.maxDate) { if (this.maxDate.getFullYear() < year) { validMax = false; } else if (this.maxDate.getFullYear() === year) { if (this.maxDate.getMonth() < month) { validMax = false; } else if (this.maxDate.getMonth() === month) { if (this.maxDate.getDate() < day) { validMax = false; } } } } if (this.disabledDates) { validDate = !this.isDateDisabled(day, month, year); } if (this.disabledDays) { validDay = !this.isDayDisabled(day, month, year); } return validMin && validMax && validDate && validDay; }, onOverlayEnter(el) { el.setAttribute(this.attributeSelector, ''); const styles = this.touchUI ? { position: 'fixed', top: '50%', left: '50%', transform: 'translate(-50%, -50%)' } : !this.inline ? { position: 'absolute', top: '0', left: '0' } : undefined; DomHandler.addStyles(el, styles); if (this.autoZIndex) { if (this.touchUI) ZIndexUtils.set('modal', el, this.baseZIndex || this.$primevue.config.zIndex.modal); else ZIndexUtils.set('overlay', el, this.baseZIndex || this.$primevue.config.zIndex.overlay); } this.alignOverlay(); this.$emit('show'); }, onOverlayEnterComplete() { this.bindOutsideClickListener(); this.bindScrollListener(); this.bindResizeListener(); }, onOverlayAfterLeave(el) { if (this.autoZIndex) { ZIndexUtils.clear(el); } }, onOverlayLeave() { this.currentView = this.view; this.unbindOutsideClickListener(); this.unbindScrollListener(); this.unbindResizeListener(); this.$emit('hide'); if (this.mask) { this.disableModality(); } this.overlay = null; }, onPrevButtonClick(event) { if (this.showOtherMonths) { this.navigationState = { backward: true, button: true }; this.navBackward(event); } }, onNextButtonClick(event) { if (this.showOtherMonths) { this.navigationState = { backward: false, button: true }; this.navForward(event); } }, navBackward(event) { event.preventDefault(); if (!this.isEnabled()) { return; } if (this.currentView === 'month') { this.decrementYear(); this.$emit('year-change', { month: this.currentMonth, year: this.currentYear }); } else if (this.currentView === 'year') { this.decrementDecade(); } else { if (event.shiftKey) { this.decrementYear(); } else { if (this.currentMonth === 0) { this.currentMonth = 11; this.decrementYear(); } else { this.currentMonth--; } this.$emit('month-change', { month: this.currentMonth + 1, year: this.currentYear }); } } }, navForward(event) { event.preventDefault(); if (!this.isEnabled()) { return; } if (this.currentView === 'month') { this.incrementYear(); this.$emit('year-change', { month: this.currentMonth, year: this.currentYear }); } else if (this.currentView === 'year') { this.incrementDecade(); } else { if (event.shiftKey) { this.incrementYear(); } else { if (this.currentMonth === 11) { this.currentMonth = 0; this.incrementYear(); } else { this.currentMonth++; } this.$emit('month-change', { month: this.currentMonth + 1, year: this.currentYear }); } } }, decrementYear() { this.currentYear--; }, decrementDecade() { this.currentYear = this.currentYear - 10; }, incrementYear() { this.currentYear++; }, incrementDecade() { this.currentYear = this.currentYear + 10; }, switchToMonthView(event) { this.currentView = 'month'; setTimeout(this.updateFocus, 0); event.preventDefault(); }, switchToYearView(event) { this.currentView = 'year'; setTimeout(this.updateFocus, 0); event.preventDefault(); }, isEnabled() { return !this.disabled && !this.readonly; }, updateCurrentTimeMeta(date) { let currentHour = date.getHours(); if (this.hourFormat === '12') { this.pm = currentHour > 11; if (currentHour >= 12) currentHour = currentHour == 12 ? 12 : currentHour - 12; else currentHour = currentHour == 0 ? 12 : currentHour; } this.currentHour = Math.floor(currentHour / this.stepHour) * this.stepHour; this.currentMinute = Math.floor(date.getMinutes() / this.stepMinute) * this.stepMinute; this.currentSecond = Math.floor(date.getSeconds() / this.stepSecond) * this.stepSecond; }, bindOutsideClickListener() { if (!this.outsideClickListener) { this.outsideClickListener = (event) => { if (this.overlayVisible && this.isOutsideClicked(event)) { this.overlayVisible = false; } }; document.addEventListener('mousedown', this.outsideClickListener); } }, unbindOutsideClickListener() { if (this.outsideClickListener) { document.removeEventListener('mousedown', this.outsideClickListener); this.outsideClickListener = null; } }, bindScrollListener() { if (!this.scrollHandler) { this.scrollHandler = new ConnectedOverlayScrollHandler(this.$refs.container, () => { if (this.overlayVisible) { this.overlayVisible = false; } }); } this.scrollHandler.bindScrollListener(); }, unbindScrollListener() { if (this.scrollHandler) { this.scrollHandler.unbindScrollListener(); } }, bindResizeListener() { if (!this.resizeListener) { this.resizeListener = () => { if (this.overlayVisible && !DomHandler.isTouchDevice()) { this.overlayVisible = false; } }; window.addEventListener('resize', this.resizeListener); } }, unbindResizeListener() { if (this.resizeListener) { window.removeEventListener('resize', this.resizeListener); this.resizeListener = null; } }, isOutsideClicked(event) { return !(this.$el.isSameNode(event.target) || this.isNavIconClicked(event) || this.$el.contains(event.target) || (this.overlay && this.overlay.contains(event.target))); }, isNavIconClicked(event) { return (this.previousButton && (this.previousButton.isSameNode(event.target) || this.previousButton.contains(event.target))) || (this.nextButton && (this.nextButton.isSameNode(event.target) || this.nextButton.contains(event.target))); }, alignOverlay() { if (this.touchUI) { this.enableModality(); } else if (this.overlay) { if (this.appendTo === 'self' || this.inline) { DomHandler.relativePosition(this.overlay, this.$el); } else { if (this.view === 'date') { this.overlay.style.width = DomHandler.getOuterWidth(this.overlay) + 'px'; this.overlay.style.minWidth = DomHandler.getOuterWidth(this.$el) + 'px'; } else { this.overlay.style.width = DomHandler.getOuterWidth(this.$el) + 'px'; } DomHandler.absolutePosition(this.overlay, this.$el); } } }, onButtonClick() { if (this.isEnabled()) { if (!this.overlayVisible) { this.input.focus(); this.overlayVisible = true; } else { this.overlayVisible = false; } } }, isDateDisabled(day, month, year) { if (this.disabledDates) { for (let disabledDate of this.disabledDates) { if (disabledDate.getFullYear() === year && disabledDate.getMonth() === month && disabledDate.getDate() === day) { return true; } } } return false; }, isDayDisabled(day, month, year) { if (this.disabledDays) { let weekday = new Date(year, month, day); let weekdayNumber = weekday.getDay(); return this.disabledDays.indexOf(weekdayNumber) !== -1; } return false; }, onMonthDropdownChange(value) { this.currentMonth = parseInt(value); this.$emit('month-change', { month: this.currentMonth + 1, year: this.currentYear }); }, onYearDropdownChange(value) { this.currentYear = parseInt(value); this.$emit('year-change', { month: this.currentMonth + 1, year: this.currentYear }); }, onDateSelect(event, dateMeta) { if (this.disabled || !dateMeta.selectable) { return; } DomHandler.find(this.overlay, 'table td span:not([data-p-disabled="true"])').forEach((cell) => (cell.tabIndex = -1)); if (event) { event.currentTarget.focus(); } if (this.isMultipleSelection() && this.isSelected(dateMeta)) { let newValue = this.modelValue.filter((date) => !this.isDateEquals(date, dateMeta)); this.updateModel(newValue); } else { if (this.shouldSelectDate(dateMeta)) { if (dateMeta.otherMonth) { this.currentMonth = dateMeta.month; this.currentYear = dateMeta.year; this.selectDate(dateMeta); } else { this.selectDate(dateMeta); } } } if (this.isSingleSelection() && (!this.showTime || this.hideOnDateTimeSelect)) { setTimeout(() => { if (this.input) { this.input.focus(); } this.overlayVisible = false; }, 150); } }, selectDate(dateMeta) { let date = new Date(dateMeta.year, dateMeta.month, dateMeta.day); if (this.showTime) { if (this.hourFormat === '12' && this.pm && this.currentHour != 12) date.setHours(this.currentHour + 12); else date.setHours(this.currentHour); date.setMinutes(this.currentMinute); date.setSeconds(this.currentSecond); } if (this.minDate && this.minDate > date) { date = this.minDate; this.currentHour = date.getHours(); this.currentMinute = date.getMinutes(); this.currentSecond = date.getSeconds(); } if (this.maxDate && this.maxDate < date) { date = this.maxDate; this.currentHour = date.getHours(); this.currentMinute = date.getMinutes(); this.currentSecond = date.getSeconds(); } let modelVal = null; if (this.isSingleSelection()) { modelVal = date; } else if (this.isMultipleSelection()) { modelVal = this.modelValue ? [...this.modelValue, date] : [date]; } else if (this.isRangeSelection()) { if (this.modelValue && this.modelValue.length) { let startDate = this.modelValue[0]; let endDate = this.modelValue[1]; if (!endDate && date.getTime() >= startDate.getTime()) { endDate = date; } else { startDate = date; endDate = null; } modelVal = [startDate, endDate]; } else { modelVal = [date, null]; } } if (modelVal !== null) { this.updateModel(modelVal); } if (this.isRangeSelection() && this.hideOnRangeSelection && modelVal[1] !== null) { setTimeout(() => { this.overlayVisible = false; }, 150); } this.$emit('date-select', date); }, updateModel(value) { this.$emit('update:modelValue', value); }, shouldSelectDate() { if (this.isMultipleSelection()) return this.maxDateCount != null ? this.maxDateCount > (this.modelValue ? this.modelValue.length : 0) : true; else return true; }, isSingleSelection() { return this.selectionMode === 'single'; }, isRangeSelection() { return this.selectionMode === 'range'; }, isMultipleSelection() { return this.selectionMode === 'multiple'; }, formatValue(value) { if (typeof value === 'string') { return value; } let formattedValue = ''; if (value) { try { if (this.isSingleSelection()) { formattedValue = this.formatDateTime(value); } else if (this.isMultipleSelection()) { for (let i = 0; i < value.length; i++) { let dateAsString = this.formatDateTime(value[i]); formattedValue += dateAsString; if (i !== value.length - 1) { formattedValue += ', '; } } } else if (this.isRangeSelection()) { if (value && value.length) { let startDate = value[0]; let endDate = value[1]; formattedValue = this.formatDateTime(startDate); if (endDate) { formattedValue += ' - ' + this.formatDateTime(endDate); } } } } catch (err) { formattedValue = value; } } return formattedValue; }, formatDateTime(date) { let formattedValue = null; if (date) { if (this.timeOnly) { formattedValue = this.formatTime(date); } else { formattedValue = this.formatDate(date, this.datePattern); if (this.showTime) { formattedValue += ' ' + this.formatTime(date); } } } return formattedValue; }, formatDate(date, format) { if (!date) { return ''; } let iFormat; const lookAhead = (match) => { const matches = iFormat + 1 < format.length && format.charAt(iFormat + 1) === match; if (matches) { iFormat++; } return matches; }, formatNumber = (match, value, len) => { let num = '' + value; if (lookAhead(match)) { while (num.length < len) { num = '0' + num; } } return num; }, formatName = (match, value, shortNames, longNames) => { return lookAhead(match) ? longNames[value] : shortNames[value]; }; let output = ''; let literal = false; if (date) { for (iFormat = 0; iFormat < format.length; iFormat++) { if (literal) { if (format.charAt(iFormat) === "'" && !lookAhead("'")) { literal = false; } else { output += format.charAt(iFormat); } } else { switch (format.charAt(iFormat)) { case 'd': output += formatNumber('d', date.getDate(), 2); break; case 'D': output += formatName('D', date.getDay(), this.$primevue.config.locale.dayNamesShort, this.$primevue.config.locale.dayNames); break; case 'o': output += formatNumber('o', Math.round((new Date(date.getFullYear(), date.getMonth(), date.getDate()).getTime() - new Date(date.getFullYear(), 0, 0).getTime()) / 86400000), 3); break; case 'm': output += formatNumber('m', date.getMonth() + 1, 2); break; case 'M': output += formatName('M', date.getMonth(), this.$primevue.config.locale.monthNamesShort, this.$primevue.config.locale.monthNames); break; case 'y': output += lookAhead('y') ? date.getFullYear() : (date.getFullYear() % 100 < 10 ? '0' : '') + (date.getFullYear() % 100); break; case '@': output += date.getTime(); break; case '!': output += date.getTime() * 10000 + this.ticksTo1970; break; case "'": if (lookAhead("'")) { output += "'"; } else { literal = true; } break; default: output += format.charAt(iFormat); } } } } return output; }, formatTime(date) { if (!date) { return ''; } let output = ''; let hours = date.getHours(); let minutes = date.getMinutes(); let seconds = date.getSeconds(); if (this.hourFormat === '12' && hours > 11 && hours !== 12) { hours -= 12; } if (this.hourFormat === '12') { output += hours === 0 ? 12 : hours < 10 ? '0' + hours : hours; } else { output += hours < 10 ? '0' + hours : hours; } output += ':'; output += minutes < 10 ? '0' + minutes : minutes; if (this.showSeconds) { output += ':'; output += seconds < 10 ? '0' + seconds : seconds; } if (this.hourFormat === '12') { output += date.getHours() > 11 ? ` ${this.$primevue.config.locale.pm}` : ` ${this.$primevue.config.locale.am}`; } return output; }, onTodayButtonClick(event) { let date = new Date(); let dateMeta = { day: date.getDate(), month: date.getMonth(), year: date.getFullYear(), otherMonth: date.getMonth() !== this.currentMonth || date.getFullYear() !== this.currentYear, today: true, selectable: true }; this.onDateSelect(null, dateMeta); this.$emit('today-click', date); event.preventDefault(); }, onClearButtonClick(event) { this.updateModel(null); this.overlayVisible = false; this.$emit('clear-click', event); event.preventDefault(); }, onTimePickerElementMouseDown(event, type, direction) { if (this.isEnabled()) { this.repeat(event, null, type, direction); event.preventDefault(); } }, onTimePickerElementMouseUp(event) { if (this.isEnabled()) { this.clearTimePickerTimer(); this.updateModelTime(); event.preventDefault(); } }, onTimePickerElementMouseLeave() { this.clearTimePickerTimer(); }, repeat(event, interval, type, direction) { let i = interval || 500; this.clearTimePickerTimer(); this.timePickerTimer = setTimeout(() => { this.repeat(event, 100, type, direction); }, i); switch (type) { case 0: if (direction === 1) this.incrementHour(event); else this.decrementHour(event); break; case 1: if (direction === 1) this.incrementMinute(event); else this.decrementMinute(event); break; case 2: if (direction === 1) this.incrementSecond(event); else this.decrementSecond(event); break; } }, convertTo24Hour(hours, pm) { if (this.hourFormat == '12') { if (hours === 12) { return pm ? 12 : 0; } else { return pm ? hours + 12 : hours; } } return hours; }, validateTime(hour, minute, second, pm) { let value = this.isComparable() ? this.modelValue : this.viewDate; const convertedHour = this.convertTo24Hour(hour, pm); if (this.isRangeSelection()) { value = this.modelValue[1] || this.modelValue[0]; } if (this.isMultipleSelection()) { value = this.modelValue[this.modelValue.length - 1]; } const valueDateString = value ? value.toDateString() : null; if (this.minDate && valueDateString && this.minDate.toDateString() === valueDateString) { if (this.minDate.getHours() > convertedHour) { return false; } if (this.minDate.getHours() === convertedHour) { if (this.minDate.getMinutes() > minute) { return false; } if (this.minDate.getMinutes() === minute) { if (this.minDate.getSeconds() > second) { return false; } } } } if (this.maxDate && valueDateString && this.maxDate.toDateString() === valueDateString) { if (this.maxDate.getHours() < convertedHour) { return false; } if (this.maxDate.getHours() === convertedHour) { if (this.maxDate.getMinutes() < minute) { return false; } if (this.maxDate.getMinutes() === minute) { if (this.maxDate.getSeconds() < second) { return false; } } } } return true; }, incrementHour(event) { let prevHour = this.currentHour; let newHour = this.currentHour + Number(this.stepHour); let newPM = this.pm; if (this.hourFormat == '24') newHour = newHour >= 24 ? newHour - 24 : newHour; else if (this.hourFormat == '12') { // Before the AM/PM break, now after if (prevHour < 12 && newHour > 11) { newPM = !this.pm; } newHour = newHour >= 13 ? newHour - 12 : newHour; } if (this.validateTime(newHour, this.currentMinute, this.currentSecond, newPM)) { this.currentHour = newHour; this.pm = newPM; } event.preventDefault(); }, decrementHour(event) { let newHour = this.currentHour - this.stepHour; let newPM = this.pm; if (this.hourFormat == '24') newHour = newHour < 0 ? 24 + newHour : newHour; else if (this.hourFormat == '12') { // If we were at noon/midnight, then switch if (this.currentHour === 12) { newPM = !this.pm; } newHour = newHour <= 0 ? 12 + newHour : newHour; } if (this.validateTime(newHour, this.currentMinute, this.currentSecond, newPM)) { this.currentHour = newHour; this.pm = newPM; } event.preventDefault(); }, incrementMinute(event) { let newMinute = this.currentMinute + Number(this.stepMinute); if (this.validateTime(this.currentHour, newMinute, this.currentSecond, this.pm)) { this.currentMinute = newMinute > 59 ? newMinute - 60 : newMinute; } event.preventDefault(); }, decrementMinute(event) { let newMinute = this.currentMinute - this.stepMinute; newMinute = newMinute < 0 ? 60 + newMinute : newMinute; if (this.validateTime(this.currentHour, newMinute, this.currentSecond, this.pm)) { this.currentMinute = newMinute; } event.preventDefault(); }, incrementSecond(event) { let newSecond = this.currentSecond + Number(this.stepSecond); if (this.validateTime(this.currentHour, this.currentMinute, newSecond, this.pm)) { this.currentSecond = newSecond > 59 ? newSecond - 60 : newSecond; } event.preventDefault(); }, decrementSecond(event) { let newSecond = this.currentSecond - this.stepSecond; newSecond = newSecond < 0 ? 60 + newSecond : newSecond; if (this.validateTime(this.currentHour, this.currentMinute, newSecond, this.pm)) { this.currentSecond = newSecond; } event.preventDefault(); }, updateModelTime() { this.timePickerChange = true; let value = this.isComparable() ? this.modelValue : this.viewDate; if (this.isRangeSelection()) { value = this.modelValue[1] || this.modelValue[0]; } if (this.isMultipleSelection()) { value = this.modelValue[this.modelValue.length - 1]; } value = value ? new Date(value.getTime()) : new Date(); if (this.hourFormat == '12') { if (this.currentHour === 12) value.setHours(this.pm ? 12 : 0); else value.setHours(this.pm ? this.currentHour + 12 : this.currentHour); } else { value.setHours(this.currentHour); } value.setMinutes(this.currentMinute); value.setSeconds(this.currentSecond); if (this.isRangeSelection()) { if (this.modelValue[1]) value = [this.modelValue[0], value]; else value = [value, null]; } if (this.isMultipleSelection()) { value = [...this.modelValue.slice(0, -1), value]; } this.updateModel(value); this.$emit('date-select', value); setTimeout(() => (this.timePickerChange = false), 0); }, toggleAMPM(event) { const validHour = this.validateTime(this.currentHour, this.currentMinute, this.currentSecond, !this.pm); if (!validHour && (this.maxDate || this.minDate)) return; this.pm = !this.pm; this.updateModelTime(); event.preventDefault(); }, clearTimePickerTimer() { if (this.timePickerTimer) { clearInterval(this.timePickerTimer); } }, onMonthSelect(event, { month, index }) { if (this.view === 'month') { this.onDateSelect(event, { year: this.currentYear, month: index, day: 1, selectable: true }); } else { this.currentMonth = index; this.currentView = 'date'; this.$emit('month-change', { month: this.currentMonth + 1, year: this.currentYear }); } setTimeout(this.updateFocus, 0); }, onYearSelect(event, year) { if (this.view === 'year') { this.onDateSelect(event, { year: year.value, month: 0, day: 1, selectable: true }); } else { this.currentYear = year.value; this.currentView = 'month'; this.$emit('year-change', { month: this.currentMonth + 1, year: this.currentYear }); } setTimeout(this.updateFocus, 0); }, enableModality() { if (!this.mask) { this.mask = document.createElement('div'); this.mask.style.zIndex = String(parseInt(this.overlay.style.zIndex, 10) - 1); this.mask.setAttribute('data-pc-section', 'datepicker-mask'); !this.isUnstyled && DomHandler.addMultipleClasses(this.mask, 'p-datepicker-mask p-datepicker-mask-scrollblocker p-component-overlay p-component-overlay-enter'); this.maskClickListener = () => { this.overlayVisible = false; }; this.mask.addEventListener('click', this.maskClickListener); document.body.appendChild(this.mask); DomHandler.blockBodyScroll(); } }, disableModality() { if (this.mask) { if (this.isUnstyled) { this.destroyMask(); } else { DomHandler.addClass(this.mask, 'p-component-overlay-leave'); this.mask.addEventListener('animationend', () => { this.destroyMask(); }); } } }, destroyMask() { this.mask.removeEventListener('click', this.maskClickListener); this.maskClickListener = null; document.body.removeChild(this.mask); this.mask = null; let bodyChildren = document.body.children; let hasBlockerMasks; for (let i = 0; i < bodyChildren.length; i++) { let bodyChild = bodyChildren[i]; if (DomHandler.isAttributeEquals(bodyChild, 'data-pc-section', 'datepicker-mask')) { hasBlockerMasks = true; break; } } if (!hasBlockerMasks) { DomHandler.unblockBodyScroll(); } }, updateCurrentMetaData() { const viewDate = this.viewDate; this.currentMonth = viewDate.getMonth(); this.currentYear = viewDate.getFullYear(); if (this.showTime || this.timeOnly) { this.updateCurrentTimeMeta(viewDate); } }, isValidSelection(value) { if (value == null) { return true; } let isValid = true; if (this.isSingleSelection()) { if (!this.isSelectable(value.getDate(), value.getMonth(), value.getFullYear(), false)) { isValid = false; } } else if (value.every((v) => this.isSelectable(v.getDate(), v.getMonth(), v.getFullYear(), false))) { if (this.isRangeSelection()) { isValid = value.length > 1 && value[1] > value[0] ? true : false; } } return isValid; }, parseValue(text) { if (!text || text.trim().length === 0) { return null; } let value; if (this.isSingleSelection()) { value = this.parseDateTime(text); } else if (this.isMultipleSelection()) { let tokens = text.split(','); value = []; for (let token of tokens) { value.push(this.parseDateTime(token.trim())); } } else if (this.isRangeSelection()) { let tokens = text.split(' - '); value = []; for (let i = 0; i < tokens.length; i++) { value[i] = this.parseDateTime(tokens[i].trim()); } } return value; }, parseDateTime(text) { let date; let parts = text.split(' '); if (this.timeOnly) { date = new Date(); this.populateTime(date, parts[0], parts[1]); } else { const dateFormat = this.datePattern; if (this.showTime) { date = this.parseDate(parts[0], dateFormat); this.populateTime(date, parts[1], parts[2]); } else { date = this.parseDate(text, dateFormat); } } return date; }, populateTime(value, timeString, ampm) { if (this.hourFormat == '12' && !ampm) { throw 'Invalid Time'; } this.pm = ampm === this.$primevue.config.locale.pm || ampm === this.$primevue.config.locale.pm.toLowerCase(); let time = this.parseTime(timeString); value.setHours(time.hour); value.setMinutes(time.minute); value.setSeconds(time.second); }, parseTime(value) { let tokens = value.split(':'); let validTokenLength = this.showSeconds ? 3 : 2; let regex = /^[0-9][0-9]$/; if (tokens.length !== validTokenLength || !tokens[0].match(regex) || !tokens[1].match(regex) || (this.showSeconds && !tokens[2].match(regex))) { throw 'Invalid time'; } let h = parseInt(tokens[0]); let m = parseInt(tokens[1]); let s = this.showSeconds ? parseInt(tokens[2]) : null; if (isNaN(h) || isNaN(m) || h > 23 || m > 59 || (this.hourFormat == '12' && h > 12) || (this.showSeconds && (isNaN(s) || s > 59))) { throw 'Invalid time'; } else { if (this.hourFormat == '12' && h !== 12 && this.pm) { h += 12; } else if (this.hourFormat == '12' && h == 12 && !this.pm) { h = 0; } return { hour: h, minute: m, second: s }; } }, parseDate(value, format) { if (format == null || value == null) { throw 'Invalid arguments'; } value = typeof value === 'object' ? value.toString() : value + ''; if (value === '') { return null; } let iFormat, dim, extra, iValue = 0, shortYearCutoff = typeof this.shortYearCutoff !== 'string' ? this.shortYearCutoff : (new Date().getFullYear() % 100) + parseInt(this.shortYearCutoff, 10), year = -1, month = -1, day = -1, doy = -1, literal = false, date, lookAhead = (match) => { let matches = iFormat + 1 < format.length && format.charAt(iFormat + 1) === match; if (matches) { iFormat++; } return matches; }, getNumber = (match) => { let isDoubled = lookAhead(match), size = match === '@' ? 14 : match === '!' ? 20 : match === 'y' && isDoubled ? 4 : match === 'o' ? 3 : 2, minSize = match === 'y' ? size : 1, digits = new RegExp('^\\d{' + minSize + ',' + size + '}'), num = value.substring(iValue).match(digits); if (!num) { throw 'Missing number at position ' + iValue; } iValue += num[0].length; return parseInt(num[0], 10); }, getName = (match, shortNames, longNames) => { let index = -1; let arr = lookAhead(match) ? longNames : shortNames; let names = []; for (let i = 0; i < arr.length; i++) { names.push([i, arr[i]]); } names.sort((a, b) => { return -(a[1].length - b[1].length); }); for (let i = 0; i < names.length; i++) { let name = names[i][1]; if (value.substr(iValue, name.length).toLowerCase() === name.toLowerCase()) { index = names[i][0]; iValue += name.length; break; } } if (index !== -1) { return index + 1; } else { throw 'Unknown name at position ' + iValue; } }, checkLiteral = () => { if (value.charAt(iValue) !== format.charAt(iFormat)) { throw 'Unexpected literal at position ' + iValue; } iValue++; }; if (this.currentView === 'month') { day = 1; } for (iFormat = 0; iFormat < format.length; iFormat++) { if (literal) { if (format.charAt(iFormat) === "'" && !lookAhead("'")) { literal = false; } else { checkLiteral(); } } else { switch (format.charAt(iFormat)) { case 'd': day = getNumber('d'); break; case 'D': getName('D', this.$primevue.config.locale.dayNamesShort, this.$primevue.config.locale.dayNames); break; case 'o': doy = getNumber('o'); break; case 'm': month = getNumber('m'); break; case 'M': month = getName('M', this.$primevue.config.locale.monthNamesShort, this.$primevue.config.locale.monthNames); break; case 'y': year = getNumber('y'); break; case '@': date = new Date(getNumber('@')); year = date.getFullYear(); month = date.getMonth() + 1; day = date.getDate(); break; case '!': date = new Date((getNumber('!') - this.ticksTo1970) / 10000); year = date.getFullYear(); month = date.getMonth() + 1; day = date.getDate(); break; case "'": if (lookAhead("'")) { checkLiteral(); } else { literal = true; } break; default: checkLiteral(); } } } if (iValue < value.length) { extra = value.substr(iValue); if (!/^\s+/.test(extra)) { throw 'Extra/unparsed characters found in date: ' + extra; } } if (year === -1) { year = new Date().getFullYear(); } else if (year < 100) { year += new Date().getFullYear() - (new Date().getFullYear() % 100) + (year <= shortYearCutoff ? 0 : -100); } if (doy > -1) { month = 1; day = doy; do { dim = this.getDaysCountInMonth(year, month - 1); if (day <= dim) { break; } month++; day -= dim; // eslint-disable-next-line } while (true); } date = this.daylightSavingAdjust(new Date(year, month - 1, day)); if (date.getFullYear() !== year || date.getMonth() + 1 !== month || date.getDate() !== day) { throw 'Invalid date'; // E.g. 31/02/00 } return date; }, getWeekNumber(date) { let checkDate = new Date(date.getTime()); checkDate.setDate(checkDate.getDate() + 4 - (checkDate.getDay() || 7)); let time = checkDate.getTime(); checkDate.setMonth(0); checkDate.setDate(1); return Math.floor(Math.round((time - checkDate.getTime()) / 86400000) / 7) + 1; }, onDateCellKeydown(event, date, groupIndex) { const cellContent = event.currentTarget; const cell = cellContent.parentElement; const cellIndex = DomHandler.index(cell); switch (event.code) { case 'ArrowDown': { cellContent.tabIndex = '-1'; let nextRow = cell.parentElement.nextElementSibling; if (nextRow) { let tableRowIndex = DomHandler.index(cell.parentElement); const tableRows = Array.from(cell.parentElement.parentElement.children); const nextTableRows = tableRows.slice(tableRowIndex + 1); let hasNextFocusableDate = nextTableRows.find((el) => { let focusCell = el.children[cellIndex].children[0]; return !DomHandler.getAttribute(focusCell, 'data-p-disabled'); }); if (hasNextFocusableDate) { let focusCell = hasNextFocusableDate.children[cellIndex].children[0]; focusCell.tabIndex = '0'; focusCell.focus(); } else { this.navigationState = { backward: false }; this.navForward(event); } } else { this.navigationState = { backward: false }; this.navForward(event); } event.preventDefault(); break; } case 'ArrowUp': { cellContent.tabIndex = '-1'; if (event.altKey) { this.overlayVisible = false; this.focused = true; } else { let prevRow = cell.parentElement.previousElementSibling; if (prevRow) { let tableRowIndex = DomHandler.index(cell.parentElement); const tableRows = Array.from(cell.parentElement.parentElement.children); const prevTableRows = tableRows.slice(0, tableRowIndex).reverse(); let hasNextFocusableDate = prevTableRows.find((el) => { let focusCell = el.children[cellIndex].children[0]; return !DomHandler.getAttribute(focusCell, 'data-p-disabled'); }); if (hasNextFocusableDate) { let focusCell = hasNextFocusableDate.children[cellIndex].children[0]; focusCell.tabIndex = '0'; focusCell.focus(); } else { this.navigationState = { backward: true }; this.navBackward(event); } } else { this.navigationState = { backward: true }; this.navBackward(event); } } event.preventDefault(); break; } case 'ArrowLeft': { cellContent.tabIndex = '-1'; let prevCell = cell.previousElementSibling; if (prevCell) { const cells = Array.from(cell.parentElement.children); const prevCells = cells.slice(0, cellIndex).reverse(); let hasNextFocusableDate = prevCells.find((el) => { let focusCell = el.children[0]; return !DomHandler.getAttribute(focusCell, 'data-p-disabled'); }); if (hasNextFocusableDate) { let focusCell = hasNextFocusableDate.children[0]; focusCell.tabIndex = '0'; focusCell.focus(); } else { this.navigateToMonth(event, true, groupIndex); } } else { this.navigateToMonth(event, true, groupIndex); } event.preventDefault(); break; } case 'ArrowRight': { cellContent.tabIndex = '-1'; let nextCell = cell.nextElementSibling; if (nextCell) { const cells = Array.from(cell.parentElement.children); const nextCells = cells.slice(cellIndex + 1); let hasNextFocusableDate = nextCells.find((el) => { let focusCell = el.children[0]; return !DomHandler.getAttribute(focusCell, 'data-p-disabled'); }); if (hasNextFocusableDate) { let focusCell = hasNextFocusableDate.children[0]; focusCell.tabIndex = '0'; focusCell.focus(); } else { this.navigateToMonth(event, false, groupIndex); } } else { this.navigateToMonth(event, false, groupIndex); } event.preventDefault(); break; } case 'Enter': case 'Space': { this.onDateSelect(event, date); event.preventDefault(); break; } case 'Escape': { this.overlayVisible = false; event.preventDefault(); break; } case 'Tab': { if (!this.inline) { this.trapFocus(event); } break; } case 'Home': { cellContent.tabIndex = '-1'; let currentRow = cell.parentElement; let focusCell = currentRow.children[0].children[0]; if (DomHandler.getAttribute(focusCell, 'data-p-disabled')) { this.navigateToMonth(event, true, groupIndex); } else { focusCell.tabIndex = '0'; focusCell.focus(); } event.preventDefault(); break; } case 'End': { cellContent.tabIndex = '-1'; let currentRow = cell.parentElement; let focusCell = currentRow.children[currentRow.children.length - 1].children[0]; if (DomHandler.getAttribute(focusCell, 'data-p-disabled')) { this.navigateToMonth(event, false, groupIndex); } else { focusCell.tabIndex = '0'; focusCell.focus(); } event.preventDefault(); break; } case 'PageUp': { cellContent.tabIndex = '-1'; if (event.shiftKey) { this.navigationState = { backward: true }; this.navBackward(event); } else this.navigateToMonth(event, true, groupIndex); event.preventDefault(); break; } case 'PageDown': { cellContent.tabIndex = '-1'; if (event.shiftKey) { this.navigationState = { backward: false }; this.navForward(event); } else this.navigateToMonth(event, false, groupIndex); event.preventDefault(); break; } default: //no op break; } }, navigateToMonth(event, prev, groupIndex) { if (prev) { if (this.numberOfMonths === 1 || groupIndex === 0) { this.navigationState = { backward: true }; this.navBackward(event); } else { let prevMonthContainer = this.overlay.children[groupIndex - 1]; let cells = DomHandler.find(prevMonthContainer, 'table td span:not([data-p-disabled="true"]):not([data-p-ink="true"])'); let focusCell = cells[cells.length - 1]; focusCell.tabIndex = '0'; focusCell.focus(); } } else { if (this.numberOfMonths === 1 || groupIndex === this.numberOfMonths - 1) { this.navigationState = { backward: false }; this.navForward(event); } else { let nextMonthContainer = this.overlay.children[groupIndex + 1]; let focusCell = DomHandler.findSingle(nextMonthContainer, 'table td span:not([data-p-disabled="true"]):not([data-p-ink="true"])'); focusCell.tabIndex = '0'; focusCell.focus(); } } }, onMonthCellKeydown(event, index) { const cell = event.currentTarget; switch (event.code) { case 'ArrowUp': case 'ArrowDown': { cell.tabIndex = '-1'; var cells = cell.parentElement.children; var cellIndex = DomHandler.index(cell); let nextCell = cells[event.code === 'ArrowDown' ? cellIndex + 3 : cellIndex - 3]; if (nextCell) { nextCell.tabIndex = '0'; nextCell.focus(); } event.preventDefault(); break; } case 'ArrowLeft': { cell.tabIndex = '-1'; let prevCell = cell.previousElementSibling; if (prevCell) { prevCell.tabIndex = '0'; prevCell.focus(); } else { this.navigationState = { backward: true }; this.navBackward(event); } event.preventDefault(); break; } case 'ArrowRight': { cell.tabIndex = '-1'; let nextCell = cell.nextElementSibling; if (nextCell) { nextCell.tabIndex = '0'; nextCell.focus(); } else { this.navigationState = { backward: false }; this.navForward(event); } event.preventDefault(); break; } case 'PageUp': { if (event.shiftKey) return; this.navigationState = { backward: true }; this.navBackward(event); break; } case 'PageDown': { if (event.shiftKey) return; this.navigationState = { backward: false }; this.navForward(event); break; } case 'Enter': case 'Space': { this.onMonthSelect(event, index); event.preventDefault(); break; } case 'Escape': { this.overlayVisible = false; event.preventDefault(); break; } case 'Tab': { this.trapFocus(event); break; } default: //no op break; } }, onYearCellKeydown(event, index) { const cell = event.currentTarget; switch (event.code) { case 'ArrowUp': case 'ArrowDown': { cell.tabIndex = '-1'; var cells = cell.parentElement.children; var cellIndex = DomHandler.index(cell); let nextCell = cells[event.code === 'ArrowDown' ? cellIndex + 2 : cellIndex - 2]; if (nextCell) { nextCell.tabIndex = '0'; nextCell.focus(); } event.preventDefault(); break; } case 'ArrowLeft': { cell.tabIndex = '-1'; let prevCell = cell.previousElementSibling; if (prevCell) { prevCell.tabIndex = '0'; prevCell.focus(); } else { this.navigationState = { backward: true }; this.navBackward(event); } event.preventDefault(); break; } case 'ArrowRight': { cell.tabIndex = '-1'; let nextCell = cell.nextElementSibling; if (nextCell) { nextCell.tabIndex = '0'; nextCell.focus(); } else { this.navigationState = { backward: false }; this.navForward(event); } event.preventDefault(); break; } case 'PageUp': { if (event.shiftKey) return; this.navigationState = { backward: true }; this.navBackward(event); break; } case 'PageDown': { if (event.shiftKey) return; this.navigationState = { backward: false }; this.navForward(event); break; } case 'Enter': case 'Space': { this.onYearSelect(event, index); event.preventDefault(); break; } case 'Escape': { this.overlayVisible = false; event.preventDefault(); break; } case 'Tab': { this.trapFocus(event); break; } default: //no op break; } }, updateFocus() { let cell; if (this.navigationState) { if (this.navigationState.button) { this.initFocusableCell(); if (this.navigationState.backward) this.previousButton.focus(); else this.nextButton.focus(); } else { if (this.navigationState.backward) { let cells; if (this.currentView === 'month') { cells = DomHandler.find(this.overlay, '[data-pc-section="monthpicker"] [data-pc-section="month"]:not([data-p-disabled="true"])'); } else if (this.currentView === 'year') { cells = DomHandler.find(this.overlay, '[data-pc-section="yearpicker"] [data-pc-section="year"]:not([data-p-disabled="true"])'); } else { cells = DomHandler.find(this.overlay, 'table td span:not([data-p-disabled="true"]):not([data-p-ink="true"])'); } if (cells && cells.length > 0) { cell = cells[cells.length - 1]; } } else { if (this.currentView === 'month') { cell = DomHandler.findSingle(this.overlay, '[data-pc-section="monthpicker"] [data-pc-section="month"]:not([data-p-disabled="true"])'); } else if (this.currentView === 'year') { cell = DomHandler.findSingle(this.overlay, '[data-pc-section="yearpicker"] [data-pc-section="year"]:not([data-p-disabled="true"])'); } else { cell = DomHandler.findSingle(this.overlay, 'table td span:not([data-p-disabled="true"]):not([data-p-ink="true"])'); } } if (cell) { cell.tabIndex = '0'; cell.focus(); } } this.navigationState = null; } else { this.initFocusableCell(); } }, initFocusableCell() { let cell; if (this.currentView === 'month') { let cells = DomHandler.find(this.overlay, '[data-pc-section="monthpicker"] [data-pc-section="month"]'); let selectedCell = DomHandler.findSingle(this.overlay, '[data-pc-section="monthpicker"] [data-pc-section="month"][data-p-highlight="true"]'); cells.forEach((cell) => (cell.tabIndex = -1)); cell = selectedCell || cells[0]; } else if (this.currentView === 'year') { let cells = DomHandler.find(this.overlay, '[data-pc-section="yearpicker"] [data-pc-section="year"]'); let selectedCell = DomHandler.findSingle(this.overlay, '[data-pc-section="yearpicker"] [data-pc-section="year"][data-p-highlight="true"]'); cells.forEach((cell) => (cell.tabIndex = -1)); cell = selectedCell || cells[0]; } else { cell = DomHandler.findSingle(this.overlay, 'span[data-p-highlight="true"]'); if (!cell) { let todayCell = DomHandler.findSingle(this.overlay, 'td.p-datepicker-today span:not([data-p-disabled="true"]):not([data-p-ink="true"])'); if (todayCell) cell = todayCell; else cell = DomHandler.findSingle(this.overlay, '.p-datepicker-calendar td span:not([data-p-disabled="true"]):not([data-p-ink="true"])'); } } if (cell) { cell.tabIndex = '0'; if (!this.inline && (!this.navigationState || !this.navigationState.button) && !this.timePickerChange) { if (!this.manualInput) cell.focus(); } this.preventFocus = false; } }, trapFocus(event) { event.preventDefault(); let focusableElements = DomHandler.getFocusableElements(this.overlay); if (focusableElements && focusableElements.length > 0) { if (!document.activeElement) { focusableElements[0].focus(); } else { let focusedIndex = focusableElements.indexOf(document.activeElement); if (event.shiftKey) { if (focusedIndex === -1 || focusedIndex === 0) focusableElements[focusableElements.length - 1].focus(); else focusableElements[focusedIndex - 1].focus(); } else { if (focusedIndex === -1) { if (this.timeOnly) { focusableElements[0].focus(); } else { let spanIndex = null; for (let i = 0; i < focusableElements.length; i++) { if (focusableElements[i].tagName === 'SPAN') spanIndex = i; } focusableElements[spanIndex].focus(); } } else if (focusedIndex === focusableElements.length - 1) focusableElements[0].focus(); else focusableElements[focusedIndex + 1].focus(); } } } }, onContainerButtonKeydown(event) { switch (event.code) { case 'Tab': this.trapFocus(event); break; case 'Escape': this.overlayVisible = false; event.preventDefault(); break; default: //Noop break; } this.$emit('keydown', event); }, onInput(event) { try { this.selectionStart = this.input.selectionStart; this.selectionEnd = this.input.selectionEnd; let value = this.parseValue(event.target.value); if (this.isValidSelection(value)) { this.typeUpdate = true; this.updateModel(value); } } catch (err) { /* NoOp */ } this.$emit('input', event); }, onInputClick() { if (this.showOnFocus && this.isEnabled() && !this.overlayVisible) { this.overlayVisible = true; } }, onFocus(event) { if (this.showOnFocus && this.isEnabled()) { this.overlayVisible = true; } this.focused = true; this.$emit('focus', event); }, onBlur(event) { this.$emit('blur', { originalEvent: event, value: event.target.value }); this.focused = false; event.target.value = this.formatValue(this.modelValue); }, onKeyDown(event) { if (event.code === 'ArrowDown' && this.overlay) { this.trapFocus(event); } else if (event.code === 'ArrowDown' && !this.overlay) { this.overlayVisible = true; } else if (event.code === 'Escape') { if (this.overlayVisible) { this.overlayVisible = false; event.preventDefault(); } } else if (event.code === 'Tab') { if (this.overlay) { DomHandler.getFocusableElements(this.overlay).forEach((el) => (el.tabIndex = '-1')); } if (this.overlayVisible) { this.overlayVisible = false; } } }, overlayRef(el) { this.overlay = el; }, inputRef(el) { this.input = el; }, previousButtonRef(el) { this.previousButton = el; }, nextButtonRef(el) { this.nextButton = el; }, getMonthName(index) { return this.$primevue.config.locale.monthNames[index]; }, getYear(month) { return this.currentView === 'month' ? this.currentYear : month.year; }, onOverlayClick(event) { if (!this.inline) { OverlayEventBus.emit('overlay-click', { originalEvent: event, target: this.$el }); } }, onOverlayKeyDown(event) { switch (event.code) { case 'Escape': this.input.focus(); this.overlayVisible = false; break; default: break; } }, onOverlayMouseUp(event) { this.onOverlayClick(event); }, createResponsiveStyle() { if (this.numberOfMonths > 1 && this.responsiveOptions && !this.isUnstyled) { if (!this.responsiveStyleElement) { this.responsiveStyleElement = document.createElement('style'); this.responsiveStyleElement.type = 'text/css'; DomHandler.setAttribute(this.responsiveStyleElement, 'nonce', this.$primevue?.config?.csp?.nonce); document.body.appendChild(this.responsiveStyleElement); } let innerHTML = ''; if (this.responsiveOptions) { const comparer = ObjectUtils.localeComparator(); let responsiveOptions = [...this.responsiveOptions].filter((o) => !!(o.breakpoint && o.numMonths)).sort((o1, o2) => -1 * comparer(o1.breakpoint, o2.breakpoint)); for (let i = 0; i < responsiveOptions.length; i++) { let { breakpoint, numMonths } = responsiveOptions[i]; let styles = ` .p-datepicker[${this.attributeSelector}] .p-datepicker-group:nth-child(${numMonths}) .p-datepicker-next { display: inline-flex !important; } `; for (let j = numMonths; j < this.numberOfMonths; j++) { styles += ` .p-datepicker[${this.attributeSelector}] .p-datepicker-group:nth-child(${j + 1}) { display: none !important; } `; } innerHTML += ` @media screen and (max-width: ${breakpoint}) { ${styles} } `; } } this.responsiveStyleElement.innerHTML = innerHTML; } }, destroyResponsiveStyleElement() { if (this.responsiveStyleElement) { this.responsiveStyleElement.remove(); this.responsiveStyleElement = null; } } }, computed: { viewDate() { let propValue = this.modelValue; if (propValue && Array.isArray(propValue)) { if (this.isRangeSelection()) { propValue = this.inline ? propValue[0] : propValue[1] || propValue[0]; } else if (this.isMultipleSelection()) { propValue = propValue[propValue.length - 1]; } } if (propValue && typeof propValue !== 'string') { return propValue; } else { let today = new Date(); if (this.maxDate && this.maxDate < today) { return this.maxDate; } if (this.minDate && this.minDate > today) { return this.minDate; } return today; } }, inputFieldValue() { return this.formatValue(this.modelValue); }, months() { let months = []; for (let i = 0; i < this.numberOfMonths; i++) { let month = this.currentMonth + i; let year = this.currentYear; if (month > 11) { month = (month % 11) - 1; year = year + 1; } let dates = []; let firstDay = this.getFirstDayOfMonthIndex(month, year); let daysLength = this.getDaysCountInMonth(month, year); let prevMonthDaysLength = this.getDaysCountInPrevMonth(month, year); let dayNo = 1; let today = new Date(); let weekNumbers = []; let monthRows = Math.ceil((daysLength + firstDay) / 7); for (let i = 0; i < monthRows; i++) { let week = []; if (i == 0) { for (let j = prevMonthDaysLength - firstDay + 1; j <= prevMonthDaysLength; j++) { let prev = this.getPreviousMonthAndYear(month, year); week.push({ day: j, month: prev.month, year: prev.year, otherMonth: true, today: this.isToday(today, j, prev.month, prev.year), selectable: this.isSelectable(j, prev.month, prev.year, true) }); } let remainingDaysLength = 7 - week.length; for (let j = 0; j < remainingDaysLength; j++) { week.push({ day: dayNo, month: month, year: year, today: this.isToday(today, dayNo, month, year), selectable: this.isSelectable(dayNo, month, year, false) }); dayNo++; } } else { for (let j = 0; j < 7; j++) { if (dayNo > daysLength) { let next = this.getNextMonthAndYear(month, year); week.push({ day: dayNo - daysLength, month: next.month, year: next.year, otherMonth: true, today: this.isToday(today, dayNo - daysLength, next.month, next.year), selectable: this.isSelectable(dayNo - daysLength, next.month, next.year, true) }); } else { week.push({ day: dayNo, month: month, year: year, today: this.isToday(today, dayNo, month, year), selectable: this.isSelectable(dayNo, month, year, false) }); } dayNo++; } } if (this.showWeek) { weekNumbers.push(this.getWeekNumber(new Date(week[0].year, week[0].month, week[0].day))); } dates.push(week); } months.push({ month: month, year: year, dates: dates, weekNumbers: weekNumbers }); } return months; }, weekDays() { let weekDays = []; let dayIndex = this.$primevue.config.locale.firstDayOfWeek; for (let i = 0; i < 7; i++) { weekDays.push(this.$primevue.config.locale.dayNamesMin[dayIndex]); dayIndex = dayIndex == 6 ? 0 : ++dayIndex; } return weekDays; }, ticksTo1970() { return ((1970 - 1) * 365 + Math.floor(1970 / 4) - Math.floor(1970 / 100) + Math.floor(1970 / 400)) * 24 * 60 * 60 * 10000000; }, sundayIndex() { return this.$primevue.config.locale.firstDayOfWeek > 0 ? 7 - this.$primevue.config.locale.firstDayOfWeek : 0; }, datePattern() { return this.dateFormat || this.$primevue.config.locale.dateFormat; }, yearOptions() { if (this.yearRange) { let $vm = this; const years = this.yearRange.split(':'); let yearStart = parseInt(years[0]); let yearEnd = parseInt(years[1]); let yearOptions = []; if (this.currentYear < yearStart) { $vm.currentYear = yearEnd; } else if (this.currentYear > yearEnd) { $vm.currentYear = yearStart; } for (let i = yearStart; i <= yearEnd; i++) { yearOptions.push(i); } return yearOptions; } else { return null; } }, monthPickerValues() { let monthPickerValues = []; const isSelectableMonth = (baseMonth) => { if (this.minDate) { const minMonth = this.minDate.getMonth(); const minYear = this.minDate.getFullYear(); if (this.currentYear < minYear || (this.currentYear === minYear && baseMonth < minMonth)) { return false; } } if (this.maxDate) { const maxMonth = this.maxDate.getMonth(); const maxYear = this.maxDate.getFullYear(); if (this.currentYear > maxYear || (this.currentYear === maxYear && baseMonth > maxMonth)) { return false; } } return true; }; for (let i = 0; i <= 11; i++) { monthPickerValues.push({ value: this.$primevue.config.locale.monthNamesShort[i], selectable: isSelectableMonth(i) }); } return monthPickerValues; }, yearPickerValues() { let yearPickerValues = []; let base = this.currentYear - (this.currentYear % 10); const isSelectableYear = (baseYear) => { if (this.minDate) { if (this.minDate.getFullYear() > baseYear) return false; } if (this.maxDate) { if (this.maxDate.getFullYear() < baseYear) return false; } return true; }; for (let i = 0; i < 10; i++) { yearPickerValues.push({ value: base + i, selectable: isSelectableYear(base + i) }); } return yearPickerValues; }, formattedCurrentHour() { return this.currentHour < 10 ? '0' + this.currentHour : this.currentHour; }, formattedCurrentMinute() { return this.currentMinute < 10 ? '0' + this.currentMinute : this.currentMinute; }, formattedCurrentSecond() { return this.currentSecond < 10 ? '0' + this.currentSecond : this.currentSecond; }, todayLabel() { return this.$primevue.config.locale.today; }, clearLabel() { return this.$primevue.config.locale.clear; }, weekHeaderLabel() { return this.$primevue.config.locale.weekHeader; }, monthNames() { return this.$primevue.config.locale.monthNames; }, attributeSelector() { return UniqueComponentId(); }, switchViewButtonDisabled() { return this.numberOfMonths > 1 || this.disabled; }, panelId() { return UniqueComponentId() + '_panel'; } }, components: { CalendarButton: Button, Portal: Portal, CalendarIcon: CalendarIcon, ChevronLeftIcon: ChevronLeftIcon, ChevronRightIcon: ChevronRightIcon, ChevronUpIcon: ChevronUpIcon, ChevronDownIcon: ChevronDownIcon }, directives: { ripple: Ripple } }; </script>