Skip to content

Commit

Permalink
Merge 41cdbb9 into bf28bca
Browse files Browse the repository at this point in the history
  • Loading branch information
justb3a committed Nov 5, 2018
2 parents bf28bca + 41cdbb9 commit b58ae54
Show file tree
Hide file tree
Showing 11 changed files with 213 additions and 38 deletions.
61 changes: 31 additions & 30 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -99,36 +99,37 @@ Inline always open version
```
## Available props

| Prop | Type | Default | Description |
|-------------------------------|-----------------|-------------|------------------------------------------|
| value | Date\|String | | Date value of the datepicker |
| name | String | | Input name property |
| id | String | | Input id |
| format | String\|Function| dd MMM yyyy | Date formatting string or function |
| full-month-name | Boolean | false | To show the full month name |
| language | Object | en | Translation for days and months |
| disabled-dates | Object | | See below for configuration |
| placeholder | String | | Input placeholder text |
| inline | Boolean | | To show the datepicker always open |
| calendar-class | String\|Object | | CSS class applied to the calendar el |
| input-class | String\|Object | | CSS class applied to the input el |
| wrapper-class | String\|Object | | CSS class applied to the outer div |
| monday-first | Boolean | false | To start the week on Monday |
| clear-button | Boolean | false | Show an icon for clearing the date |
| clear-button-icon | String | | Use icon for button (ex: fa fa-times) |
| calendar-button | Boolean | false | Show an icon that that can be clicked |
| calendar-button-icon | String | | Use icon for button (ex: fa fa-calendar) |
| calendar-button-icon-content | String | | Use for material-icons (ex: event) |
| day-cell-content | Function | | Use to render custom content in day cell |
| bootstrap-styling | Boolean | false | Output bootstrap v4 styling classes. |
| initial-view | String | minimumView | If set, open on that view |
| disabled | Boolean | false | If true, disable Datepicker on screen |
| required | Boolean | false | Sets html required attribute on input |
| typeable | Boolean | false | If true, allow the user to type the date |
| use-utc | Boolean | false | use UTC for time calculations |
| open-date | Date\|String | | If set, open on that date |
| minimum-view | String | 'day' | If set, lower-level views won't show |
| maximum-view | String | 'year' | If set, higher-level views won't show |
| Prop | Type | Default | Description |
|------------------------------|------------------|-------------|------------------------------------------|
| value | Date\|String | | Date value of the datepicker |
| name | String | | Input name property |
| id | String | | Input id |
| format | String\|Function | dd MMM yyyy | Date formatting string or function |
| full-month-name | Boolean | false | To show the full month name |
| language | Object | en | Translation for days and months |
| disabled-dates | Object | | See below for configuration |
| placeholder | String | | Input placeholder text |
| inline | Boolean | | To show the datepicker always open |
| calendar-class | String\|Object | | CSS class applied to the calendar el |
| input-class | String\|Object | | CSS class applied to the input el |
| wrapper-class | String\|Object | | CSS class applied to the outer div |
| monday-first | Boolean | false | To start the week on Monday |
| calendarweek | Boolean | false | To display the calendar week |
| clear-button | Boolean | false | Show an icon for clearing the date |
| clear-button-icon | String | | Use icon for button (ex: fa fa-times) |
| calendar-button | Boolean | false | Show an icon that that can be clicked |
| calendar-button-icon | String | | Use icon for button (ex: fa fa-calendar) |
| calendar-button-icon-content | String | | Use for material-icons (ex: event) |
| day-cell-content | Function | | Use to render custom content in day cell |
| bootstrap-styling | Boolean | false | Output bootstrap v4 styling classes. |
| initial-view | String | minimumView | If set, open on that view |
| disabled | Boolean | false | If true, disable Datepicker on screen |
| required | Boolean | false | Sets html required attribute on input |
| typeable | Boolean | false | If true, allow the user to type the date |
| use-utc | Boolean | false | use UTC for time calculations |
| open-date | Date\|String | | If set, open on that date |
| minimum-view | String | 'day' | If set, lower-level views won't show |
| maximum-view | String | 'year' | If set, higher-level views won't show |


## Events
Expand Down
2 changes: 2 additions & 0 deletions src/components/Datepicker.vue
Original file line number Diff line number Diff line change
Expand Up @@ -46,6 +46,7 @@
:pageTimestamp="pageTimestamp"
:isRtl="isRtl"
:mondayFirst="mondayFirst"
:calendarWeek="calendarWeek"
:dayCellContent="dayCellContent"
:use-utc="useUtc"
@changedMonth="handleChangedMonthFromDayPicker"
Expand Down Expand Up @@ -135,6 +136,7 @@ export default {
inputClass: [String, Object, Array],
wrapperClass: [String, Object, Array],
mondayFirst: Boolean,
calendarWeek: Boolean,
clearButton: Boolean,
clearButtonIcon: String,
calendarButton: Boolean,
Expand Down
43 changes: 38 additions & 5 deletions src/components/PickerDay.vue
Original file line number Diff line number Diff line change
@@ -1,5 +1,5 @@
<template>
<div :class="[calendarClass, 'vdp-datepicker__calendar']" v-show="showDayView" :style="calendarStyle" @mousedown.prevent>
<div :class="[calendarClass, 'vdp-datepicker__calendar', {'vdp-datepicker__calendar--week': calendarWeek}]" v-show="showDayView" :style="calendarStyle" @mousedown.prevent>
<slot name="beforeCalendarHeader"></slot>
<header>
<span
Expand All @@ -12,17 +12,22 @@
class="next"
:class="{'disabled': isRightNavDisabled}">&gt;</span>
</header>
<div :class="isRtl ? 'flex-rtl' : ''">
<div :class="{ 'flex-ltr': !isRtl, 'flex-rtl': isRtl }">
<span v-if="calendarWeek" class="cell day-header">{{ translation.calendarweek }}</span>
<span class="cell day-header" v-for="d in daysOfWeek" :key="d.timestamp">{{ d }}</span>
<span v-if="calendarWeek" class="cell weeknumber">{{ weeknumber(0) }}</span>
<template v-if="blankDays > 0">
<span class="cell day blank" v-for="d in blankDays" :key="d.timestamp"></span>
</template><!--
--><span class="cell day"
v-for="day in days"
</template>
<template v-for="(day, index) in days">
<span v-if="showCalendarWeek(day, index)" class="cell weeknumber">{{ weeknumber(index + 1) }}</span>
<span class="cell day"
:key="day.timestamp"
:class="dayClasses(day)"
v-html="dayCellContent(day)"
@click="selectDate(day)"></span>
<span v-if="showCalendarWeek(day, index, false)" class="cell weeknumber">{{ weeknumber(index + 1) }}</span>
</template>
</div>
</div>
</template>
Expand All @@ -47,6 +52,7 @@ export default {
translation: Object,
isRtl: Boolean,
mondayFirst: Boolean,
calendarWeek: Boolean,
useUtc: Boolean
},
data () {
Expand Down Expand Up @@ -367,6 +373,33 @@ export default {
*/
isDefined (prop) {
return typeof prop !== 'undefined' && prop
},
/**
* Whether the calender week shoud be displayed
* @param {Object} day
* @param {Number} index
* @param {Boolean} before
* @return {Boolean}
*/
showCalendarWeek (day, index, before = true) {
let show = false
if (this.calendarWeek && day.isSunday) {
if (before) {
show = !this.mondayFirst && index > 0
} else {
show = this.mondayFirst && index < this.days.length - 1
}
}
return show
},
/**
* Get calendar week for specific day
* @param {Number} index
* @return {Number}
*/
weeknumber (index) {
return this.utils.getWeekNumber(new Date(this.days[index].timestamp))
}
}
}
Expand Down
14 changes: 13 additions & 1 deletion src/locale/Language.js
Original file line number Diff line number Diff line change
@@ -1,9 +1,10 @@
export default class Language {
constructor (language, months, monthsAbbr, days) {
constructor (language, months, monthsAbbr, days, calendarweek) {
this.language = language
this.months = months
this.monthsAbbr = monthsAbbr
this.days = days
this.calendarweek = calendarweek
this.rtl = false
this.ymd = false
this.yearSuffix = ''
Expand Down Expand Up @@ -52,6 +53,17 @@ export default class Language {
}
this._days = days
}

get calendarweek () {
return this._calendarweek
}

set calendarweek (calendarweek = '') {
if (typeof calendarweek !== 'string') {
throw new TypeError('Calendar week must be a string')
}
this._calendarweek = calendarweek
}
}
// eslint-disable-next-line
;
3 changes: 2 additions & 1 deletion src/locale/translations/de.js
Original file line number Diff line number Diff line change
Expand Up @@ -4,7 +4,8 @@ export default new Language(
'German',
['Januar', 'Februar', 'März', 'April', 'Mai', 'Juni', 'Juli', 'August', 'September', 'Oktober', 'November', 'Dezember'],
['Jan', 'Feb', 'Mär', 'Apr', 'Mai', 'Jun', 'Jul', 'Aug', 'Sep', 'Okt', 'Nov', 'Dez'],
['So.', 'Mo.', 'Di.', 'Mi.', 'Do.', 'Fr.', 'Sa.']
['So.', 'Mo.', 'Di.', 'Mi.', 'Do.', 'Fr.', 'Sa.'],
'KW'
)
// eslint-disable-next-line
;
3 changes: 2 additions & 1 deletion src/locale/translations/en.js
Original file line number Diff line number Diff line change
Expand Up @@ -4,7 +4,8 @@ export default new Language(
'English',
['January', 'February', 'March', 'April', 'May', 'June', 'July', 'August', 'September', 'October', 'November', 'December'],
['Jan', 'Feb', 'Mar', 'Apr', 'May', 'Jun', 'Jul', 'Aug', 'Sep', 'Oct', 'Nov', 'Dec'],
['Sun', 'Mon', 'Tue', 'Wed', 'Thu', 'Fri', 'Sat']
['Sun', 'Mon', 'Tue', 'Wed', 'Thu', 'Fri', 'Sat'],
'CW'
)
// eslint-disable-next-line
;
17 changes: 17 additions & 0 deletions src/styles/style.styl
Original file line number Diff line number Diff line change
Expand Up @@ -58,6 +58,10 @@
.disabled
color #ddd
cursor default
.flex-ltr
display flex
width 100%
flex-wrap wrap
.flex-rtl
display flex
width inherit
Expand Down Expand Up @@ -106,6 +110,19 @@
.year
width 33.333%

.vdp-datepicker__calendar--week
.weeknumber
color #999
.cell
width (100/8)%
header
span
width (100 - (100/8)*2)%

.prev
.next
width (100/8)%

.vdp-datepicker__clear-button
.vdp-datepicker__calendar-button
cursor pointer
Expand Down
15 changes: 15 additions & 0 deletions src/utils/DateUtils.js
Original file line number Diff line number Diff line change
Expand Up @@ -53,6 +53,21 @@ const utils = {
return this.useUtc ? date.getUTCMinutes() : date.getMinutes()
},

/**
* Returns the weeknumber, using UTC or not
* - thursday in current week decides the year
* - january 4 is always in week 1
* - adjust to thursday in week 1 and count number of weeks from date to week1
* @param {Date} date
*/
getWeekNumber (date) {
this.useUtc ? date.setUTCHours(0, 0, 0, 0) : date.setHours(0, 0, 0, 0)
this.setDate(date, this.getDate(date) + 3 - (this.getDay(date) + 6) % 7)
const week1 = new Date(this.getFullYear(date), 0, 4)

return 1 + Math.round(((date.getTime() - week1.getTime()) / 86400000 - 3 + (this.getDay(week1) + 6) % 7) / 7)
},

/**
* Sets the full year, using UTC or not
* @param {Date} date
Expand Down
17 changes: 17 additions & 0 deletions test/unit/specs/DateUtils.spec.js
Original file line number Diff line number Diff line change
Expand Up @@ -98,6 +98,17 @@ describe('DateUtils', () => {
it('getMonthName accepts a number', () => {
expect(DateUtils.getMonthNameAbbr(3, en.monthsAbbr)).toEqual('Apr')
})

it('should give correct week number', () => {
expect(DateUtils.getWeekNumber(new Date(2018, 9, 31))).toEqual(44)
expect(DateUtils.getWeekNumber(new Date(2018, 9, 22))).toEqual(43)
expect(DateUtils.getWeekNumber(new Date(2018, 9, 20))).toEqual(42)
expect(DateUtils.getWeekNumber(new Date(2018, 9, 20), true)).toEqual(42)
})

it('calendarweek equals cw', () => {
expect(en.calendarweek).toEqual('CW')
})
})

describe('daysInMonth', () => {
Expand Down Expand Up @@ -163,6 +174,12 @@ describe('UTC functions', () => {
expect(utcUtils.getMinutes(date)).toEqual(date.getUTCMinutes())
})

it('getMinutes', () => {
const date = new Date(2018, 9, 31)
expect(DateUtils.getMinutes(date)).toEqual(date.getMinutes())
expect(utcUtils.getMinutes(date)).toEqual(date.getUTCMinutes())
})

it('setFullYear', () => {
const date = getAmbiguousDate()
expect(DateUtils.setFullYear(date, 2018)).toEqual(date.setFullYear(2018))
Expand Down
4 changes: 4 additions & 0 deletions test/unit/specs/Locale/Language.spec.js
Original file line number Diff line number Diff line change
Expand Up @@ -18,4 +18,8 @@ describe('Language class', () => {
it('should throw when there are not exacty 7 days', () => {
expect(() => new Language('a', months, months, ['m', 't', 'w'])).toThrow(RangeError)
})

it('should throw when calendarweek is not a string', () => {
expect(() => new Language('a', months, months, days, 1)).toThrow(TypeError)
})
})
72 changes: 72 additions & 0 deletions test/unit/specs/PickerDay/calendarWeek.spec.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,72 @@
import PickerDay from '@/components/PickerDay.vue'
import {shallow} from '@vue/test-utils'
import {en} from '@/locale'

describe('PickerDay: Datepicker with calendar week and sunday as first day of week', () => {
let wrapper
beforeEach(() => {
wrapper = shallow(PickerDay, {
propsData: {
calendarWeek: true,
translation: en,
allowedToShowView: () => true,
pageDate: new Date(2018, 9, 1)
}
})
})

it('should return false to show calendar week if day is sunday and index equals zero', () => {
expect(wrapper.vm.showCalendarWeek(wrapper.vm.days[0], 0)).toEqual(false)
})

it('should return false to show calendar week if day is not sunday', () => {
expect(wrapper.vm.showCalendarWeek(wrapper.vm.days[1], 1)).toEqual(false)
expect(wrapper.vm.showCalendarWeek(wrapper.vm.days[2], 2)).toEqual(false)
expect(wrapper.vm.showCalendarWeek(wrapper.vm.days[3], 3)).toEqual(false)
expect(wrapper.vm.showCalendarWeek(wrapper.vm.days[4], 4)).toEqual(false)
expect(wrapper.vm.showCalendarWeek(wrapper.vm.days[5], 5)).toEqual(false)
expect(wrapper.vm.showCalendarWeek(wrapper.vm.days[7], 7)).toEqual(false)
})

it('should return true to show calendar week if day is sunday', () => {
expect(wrapper.vm.showCalendarWeek(wrapper.vm.days[6], 6)).toEqual(true)
expect(wrapper.vm.showCalendarWeek(wrapper.vm.days[13], 13)).toEqual(true)
expect(wrapper.vm.showCalendarWeek(wrapper.vm.days[20], 20)).toEqual(true)
expect(wrapper.vm.showCalendarWeek(wrapper.vm.days[27], 27)).toEqual(true)
})
})

describe('PickerDay: Datepicker with calendar week and monday as first day of week', () => {
let wrapper
beforeEach(() => {
wrapper = shallow(PickerDay, {
propsData: {
calendarWeek: true,
mondayFirst: true,
translation: en,
allowedToShowView: () => true,
pageDate: new Date(2019, 2, 1)
}
})
})

it('should return false to show calendar week if day is sunday and index equals number of days', () => {
expect(wrapper.vm.showCalendarWeek(wrapper.vm.days[30], 30, false)).toEqual(false)
})

it('should return false to show calendar week if day is not sunday', () => {
expect(wrapper.vm.showCalendarWeek(wrapper.vm.days[1], 1, false)).toEqual(false)
expect(wrapper.vm.showCalendarWeek(wrapper.vm.days[3], 3, false)).toEqual(false)
expect(wrapper.vm.showCalendarWeek(wrapper.vm.days[4], 4, false)).toEqual(false)
expect(wrapper.vm.showCalendarWeek(wrapper.vm.days[5], 5, false)).toEqual(false)
expect(wrapper.vm.showCalendarWeek(wrapper.vm.days[6], 6, false)).toEqual(false)
expect(wrapper.vm.showCalendarWeek(wrapper.vm.days[7], 7, false)).toEqual(false)
})

it('should return true to show calendar week if day is sunday', () => {
expect(wrapper.vm.showCalendarWeek(wrapper.vm.days[2], 2, false)).toEqual(true)
expect(wrapper.vm.showCalendarWeek(wrapper.vm.days[9], 9, false)).toEqual(true)
expect(wrapper.vm.showCalendarWeek(wrapper.vm.days[16], 16, false)).toEqual(true)
expect(wrapper.vm.showCalendarWeek(wrapper.vm.days[23], 23, false)).toEqual(true)
})
})

0 comments on commit b58ae54

Please sign in to comment.