Skip to content
Draft
Show file tree
Hide file tree
Changes from 2 commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
1 change: 1 addition & 0 deletions docs/guide/Props/README.md
Original file line number Diff line number Diff line change
Expand Up @@ -3,6 +3,7 @@

| Prop | Type | Default | Description |
| ----------------------------- | -----------------| ----------- | ----------------------------------------------- |
| append-to-body | Boolean | | Append datepicker calendar to body |
| autofocus | String | | Sets html `autofocus` attribute on input |
| bootstrap-styling | Boolean | false | Use bootstrap v4 styling classes. |
| calendar-button | Boolean | false | Show an icon that that can be clicked |
Expand Down
21 changes: 20 additions & 1 deletion example/Demo.vue
Original file line number Diff line number Diff line change
Expand Up @@ -3,7 +3,10 @@
<h1>Datepicker Examples</h1>
<div class="example">
<h3>Default datepicker...</h3>
<Datepicker placeholder="Select Date" />
<Datepicker
placeholder="Select Date"
:append-to-body="true"
/>
<code>
&lt;datepicker placeholder="Select Date"&gt;&lt;/datepicker&gt;
</code>
Expand Down Expand Up @@ -37,6 +40,7 @@
<Datepicker
v-model="vModelExample"
placeholder="Select Date"
:append-to-body="true"
/>
<code>
&lt;datepicker placeholder="Select Date" v-model="vmodelexample"&gt;&lt;/datepicker&gt;
Expand All @@ -45,6 +49,18 @@
<p>{{ vModelExample }}</p>
</div>

<div class="example overflow-scroll">
<h3>Append datepicker to body</h3>
<Datepicker
:append-to-body="true"
/>
<h3>Don't append datepicker to body</h3>
<Datepicker />
<code>
&lt;datepicker :append-to-body="true"&gt;&lt;/datepicker&gt;
</code>
</div>

<div class="example">
<h3>Format datepicker</h3>
<Datepicker :format="format" />
Expand Down Expand Up @@ -499,4 +515,7 @@ h5 {
font-size: 80%;
display: block;
}
.overflow-scroll{
overflow:scroll
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Formatting: overflow: scroll;

}
</style>
312 changes: 312 additions & 0 deletions src/components/Calendar.vue
Original file line number Diff line number Diff line change
@@ -0,0 +1,312 @@
<template>
<div
ref="datepicker"
:class="[calendarClass, 'vdp-datepicker__calendar']"
:style="calendarStyle"
@mousedown.prevent
>
<slot name="beforeCalendarHeader" />
<component
:is="currentPicker"
:page-date="pageDate"
:selected-date="selectedDate"
:allowed-to-show-view="allowedToShowView"
:translation="translation"
:page-timestamp="pageTimestamp"

:is-rtl="isRtl"
:use-utc="useUtc"
:show-header="showHeader"
:full-month-name="fullMonthName"
:monday-first="mondayFirst"
:day-cell-content="dayCellContent"
:highlighted="highlighted"
:disabled-dates="disabledDates"

@select-date="selectDate"
@changed-month="handleChangedMonthFromDayPicker"
@selected-disabled="selectDisabledDate"

@select-month="selectMonth"
@changed-year="setPageDate"
@show-month-calendar="showSpecificCalendar('Month')"

@select-year="selectYear"
@changed-decade="setPageDate"
@show-year-calendar="showSpecificCalendar('Year')"
>
<template
v-for="slotKey of calendarSlots"
>
<slot
:name="`${slotKey}`"
:item="slotKey"
/>
</template>
</component>
<slot name="calendarFooter" />
</div>
</template>
<script>
import { makeDateUtils } from '~/utils/DateUtils'
import PickerDay from '~/components/PickerDay'
import PickerMonth from '~/components/PickerMonth'
import PickerYear from '~/components/PickerYear'
import calendarProps from '~/mixins/calendarProps'
import sharedProps from '~/mixins/sharedProps'
import calendarSlots from '~/utils/calendarSlots'

