Implemented selection modes for Calendar

pull/12/head
cagataycivici 2019-05-15 21:10:09 +03:00
parent c7eb28908f
commit 1f063e032a
2 changed files with 413 additions and 49 deletions

View File

@ -33,9 +33,10 @@
</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>
<tr v-for="week of month.dates" :key="week[0].day + '' + week[0].month">
<td v-for="date of week" :key="date.day + '' + date.month" :class="{'p-datepicker-other-month': date.otherMonth, 'p-datepicker-today': date.today}">
<span :class="{'p-highlight': isSelected(date), 'p-disabled': !date.selectable}"
@click="onDateSelect(date)" draggable="false">{{date.day}}</span>
</td>
</tr>
</tbody>
@ -60,7 +61,23 @@ export default {
type: Date,
default: null
},
timeOnly: {
selectionMode: {
type: String,
default: 'single'
},
dateFormat: {
type: String,
default: 'mm/dd/yy'
},
inline: {
type: Boolean,
default: false
},
showOtherMonths: {
type: Boolean,
default: true
},
selectOtherMonths: {
type: Boolean,
default: false
},
@ -68,10 +85,6 @@ export default {
type: Boolean,
default: false
},
inline: {
type: Boolean,
default: false
},
icon: {
type: String,
default: 'pi pi-calendar'
@ -122,6 +135,73 @@ export default {
type: Array,
value: null
},
maxDateCount: {
type: Number,
value: null
},
appendTo: {
type: null
},
showOnFocus: {
type: Boolean,
default: true
},
autoZIndex: {
type: Boolean,
default: true
},
baseZIndex: {
type: Number,
default: 0
},
showButtonBar: {
type: Boolean,
default: false
},
shortYearCutoff: {
type: String,
default: '+10'
},
showTime: {
type: Boolean,
default: false
},
timeOnly: {
type: Boolean,
default: false
},
hourFormat: {
type: String,
default: '24'
},
stepHour: {
type: Number,
default: 1
},
stepMinute: {
type: Number,
default: 1
},
stepSecond: {
type: Number,
default: 1
},
showSeconds: {
type: Boolean,
default: false
},
keepInvalid: {
type: Boolean,
default: false
},
hideOnDateTimeSelect: {
type: Boolean,
default: false
},
timeSeparator: {
type: String,
default: ':'
},
locale: {
type: Object,
default: () => {
@ -138,21 +218,6 @@ export default {
weekHeader: 'Sm'
}
}
},
appendTo: {
type: null
},
showOnFocus: {
type: Boolean,
default: true
},
autoZIndex: {
type: Boolean,
default: true
},
baseZIndex: {
type: Number,
default: 0
}
},
created() {
@ -176,32 +241,35 @@ export default {
return {
currentMonth: null,
currentYear: null,
currentHour: null,
currentMinute: null,
currentSecond: null,
overlayVisible: false
}
},
outsideClickListener: null,
methods: {
isSelected(dateMeta) {
if(this.value) {
if(this.isSingleSelection()) {
return this.isDateEquals(this.props.value, dateMeta);
if (this.value) {
if (this.isSingleSelection()) {
return this.isDateEquals(this.value, dateMeta);
}
else if(this.isMultipleSelection()) {
else if (this.isMultipleSelection()) {
let selected = false;
for(let date of this.props.value) {
for (let date of this.value) {
selected = this.isDateEquals(date, dateMeta);
if(selected) {
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 if( this.isRangeSelection()) {
if (this.value[1])
return this.isDateEquals(this.value[0], dateMeta) || this.isDateEquals(this.value[1], dateMeta) || this.isDateBetween(this.value[0], this.value[1], dateMeta);
else {
return this.isDateEquals(this.props.value[0], dateMeta);
return this.isDateEquals(this.value[0], dateMeta);
}
}
@ -210,6 +278,21 @@ export default {
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);
@ -374,19 +457,9 @@ export default {
},
decrementYear() {
this.currentYear--;
/*if (this.yearNavigator && this.currentYear < this.yearOptions[0]) {
let difference = this.yearOptions[this.yearOptions.length - 1] - this.yearOptions[0];
this.populateYearOptions(this.yearOptions[0] - difference, this.yearOptions[this.yearOptions.length - 1] - difference);
}*/
},
incrementYear() {
this.currentYear++;
/*if (this.yearNavigator && this.currentYear > this.yearOptions[this.yearOptions.length - 1]) {
let difference = this.yearOptions[this.yearOptions.length - 1] - this.yearOptions[0];
this.populateYearOptions(this.yearOptions[0] + difference, this.yearOptions[this.yearOptions.length - 1] + difference);
}*/
},
bindOutsideClickListener() {
if (!this.outsideClickListener) {
@ -455,6 +528,242 @@ export default {
onYearDropdownChange(value) {
this.currentYear = parseInt(value);
this.$emit('year-change', {month: this.currentMonth + 1, year: this.currentYear});
},
onDateSelect(dateMeta) {
if (this.$attrs.disabled || !dateMeta.selectable) {
return;
}
if (this.isMultipleSelection() && this.isSelected(dateMeta)) {
let newValue = this.value.filter((date, i) => !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(() => {
this.overlayVisible = false;
if (this.mask) {
this.disableModality();
}
}, 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();
}
if (this.isSingleSelection()) {
this.updateModel(date);
}
else if (this.isMultipleSelection()) {
this.updateModel(this.value ? [...this.value, date] : [date]);
}
else if (this.isRangeSelection()) {
if (this.value && this.value.length) {
let startDate = this.value[0];
let endDate = this.value[1];
if (!endDate && date.getTime() >= startDate.getTime()) {
endDate = date;
}
else {
startDate = date;
endDate = null;
}
this.updateModel([startDate, endDate]);
}
else {
this.updateModel([date, null]);
}
}
this.$emit('select', date);
},
updateModel(value) {
this.$emit('input', value);
},
shouldSelectDate(dateMeta) {
if (this.isMultipleSelection())
return this.maxDateCount != null ? this.maxDateCount > (this.value ? this.value.length : 0) : true;
else
return true;
},
isSingleSelection() {
return this.selectionMode === 'single';
},
isRangeSelection() {
return this.selectionMode === 'range';
},
isMultipleSelection() {
return this.selectionMode === 'multiple';
},
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.locale.dayNamesShort, this.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.locale.monthNamesShort, this.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 ? ' PM' : ' AM';
}
return output;
}
},
computed: {
@ -501,7 +810,40 @@ export default {
];
},
inputFieldValue() {
return '';
let formattedValue = '';
if (this.value) {
try {
if (this.isSingleSelection()) {
formattedValue = this.formatDateTime(this.value);
}
else if (this.isMultipleSelection()) {
for(let i = 0; i < this.value.length; i++) {
let dateAsString = this.formatDateTime(this.value[i]);
formattedValue += dateAsString;
if(i !== (this.value.length - 1)) {
formattedValue += ', ';
}
}
}
else if (this.isRangeSelection()) {
if (this.value && this.value.length) {
let startDate = this.value[0];
let endDate = this.value[1];
formattedValue = this.formatDateTime(startDate);
if (endDate) {
formattedValue += ' - ' + this.formatDateTime(endDate);
}
}
}
}
catch(err) {
formattedValue = this.value;
}
}
return formattedValue;
},
months() {
let months = [];
@ -587,10 +929,18 @@ export default {
},
yearOptions() {
const years = this.yearRange.split(':');
const yearStart = parseInt(years[0]);
const yearEnd = parseInt(years[1]);
let yearStart = parseInt(years[0]);
let yearEnd = parseInt(years[1]);
let diff = yearEnd - yearStart;
let yearOptions = [];
if (this.currentYear < yearStart) {
this.currentYear = yearEnd;
}
else if (this.currentYear > yearEnd) {
this.currentYear = yearStart;
}
for (let i = yearStart; i <= yearEnd; i++) {
yearOptions.push(i);
}

View File

@ -11,11 +11,11 @@
<div class="p-grid p-fluid">
<div class="p-col-12 p-md-4">
<h3>Basic</h3>
<Calendar v-model="date1" />
<Calendar v-model="date1" />{{date1}}
</div>
<div class="p-col-12 p-md-4">
<h3>Spanish</h3>
<Calendar v-model="date2" :locale="es" />
<Calendar v-model="date2" :locale="es" dateFormat="dd/mm/yy" />
</div>
<div class="p-col-12 p-md-4">
<h3>Icon</h3>
@ -33,6 +33,18 @@
<h3>Navigators</h3>
<Calendar v-model="date6" :monthNavigator="true" :yearNavigator="true" yearRange="2000:2030" />
</div>
<div class="p-col-12 p-md-4">
<h3>Multiple</h3>
<Calendar v-model="dates1" selectionMode="multiple" :readonly="true" />
</div>
<div class="p-col-12 p-md-4">
<h3>Range</h3>
<Calendar v-model="dates2" selectionMode="range" :readonly="true" />
</div>
<div class="p-col-12 p-md-4">
<h3>Button Bar</h3>
<Calendar v-model="date7" :showButtonBar="true" />
</div>
</div>
</div>
@ -45,7 +57,6 @@ import CalendarDoc from './CalendarDoc'
export default {
created() {
console.log(this.es.firstDayOfWeek);
let today = new Date();
let month = today.getMonth();
let year = today.getFullYear();
@ -72,6 +83,9 @@ export default {
date4: null,
date5: null,
date6: null,
date7: null,
dates1: null,
dates2: null,
es: {
firstDayOfWeek: 1,
dayNames: [ "Domingo","Lunes","Martes","Miércoles","Jueves","Viernes","Sábado" ],