Initiated Calendar component
parent
bf9c810f71
commit
4ead1093a4
|
@ -2,51 +2,58 @@
|
|||
<span :class="containerClass">
|
||||
<CalendarInputText v-if="!inline" type="text" v-bind="$attrs" v-on="listeners" :value="inputFieldValue" />
|
||||
<CalendarButton v-if="showIcon" :icon="icon" tabindex="-1" class="p-datepicker-trigger p-calendar-button" :disabled="$attrs.disabled" />
|
||||
<div :class="panelStyleClass">
|
||||
<div class="p-datepicker-group" v-for="(month,i) of months" :key="month.month + month.year">
|
||||
<div class="p-datepicker-header">
|
||||
<button class="p-datepicker-prev p-link" v-if="i === 0">
|
||||
<span class="p-datepicker-prev-icon pi pi-chevron-left"></span>
|
||||
</button>
|
||||
<button class="p-datepicker-next p-link" v-if="numberOfMonths === 1 ? true : (i === numberOfMonths -1)">
|
||||
<span class="p-datepicker-next-icon pi pi-chevron-right"></span>
|
||||
</button>
|
||||
<div class="p-datepicker-title">
|
||||
<span class="p-datepicker-month" v-if="monthNavigator && (view !== 'month')">{{locale.monthNames[month.month]}}</span>
|
||||
<span class="p-datepicker-year" v-if="!yearNavigator">{{view === 'month' ? currentYear : month.year}}</span>
|
||||
<transition name="p-input-overlay" @enter="onOverlayEnter" @leave="onOverlayLeave">
|
||||
<div ref="overlay" :class="panelStyleClass" v-if="inline ? true : overlayVisible">
|
||||
<div class="p-datepicker-group" v-for="(month,i) of months" :key="month.month + month.year">
|
||||
<div class="p-datepicker-header">
|
||||
<button class="p-datepicker-prev p-link" v-if="i === 0">
|
||||
<span class="p-datepicker-prev-icon pi pi-chevron-left"></span>
|
||||
</button>
|
||||
<button class="p-datepicker-next p-link" v-if="numberOfMonths === 1 ? true : (i === numberOfMonths -1)">
|
||||
<span class="p-datepicker-next-icon pi pi-chevron-right"></span>
|
||||
</button>
|
||||
<div class="p-datepicker-title">
|
||||
<span class="p-datepicker-month" v-if="monthNavigator && (view !== 'month')">{{locale.monthNames[month.month]}}</span>
|
||||
<span class="p-datepicker-year" v-if="!yearNavigator">{{view === 'month' ? currentYear : month.year}}</span>
|
||||
</div>
|
||||
</div>
|
||||
<div class="p-datepicker-calendar-container" v-if="view ==='date'">
|
||||
<table class="p-datepicker-calendar">
|
||||
<thead>
|
||||
<tr>
|
||||
<th scope="col" v-for="weekDay of weekDays" :key="weekDay">
|
||||
<span>{{weekDay}}</span>
|
||||
</th>
|
||||
</tr>
|
||||
</thead>
|
||||
<tbody>
|
||||
<tr v-for="week of month.dates" :key="week[0].day + week[0].month">
|
||||
<td v-for="date of week" :key="date.day" :class="{'p-datepicker-other-month': date.otherMonth, 'p-datepicker-today': date.today}">
|
||||
<span :class="{'p-highlight': isSelected(date), 'p-disabled': !date.selectable}">{{date.day}}</span>
|
||||
</td>
|
||||
</tr>
|
||||
</tbody>
|
||||
</table>
|
||||
</div>
|
||||
</div>
|
||||
<div class="p-datepicker-calendar-container" *ngIf="view ==='date'">
|
||||
<table class="p-datepicker-calendar">
|
||||
<thead>
|
||||
<tr>
|
||||
<th scope="col" *ngFor="let weekDay of weekDays;let begin = first; let end = last">
|
||||
<span>{{weekDay}}</span>
|
||||
</th>
|
||||
</tr>
|
||||
</thead>
|
||||
<tbody>
|
||||
<tr v-for="week of month.dates" :key="week[0].day + week[0].month">
|
||||
<td v-for="date of week" :key="date.day" :class="{'p-datepicker-other-month': date.otherMonth, 'p-datepicker-today': date.today}">
|
||||
|
||||
</td>
|
||||
</tr>
|
||||
</tbody>
|
||||
</table>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</transition>
|
||||
</span>
|
||||
</template>
|
||||
|
||||
<script>
|
||||
import InputText from '../inputtext/InputText';
|
||||
import Button from '../button/Button';
|
||||
import DomHandler from '../utils/DomHandler';
|
||||
|
||||
export default {
|
||||
inheritAttrs: false,
|
||||
props: {
|
||||
value: null,
|
||||
defaultDate: {
|
||||
type: Date,
|
||||
default: null
|
||||
},
|
||||
timeOnly: {
|
||||
type: Boolean,
|
||||
default: false
|
||||
|
@ -85,19 +92,248 @@ export default {
|
|||
},
|
||||
panelClass: String,
|
||||
panelStyle: null,
|
||||
minDate: {
|
||||
type: Date,
|
||||
value: null
|
||||
},
|
||||
maxDate: {
|
||||
type: Date,
|
||||
value: null
|
||||
},
|
||||
disabledDates: {
|
||||
type: Array,
|
||||
value: null
|
||||
},
|
||||
disabledDays: {
|
||||
type: Array,
|
||||
value: null
|
||||
},
|
||||
locale: {
|
||||
type: Object,
|
||||
default: {
|
||||
firstDayOfWeek: 0,
|
||||
dayNames: ["Sunday", "Monday", "Tuesday", "Wednesday", "Thursday", "Friday", "Saturday"],
|
||||
dayNamesShort: ["Sun", "Mon", "Tue", "Wed", "Thu", "Fri", "Sat"],
|
||||
dayNamesMin: ["Su","Mo","Tu","We","Th","Fr","Sa"],
|
||||
monthNames: [ "January","February","March","April","May","June","July","August","September","October","November","December" ],
|
||||
monthNamesShort: [ "Jan", "Feb", "Mar", "Apr", "May", "Jun","Jul", "Aug", "Sep", "Oct", "Nov", "Dec" ],
|
||||
today: 'Today',
|
||||
clear: 'Clear',
|
||||
dateFormat: 'mm/dd/yy'
|
||||
default: () => {
|
||||
return {
|
||||
firstDayOfWeek: 0,
|
||||
dayNames: ["Sunday", "Monday", "Tuesday", "Wednesday", "Thursday", "Friday", "Saturday"],
|
||||
dayNamesShort: ["Sun", "Mon", "Tue", "Wed", "Thu", "Fri", "Sat"],
|
||||
dayNamesMin: ["Su","Mo","Tu","We","Th","Fr","Sa"],
|
||||
monthNames: [ "January","February","March","April","May","June","July","August","September","October","November","December" ],
|
||||
monthNamesShort: [ "Jan", "Feb", "Mar", "Apr", "May", "Jun","Jul", "Aug", "Sep", "Oct", "Nov", "Dec" ],
|
||||
today: 'Today',
|
||||
clear: 'Clear',
|
||||
dateFormat: 'mm/dd/yy'
|
||||
}
|
||||
}
|
||||
},
|
||||
appendTo: null,
|
||||
showOnFocus: {
|
||||
type: Boolean,
|
||||
default: true
|
||||
},
|
||||
autoZIndex: {
|
||||
type: Boolean,
|
||||
default: true
|
||||
},
|
||||
baseZIndex: {
|
||||
type: Number,
|
||||
default: 0
|
||||
}
|
||||
},
|
||||
created() {
|
||||
let viewDate = null;
|
||||
if (this.defaultDate) {
|
||||
viewDate = this.defaultDate;
|
||||
}
|
||||
else {
|
||||
let propValue = this.value;
|
||||
if (Array.isArray(propValue)) {
|
||||
propValue = propValue[0];
|
||||
}
|
||||
|
||||
viewDate = propValue || new Date();
|
||||
}
|
||||
|
||||
this.currentMonth = viewDate.getMonth();
|
||||
this.currentYear = viewDate.getFullYear();
|
||||
},
|
||||
data() {
|
||||
return {
|
||||
currentMonth: null,
|
||||
currentYear: null,
|
||||
overlayVisible: false
|
||||
}
|
||||
},
|
||||
outsideClickListener: null,
|
||||
methods: {
|
||||
isSelected(dateMeta) {
|
||||
if(this.value) {
|
||||
if(this.isSingleSelection()) {
|
||||
return this.isDateEquals(this.props.value, dateMeta);
|
||||
}
|
||||
else if(this.isMultipleSelection()) {
|
||||
let selected = false;
|
||||
for(let date of this.props.value) {
|
||||
selected = this.isDateEquals(date, dateMeta);
|
||||
if(selected) {
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
return selected;
|
||||
}
|
||||
else if(this.isRangeSelection()) {
|
||||
if(this.props.value[1])
|
||||
return this.isDateEquals(this.props.value[0], dateMeta) || this.isDateEquals(this.props.value[1], dateMeta) || this.isDateBetween(this.props.value[0], this.props.value[1], dateMeta);
|
||||
else {
|
||||
return this.isDateEquals(this.props.value[0], dateMeta);
|
||||
}
|
||||
|
||||
}
|
||||
}
|
||||
else {
|
||||
return false;
|
||||
}
|
||||
},
|
||||
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() {
|
||||
if (this.autoZIndex) {
|
||||
this.$refs.overlay.style.zIndex = String(this.baseZIndex + DomHandler.generateZIndex());
|
||||
}
|
||||
this.alignOverlay();
|
||||
this.bindOutsideClickListener();
|
||||
},
|
||||
onOverlayLeave() {
|
||||
this.unbindOutsideClickListener();
|
||||
},
|
||||
bindOutsideClickListener() {
|
||||
if (!this.outsideClickListener) {
|
||||
this.outsideClickListener = (event) => {
|
||||
if (this.overlayVisible && this.$refs.overlay && !this.$el.contains(event.target)) {
|
||||
this.overlayVisible = false;
|
||||
}
|
||||
};
|
||||
document.addEventListener('click', this.outsideClickListener);
|
||||
}
|
||||
},
|
||||
unbindOutsideClickListener() {
|
||||
if (this.outsideClickListener) {
|
||||
document.removeEventListener('click', this.outsideClickListener);
|
||||
this.outsideClickListener = null;
|
||||
}
|
||||
},
|
||||
alignOverlay() {
|
||||
if (this.$refs.overlay) {
|
||||
if (this.appendTo)
|
||||
DomHandler.absolutePosition(this.$refs.overlay, this.$el);
|
||||
else
|
||||
DomHandler.relativePosition(this.$refs.overlay, this.$el);
|
||||
}
|
||||
}
|
||||
},
|
||||
computed: {
|
||||
|
@ -106,6 +342,16 @@ export default {
|
|||
...this.$listeners,
|
||||
input: event => {
|
||||
this.$emit('input', event)
|
||||
},
|
||||
focus: event => {
|
||||
this.focus = true;
|
||||
if (this.showOnFocus) {
|
||||
this.overlayVisible = true;
|
||||
}
|
||||
this.$emit('focus', event)
|
||||
},
|
||||
blur: event => {
|
||||
this.$emit('blur', event);
|
||||
}
|
||||
};
|
||||
},
|
||||
|
@ -124,7 +370,6 @@ export default {
|
|||
'p-datepicker p-component',
|
||||
{
|
||||
'p-datepicker-inline': this.inline,
|
||||
'p-input-overlay': !this.inline,
|
||||
'p-shadow': !this.inline,
|
||||
'p-disabled': this.$attrs.disabled,
|
||||
'p-datepicker-timeonly': this.timeOnly,
|
||||
|
@ -136,6 +381,85 @@ export default {
|
|||
},
|
||||
inputFieldValue() {
|
||||
return '';
|
||||
},
|
||||
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();
|
||||
|
||||
for (let i = 0; i < 6; 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++;
|
||||
}
|
||||
}
|
||||
|
||||
dates.push(week);
|
||||
}
|
||||
|
||||
months.push({
|
||||
month: month,
|
||||
year: year,
|
||||
dates: dates
|
||||
});
|
||||
}
|
||||
|
||||
return months;
|
||||
},
|
||||
weekDays() {
|
||||
let weekDays = [];
|
||||
let dayIndex = this.locale.firstDayOfWeek;
|
||||
for (let i = 0; i < 7; i++) {
|
||||
weekDays.push(this.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.locale.firstDayOfWeek > 0 ? 7 - this.locale.firstDayOfWeek : 0;
|
||||
}
|
||||
},
|
||||
components: {
|
||||
|
@ -190,7 +514,6 @@ export default {
|
|||
.p-datepicker {
|
||||
width: auto;
|
||||
padding: .2em;
|
||||
display: none;
|
||||
position: absolute;
|
||||
}
|
||||
|
||||
|
|
Loading…
Reference in New Issue