export default {
name: 'Calendar',
components: {
PickerDay,
PickerMonth,
PickerYear,
},
mixins: [
calendarProps,
sharedProps,
],
props: {
translation: {
type: Object,
default() {
return {}
},
},
open: {
type: Boolean,
default: false,
},
value: {
type: Date,
default: null,
},
},
data() {
const constructedDateUtils = makeDateUtils(this.useUtc)
const startDate = constructedDateUtils.getNewDateObject(this.openDate)
const pageTimestamp = constructedDateUtils.setDate(startDate, 1)
return {
/*
* Vue cannot observe changes to a Date Object so date must be stored as a timestamp
* This represents the first day of the current viewing month
* {Number}
*/
pageTimestamp,
/*
* Selected Date
* {Date}
*/
selectedDate: null,
calendarSlots,
currentPicker: '',
utils: constructedDateUtils,
}
},
computed: {
pageDate() {
return new Date(this.pageTimestamp)
},

calendarStyle() {
return {
position: this.isInline ? 'static' : undefined,
}
},
isInline() {
return !!this.inline
},

computedInitialView() {
if (!this.initialView) {
return this.minimumView
}

return this.initialView
},
},
watch: {
initialView() {
this.setInitialView()
},
openDate() {
this.setPageDate()
},
value: {
handler(newValue) {
this.setValue(newValue)
},
immediate: true,
},
},
mounted() {
this.init()
},
methods: {
/**
* Initiate the component
*/
init() {
this.setInitialView()
},
/**
* @param {Object} date
*/
selectDate(date) {
this.setDate(date.timestamp)
if (!this.isInline) {
this.close(true)
}
this.$emit('reset-typed-date', this.utils.getNewDateObject())
},
/**
* @param {Object} date
*/
selectDisabledDate(date) {
this.$emit('selected-disabled', date)
},
/**
* @param {Object} month
*/
selectMonth(month) {
const date = new Date(month.timestamp)
if (this.allowedToShowView('day')) {
this.setPageDate(date)
this.$emit('changed-month', month)
this.showSpecificCalendar('Day')
} else {
this.selectDate(month)
}
},
/**
* @param {Object} year
*/
selectYear(year) {
const date = new Date(year.timestamp)
if (this.allowedToShowView('month')) {
this.setPageDate(date)
this.$emit('changed-year', year)
this.showSpecificCalendar('Month')
} else {
this.selectDate(year)
}
},
/**
* Handles a month change from the day picker
*/
handleChangedMonthFromDayPicker(date) {
this.setPageDate(date)
this.$emit('changed-month', date)
},

/**
* Show a specific picker
* @return {Boolean}
*/
showSpecificCalendar(type) {
if (type) {
if (!this.allowedToShowView(type.toLowerCase())) {
return false
}
this.currentPicker = `Picker${type}`
return true
}
this.currentPicker = ''
return false
},

/**
* Sets the initial picker page view: day, month or year
*/
setInitialView() {
const initialView = this.computedInitialView
if (!this.allowedToShowView(initialView)) {
throw new Error(`initialView '${this.initialView}' cannot be rendered based on minimum '${this.minimumView}' and maximum '${this.maximumView}'`)
}
switch (initialView) {
case 'year':
this.showSpecificCalendar('Year')
break
case 'month':
this.showSpecificCalendar('Month')
break
default:
this.showSpecificCalendar('Day')
break
}
},

/**
* Are we allowed to show a specific picker view?
* @param {String} view
* @return {Boolean}
*/
allowedToShowView(view) {
const views = [
'day',
'month',
'year',
]
const minimumViewIndex = views.indexOf(this.minimumView)
const maximumViewIndex = views.indexOf(this.maximumView)
const viewIndex = views.indexOf(view)

return viewIndex >= minimumViewIndex && viewIndex <= maximumViewIndex
},

/**
* Sets the date that the calendar should open on
*/
setPageDate(date) {
let dateTemp = date
if (!dateTemp) {
if (this.openDate) {
dateTemp = new Date(this.openDate)
} else {
dateTemp = new Date()
}
dateTemp = this.utils.resetDateTime(dateTemp)
}
this.pageTimestamp = this.utils.setDate(new Date(dateTemp), 1)
},
/**
* Set the selected date
* @param {Number} timestamp
*/
setDate(timestamp) {
const date = new Date(timestamp)
this.selectedDate = date
this.setPageDate(date)
this.$emit('selected', date)
this.$emit('input', date)
},

/**
* Set the datepicker value
* @param {Date|String|Number|null} date
*/
setValue(date) {
let dateTemp = date
if (typeof dateTemp === 'string' || typeof dateTemp === 'number') {
const parsed = new Date(dateTemp)
dateTemp = Number.isNaN(parsed.valueOf()) ? null : parsed
}
if (!dateTemp) {
this.setPageDate()
this.selectedDate = null
return
}
this.selectedDate = dateTemp
this.setPageDate(dateTemp)
},
close() {
this.$emit('close')
},
},
}
</script>

<style lang="scss">
@import '../styles/calendar.scss';
</style>
5 changes: 3 additions & 2 deletions src/components/DateInput.vue
Original file line number Diff line number Diff line change
Expand Up @@ -4,8 +4,7 @@
<!-- Calendar Button -->
<span
v-if="calendarButton"
:class="{'input-group-prepend' : bootstrapStyling}"
:style="{'cursor:not-allowed;' : disabled}"
:class="{'input-group-prepend' : bootstrapStyling, 'calendar-btn-disabled': disabled}"
class="vdp-datepicker__calendar-button"
@click="showCalendar(true)"
>
Expand Down Expand Up @@ -63,11 +62,13 @@
<script>
import { makeDateUtils } from '~/utils/DateUtils'
import inputProps from '~/mixins/inputProps'
import sharedProps from '~/mixins/sharedProps'

export default {
name: 'DatepickerInput',
mixins: [
inputProps,
sharedProps,
],
props: {
selectedDate: {
Expand Down
Loading