Skip to content

Commit

Permalink
Added linkedTo and openOffset attributes along with the openDate beha…
Browse files Browse the repository at this point in the history
…viour.
  • Loading branch information
anthonyjb committed Feb 24, 2020
1 parent b9c1d73 commit 6bec42a
Show file tree
Hide file tree
Showing 6 changed files with 125 additions and 56 deletions.
7 changes: 6 additions & 1 deletion module/calendar.js
Original file line number Diff line number Diff line change
Expand Up @@ -335,7 +335,7 @@ export class Calendar {

// Not in the current month (blocked)
if (date.getMonth() !== this.month) {
classList.add(css['blocked'])
classList.add(css['outside-month'])
}

// Blocked by the dates test (blocked)
Expand Down Expand Up @@ -411,6 +411,11 @@ Calendar.css = {
*/
'next': 'mh-calendar__next',

/**
* Applied to a date in the calendar which is outside of the current month.
*/
'outside-month': 'mh-calendar__date--outside-month',

/**
* Applied to the calendar's 'previous month' navigation element.
*/
Expand Down
51 changes: 26 additions & 25 deletions module/date-picker.js
Original file line number Diff line number Diff line change
Expand Up @@ -42,6 +42,12 @@ export class DatePicker {
*/
'format': 'human',

/**
* Another element (input) this date picker is linked to, the
* element must also be a date picker.
*/
'linkedTo': null,

/**
* The latest date that can be selected.
*/
Expand All @@ -64,6 +70,13 @@ export class DatePicker {
*/
'noPopup': false,

/**
* The number of days to offset the open date when opening the
* date picker from a linked date picker (see behaviours >
* openDate > offset.
*/
'openOffset': 0,

/**
* A list of parsers that will be used to attempt to parse
* an input string as a date (strings are parsed using each
Expand Down Expand Up @@ -107,6 +120,9 @@ export class DatePicker {
})
}

if (typeof this._options.linkedTo === 'string') {
this._options.linkedTo = $.one(this._options.linkedTo)
}
if (typeof this._options.monthNames === 'string') {
this._options.monthNames = _toArray(this._options.monthNames)
}
Expand Down Expand Up @@ -375,11 +391,13 @@ export class DatePicker {
this._options.parsers,
this.input.value
)

if (date === null) {
const openDate = this.constructor
.behaviours
.openDate[this._behaviours.openDate]
this.calendar.goto(...openDate(this))
.openDate[this._behaviours.openDate](this)
this.calendar.goto(openDate.getMonth(), openDate.getFullYear())
this.calendar.date = openDate
} else {
this.calendar.goto(date.getMonth(), date.getFullYear())
this.calendar.date = date
Expand Down Expand Up @@ -512,36 +530,19 @@ DatePicker.behaviours = {
'openDate': {

/**
* Offset by X months from the value of another field or the current
* Offset by X days from the value of another field or the current
* month.
*/
'offset': (inst) => {

// Get the date value for the linked to field
const linkedSelector = inst
._dom
.input
.getAttribute('data-mh-date-picker--linked-to')
const linkedInput = $.one(linkedSelector)
let date = linkedInput._mhDatePicker.calendar.date

// Get the month offset to apply
let offset = inst
._dom
.input
.getAttribute('data-mh-date-picker--open-offset') || 0
offset = parseInt(offset, 10)
let date = inst._options.linkedTo._mhDatePicker.calendar.date

// Apply the offset
for (let i = 0; i < offset; i += 1) {
if (date.getMonth() == 11) {
date = new Date(date.getFullYear() + 1, 0, 1)
} else {
date = new Date(date.getFullYear(), date.getMonth() + 1, 1)
}
}
date.setDate(date.getDate() + inst._options.openOffset)
date.setHours(0, 0, 0, 0)

return [date.getMonth(), date.getFullYear()]
return date
},

/**
Expand All @@ -550,7 +551,7 @@ DatePicker.behaviours = {
'today': (inst) => {
const date = new Date()
date.setHours(0, 0, 0, 0)
return [date.getMonth(), date.getFullYear()]
return date
}

}
Expand Down
2 changes: 1 addition & 1 deletion package.json
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
{
"name": "manhattan-date-picker",
"version": "1.0.1",
"version": "1.0.2",
"description": "Date parsing and picking for form fields.",
"engines": {
"node": ">=8.9.4"
Expand Down
9 changes: 7 additions & 2 deletions scss/_calendar.scss
Original file line number Diff line number Diff line change
Expand Up @@ -102,7 +102,7 @@
&--selected {
background: #e26a6a;
border-radius: 20px;
color: #fff;
color: #fff !important;
font-weight: bold;

&:hover {
Expand Down Expand Up @@ -132,8 +132,13 @@
}
}

&--outside-month {
color: #999;
font-weight: normal;
}

&--selected.mh-calendar__date--blocked {
color: #fff;
}
}
}
}
27 changes: 5 additions & 22 deletions spec/calendar.spec.js
Original file line number Diff line number Diff line change
Expand Up @@ -381,35 +381,19 @@ describe('Calendar', () => {
.true
})

it('should add blocked class to dates that outside of the current '
+ 'month', () => {
it('should add outside month class to dates that outside of the current '
+ 'current month', () => {

for (let dateElm of calendar._dom.dates.childNodes) {
if (dateElm._date.getMonth() === 0) {
dateElm.classList
.contains(Calendar.css['blocked'])
.contains(Calendar.css['outside-month'])
.should
.be
.false
} else {
dateElm.classList
.contains(Calendar.css['blocked'])
.should
.be
.true
}
}

})

it('should add blocked class to dates that don\'t pass the given '
+ 'testDate function', () => {

calendar.goto(1, 2010)
for (let dateElm of calendar._dom.dates.childNodes) {
if (dateElm._date.getDate() === 5) {
dateElm.classList
.contains(Calendar.css['blocked'])
.contains(Calendar.css['outside-month'])
.should
.be
.true
Expand Down Expand Up @@ -485,10 +469,9 @@ describe('Calendar', () => {
})

it('should do nothing if the date picked is blocked', () => {

calendar.goto(6, 2010)
const {date} = calendar
const [dateElm] = calendar._dom.dates.childNodes
dateElm.classList.add(Calendar.css['blocked'])
$.dispatch(dateElm, 'click')
calendar.date.getTime().should.equal(date.getTime())
onPicked.should.not.have.been.called
Expand Down
85 changes: 80 additions & 5 deletions spec/date-picker.spec.js
Original file line number Diff line number Diff line change
Expand Up @@ -14,6 +14,7 @@ chai.use(require('sinon-chai'))
describe('DatePicker', () => {

let inputElm = null
let otherInputElm = null

beforeEach(() => {
inputElm = $.create(
Expand All @@ -24,10 +25,21 @@ describe('DatePicker', () => {
}
)
document.body.appendChild(inputElm)

otherInputElm = $.create(
'input',
{
'name': 'other_input',
'type': 'text',
'value': '1st March 2017'
}
)
document.body.appendChild(otherInputElm)
})

afterEach(() => {
document.body.removeChild(inputElm)
document.body.removeChild(otherInputElm)
})

describe('constructor', () => {
Expand Down Expand Up @@ -59,6 +71,19 @@ describe('DatePicker', () => {
})
})

describe('linkedTo', () => {
it('should accept a selector string and convert it to an '
+ 'element', () => {

const datePicker = new DatePicker(
inputElm,
{'linkedTo': 'input[name="other_input"]'}
)
const {linkedTo} = datePicker._options
linkedTo.should.equal(otherInputElm)
})
})

describe('maxDate', () => {
it('should accept a date string and convert it to a date', () => {
const datePicker = new DatePicker(
Expand Down Expand Up @@ -421,17 +446,19 @@ describe('DatePicker', () => {
datePicker.calendar.year.should.equal(2017)
})

it('should not set the date for the calendar the input\'s '
+ 'value is not a valid date', () => {
it('should set a default open date for the calendar if the '
+ 'input\'s value is not a valid date', () => {
datePicker.calendar.goto(1, 2010)
datePicker.calendar.date = new Date(2010, 1, 5)
inputElm.value = 'querty'
datePicker.open()

const {date} = datePicker.calendar
date.getTime().should.equal((new Date(2010, 1, 5)).getTime())
datePicker.calendar.month.should.equal(1)
datePicker.calendar.year.should.equal(2010)
const today = new Date()
today.setHours(0, 0, 0, 0)
date.getTime().should.equal(today.getTime())
datePicker.calendar.month.should.equal(today.getMonth())
datePicker.calendar.year.should.equal(today.getFullYear())
})

it('should call _track to make sure the picker is inline with '
Expand Down Expand Up @@ -664,6 +691,54 @@ describe('DatePicker', () => {
})
})

describe('behaviours > openDate', () => {
const behaviours = DatePicker.behaviours.openDate
let datePicker = null
let otherDatePicker = null

beforeEach(() => {
datePicker = new DatePicker(
inputElm,
{
'linkedTo': 'input[name="other_input"]',
'openOffset': 1
}
)
datePicker.init()
otherDatePicker = new DatePicker(otherInputElm)
otherDatePicker.init()
})

afterEach(() => {
datePicker.destroy()
otherDatePicker.destroy()
})

describe('offset', () => {

it('should return the day after the linked input\'s date', () => {
const date = behaviours.offset(datePicker)
const tomorrow = new Date()
tomorrow.setHours(0, 0, 0, 0)
tomorrow.setDate(tomorrow.getDate() + 1)
date.getTime().should.equal(tomorrow.getTime())
})

})

describe('today', () => {

it('should return todays date', () => {
const date = behaviours.today(datePicker)
const today = new Date()
today.setHours(0, 0, 0, 0)
date.getTime().should.equal(today.getTime())
})

})

})

describe('events', () => {
let datePicker = null

Expand Down

0 comments on commit 6bec42a

Please sign in to comment.