Initiated Calendar component

pull/12/head
cagataycivici 2019-05-13 14:22:49 +03:00
parent bf9c810f71
commit 4ead1093a4
1 changed files with 366 additions and 43 deletions

View File

@ -2,7 +2,8 @@
<span :class="containerClass"> <span :class="containerClass">
<CalendarInputText v-if="!inline" type="text" v-bind="$attrs" v-on="listeners" :value="inputFieldValue" /> <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" /> <CalendarButton v-if="showIcon" :icon="icon" tabindex="-1" class="p-datepicker-trigger p-calendar-button" :disabled="$attrs.disabled" />
<div :class="panelStyleClass"> <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-group" v-for="(month,i) of months" :key="month.month + month.year">
<div class="p-datepicker-header"> <div class="p-datepicker-header">
<button class="p-datepicker-prev p-link" v-if="i === 0"> <button class="p-datepicker-prev p-link" v-if="i === 0">
@ -16,11 +17,11 @@
<span class="p-datepicker-year" v-if="!yearNavigator">{{view === 'month' ? currentYear : month.year}}</span> <span class="p-datepicker-year" v-if="!yearNavigator">{{view === 'month' ? currentYear : month.year}}</span>
</div> </div>
</div> </div>
<div class="p-datepicker-calendar-container" *ngIf="view ==='date'"> <div class="p-datepicker-calendar-container" v-if="view ==='date'">
<table class="p-datepicker-calendar"> <table class="p-datepicker-calendar">
<thead> <thead>
<tr> <tr>
<th scope="col" *ngFor="let weekDay of weekDays;let begin = first; let end = last"> <th scope="col" v-for="weekDay of weekDays" :key="weekDay">
<span>{{weekDay}}</span> <span>{{weekDay}}</span>
</th> </th>
</tr> </tr>
@ -28,7 +29,7 @@
<tbody> <tbody>
<tr v-for="week of month.dates" :key="week[0].day + week[0].month"> <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 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> </td>
</tr> </tr>
</tbody> </tbody>
@ -36,17 +37,23 @@
</div> </div>
</div> </div>
</div> </div>
</transition>
</span> </span>
</template> </template>
<script> <script>
import InputText from '../inputtext/InputText'; import InputText from '../inputtext/InputText';
import Button from '../button/Button'; import Button from '../button/Button';
import DomHandler from '../utils/DomHandler';
export default { export default {
inheritAttrs: false, inheritAttrs: false,
props: { props: {
value: null, value: null,
defaultDate: {
type: Date,
default: null
},
timeOnly: { timeOnly: {
type: Boolean, type: Boolean,
default: false default: false
@ -85,9 +92,26 @@ export default {
}, },
panelClass: String, panelClass: String,
panelStyle: null, panelStyle: null,
minDate: {
type: Date,
value: null
},
maxDate: {
type: Date,
value: null
},
disabledDates: {
type: Array,
value: null
},
disabledDays: {
type: Array,
value: null
},
locale: { locale: {
type: Object, type: Object,
default: { default: () => {
return {
firstDayOfWeek: 0, firstDayOfWeek: 0,
dayNames: ["Sunday", "Monday", "Tuesday", "Wednesday", "Thursday", "Friday", "Saturday"], dayNames: ["Sunday", "Monday", "Tuesday", "Wednesday", "Thursday", "Friday", "Saturday"],
dayNamesShort: ["Sun", "Mon", "Tue", "Wed", "Thu", "Fri", "Sat"], dayNamesShort: ["Sun", "Mon", "Tue", "Wed", "Thu", "Fri", "Sat"],
@ -100,12 +124,234 @@ export default {
} }
} }
}, },
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: { computed: {
listeners() { listeners() {
return { return {
...this.$listeners, ...this.$listeners,
input: event => { input: event => {
this.$emit('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 p-component',
{ {
'p-datepicker-inline': this.inline, 'p-datepicker-inline': this.inline,
'p-input-overlay': !this.inline,
'p-shadow': !this.inline, 'p-shadow': !this.inline,
'p-disabled': this.$attrs.disabled, 'p-disabled': this.$attrs.disabled,
'p-datepicker-timeonly': this.timeOnly, 'p-datepicker-timeonly': this.timeOnly,
@ -136,6 +381,85 @@ export default {
}, },
inputFieldValue() { inputFieldValue() {
return ''; 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: { components: {
@ -190,7 +514,6 @@ export default {
.p-datepicker { .p-datepicker {
width: auto; width: auto;
padding: .2em; padding: .2em;
display: none;
position: absolute; position: absolute;
} }