Last active
March 8, 2018 15:41
-
-
Save djave-co/05808c8d8151fa0f22e289ed9cdef3d9 to your computer and use it in GitHub Desktop.
Vue calendar component
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
<template> | |
<div class="calendar"> | |
<nav class="calendar__nav"> | |
<a @click="decMonth" class="calendar__chevron btn btn-primary"> | |
← | |
</a> | |
<b>{{ monthName }}</b> | |
<b>{{ year }}</b> | |
<a @click="incMonth" class="calendar__chevron btn btn-primary"> | |
→ | |
</a> | |
</nav> | |
<div class="calendar__labels"> | |
<span class="calendar__label" v-for="label in dayLabels">{{ label }} </span> | |
</div> | |
<div class="calendar__month"> | |
<div v-for="week in weeks" class="calendar__week"> | |
<span class="calendar__day" v-for="day in week" v-bind:class="[selectedClass(day), dayClass(day), betweenClass(day)]" @click="select(day)"> | |
<span v-if="day.date"> | |
{{ day.date }} | |
</span> | |
</span> | |
</div> | |
</div> | |
<input required="required" name="start_date" type="text" :value="startDate ? dateFormat(startDate) : ''"> | |
<input required="required" name="end_date" type="text" :value="endDate ? dateFormat(endDate) : ''"> | |
</div> | |
</template> | |
<script> | |
import moment from 'moment'; | |
export default { | |
data(){ | |
return { | |
dayLabels: ['S', 'M', 'T', 'W', 'T', 'F', 'S'], | |
month : moment().month(), | |
year : moment().year(), | |
startDate : false, | |
endDate : false, | |
} | |
}, | |
computed : { | |
firstDate() { | |
return new Date(this.year, this.month, 1); | |
}, | |
monthName(){ | |
return moment().month(this.month).format('MMMM'); | |
}, | |
daysInMonth() { | |
return moment().month(this.month).year(this.year).daysInMonth(); | |
}, | |
firstDayIndex() { | |
return this.firstDate.getDay(); // 5 | |
}, | |
lastDate() { | |
return this.firstDayIndex + this.daysInMonth; | |
}, | |
weeks() { | |
var squareIndex = 0; | |
var dateOfMonth = 1; | |
var weeks = []; | |
while (squareIndex < (this.lastDate)) { | |
var week = []; | |
for (var d = 0; d < 7; d++) { | |
if (squareIndex < this.firstDayIndex || squareIndex >= (this.lastDate)) { | |
week.push({ date : false }); //4 | |
} else { | |
week.push({ | |
date : dateOfMonth, | |
data : { | |
day : dateOfMonth, | |
month : this.month, | |
year : this.year | |
} | |
}); | |
dateOfMonth++; | |
} | |
squareIndex++; | |
} | |
weeks.push(week); | |
} | |
return weeks; | |
} | |
}, | |
methods: { | |
incMonth: function() { | |
if (this.month == 11) { // | |
this.year++; | |
this.month = 0; | |
return true; | |
} | |
this.month++; | |
}, | |
decMonth: function() { | |
if (this.month == 0) { | |
this.year--; | |
this.month = 11; | |
return true; | |
} | |
this.month--; | |
}, | |
select : function(day){ | |
if( ! this.isDay(day) ) return false; | |
if(this.startDate && this.endDate){ | |
this.setStartDate(day.data); | |
this.endDate = false; | |
return; | |
} | |
if(this.startDate){ | |
if(this.isBefore(day.data, this.startDate)){ | |
this.setEndDate(this.startDate); | |
this.setStartDate(day.data); | |
return; | |
} | |
this.setEndDate(day.data); | |
return; | |
} | |
return this.setStartDate(day.data); | |
}, | |
setStartDate(day){ | |
this.startDate = JSON.parse(JSON.stringify(day)); | |
}, | |
setEndDate(day){ | |
this.endDate = JSON.parse(JSON.stringify(day)); | |
}, | |
isSelected : function(calendarDate){ | |
if( ! this.startDate && ! this.endDate){ | |
return false; | |
} | |
if(calendarDate.date === false){ | |
return false; | |
} | |
// Is it the first date? | |
if( moment( this.dateFormat(calendarDate.data) ).isSame(this.dateFormat(this.startDate), 'day')){ | |
return true; | |
} | |
if( moment( this.dateFormat(calendarDate.data) ).isSame(this.dateFormat(this.endDate), 'day')){ | |
return true; | |
} | |
if( this.isBetweenSelectedDates(calendarDate.data)){ | |
return true; | |
} | |
return false; | |
}, | |
selectedClass : function(day){ | |
if(this.isSelected(day)){ | |
return 'selected'; | |
} | |
return ''; | |
}, | |
dayClass : function(day){ | |
if(this.isDay(day)){ | |
return 'day'; | |
} | |
return ''; | |
}, | |
betweenClass(calendarDate){ | |
if(this.isDay(calendarDate) && this.isBetweenSelectedDates(calendarDate.data)){ | |
return 'between'; | |
} | |
}, | |
isBetweenSelectedDates(day){ | |
if( ! this.startDate || ! this.endDate) return false; | |
var date = moment(this.dateFormat(day), "YYYY-MM-DD"); | |
var start = moment(this.dateFormat(this.startDate), "YYYY-MM-DD"); | |
var end = moment(this.dateFormat(this.endDate), "YYYY-MM-DD"); | |
var between = date.isBetween( start, end ); | |
return between; | |
}, | |
isBefore(thisDate, isBeforeThis){ | |
return moment(this.dateFormat(thisDate), 'YYYY-MM-DD').isBefore( moment(this.dateFormat(isBeforeThis), 'YYYY-MM-DD') ); | |
}, | |
isDay : function(day){ | |
return day.date !== false; | |
}, | |
dateFormat(day){ | |
return day.year + '-' + (day.month + 1) + '-' + day.day; | |
} | |
} | |
} | |
</script> | |
<style lang="scss"> | |
.calendar__week, .calendar__labels{ | |
display:flex; | |
} | |
.calendar__day, .calendar__label{ | |
flex:1; | |
box-sizing:border-box; | |
text-align:center; | |
padding:10px; | |
&:hover{ | |
background:#eaeaea; | |
} | |
&.selected{ | |
background:#33fa33; | |
} | |
} | |
</style> |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment