diff --git a/spec/tests/datepicker/datepickerSpec.js b/spec/tests/datepicker/datepickerSpec.js index d2cc8f613d..0f45d9e518 100644 --- a/spec/tests/datepicker/datepickerSpec.js +++ b/spec/tests/datepicker/datepickerSpec.js @@ -7,14 +7,16 @@ describe('Datepicker Plugin', () => { `; - beforeEach(() => { - XloadHtml(fixture); - M.Datepicker.init(document.querySelectorAll('.datepicker')); - }); + beforeEach(() => XloadHtml(fixture)); afterEach(() => XunloadFixtures()); describe('Datepicker', () => { + afterEach(() => { + M.Datepicker.getInstance(document.querySelector('.datepicker')).destroy(); + }); + it('should open and close programmatically', (done) => { + M.Datepicker.init(document.querySelectorAll('.datepicker')); const input = document.querySelector('#datepickerInput'); const modal = document.querySelector('.datepicker-modal'); expect(modal).toBeHidden('Should be hidden before datepicker input is focused.'); @@ -40,15 +42,17 @@ describe('Datepicker Plugin', () => { const input = document.querySelector('#datepickerInput'); const today = new Date(); M.Datepicker.init(input, { format: 'mm/dd/yyyy' }).open(); - M.Datepicker.getInstance(input).open(); + const datepicker = M.Datepicker.getInstance(input); + datepicker.open(); setTimeout(() => { const day1 = document.querySelector('.datepicker-modal button[data-day="1"]'); day1.click(); + document.querySelector('.datepicker-done').click(); setTimeout(() => { const year = today.getFullYear(); let month = today.getMonth() + 1; month = month < 10 ? `0${month}` : month; - const value = M.Datepicker.getInstance(input).toString(); + const value = datepicker.toString(); expect(value).toEqual(`${month}/01/${year}`); done(); }, 400); @@ -58,17 +62,18 @@ describe('Datepicker Plugin', () => { it('can have a format function', (done) => { const input = document.querySelector('#datepickerInput'); const today = new Date(); - const formatFn = (date) => `${date.getFullYear() - 100}-${date.getMonth() + 1}-99`; + const formatFn = `${today.getFullYear() - 100}-${today.getMonth() + 1}-99`; M.Datepicker.init(input, { format: formatFn }).open(); - M.Datepicker.getInstance(input).open(); + const datepicker = M.Datepicker.getInstance(input); + datepicker.open(); setTimeout(() => { const day1 = document.querySelector('.datepicker-modal button[data-day="1"]'); day1.click(); + document.querySelector('.datepicker-done').click(); setTimeout(() => { const year = today.getFullYear() - 100; const month = today.getMonth() + 1; - const value = M.Datepicker.getInstance(input).toString(); - expect(value).toEqual(`${year}-${month}-99`); + expect(datepicker.toString()).toEqual(`${year}-${month}-99`); done(); }, 400); }, 400); diff --git a/src/datepicker.ts b/src/datepicker.ts index 5a3b2b5dcd..23a76ec0a2 100644 --- a/src/datepicker.ts +++ b/src/datepicker.ts @@ -394,6 +394,10 @@ export class Datepicker extends Component { return day.getTime() > date.getTime() && day.getTime() < dateEnd.getTime(); } + static _comparePastDate(a: Date, b: Date) { + return a.getTime() < b.getTime() + } + static getInstance(el: HTMLElement): Datepicker { return (el as any).M_Datepicker; } @@ -424,10 +428,11 @@ export class Datepicker extends Component { } if (this.options.isDateRange) { - this.endDateEl = this.el.cloneNode(true); + this.endDateEl = this.el.cloneNode(true); this.endDateEl.classList.add('datepicker-end-date'); this.endDateEl.addEventListener('click', this._handleInputClick); this.endDateEl.addEventListener('keypress', this._handleInputKeydown); + this.endDateEl.addEventListener('change', this._handleInputChange); this.el.parentElement.appendChild(this.endDateEl); } @@ -460,9 +465,9 @@ export class Datepicker extends Component { } /** - * Gets a string representation of the selected date. + * Gets a string representation of the given date. */ - toString(date: Date, format: string | ((d: Date) => string) = null): string { + toString(date: Date = this.date, format: string | ((d: Date) => string) = null): string { format = format || this.options.format; if (typeof format === 'function') return format(date); if (!Datepicker._isDate(date)) return ''; @@ -1030,8 +1035,9 @@ export class Datepicker extends Component { this.el.removeEventListener('change', this._handleInputChange); this.calendarEl.removeEventListener('click', this._handleCalendarClick); if (this.options.isDateRange) { - this.endDateEl.addEventListener('click', this._handleInputClick); - this.endDateEl.addEventListener('keypress', this._handleInputKeydown); + this.endDateEl.removeEventListener('click', this._handleInputClick); + this.endDateEl.removeEventListener('keypress', this._handleInputKeydown); + this.endDateEl.removeEventListener('change', this._handleInputChange); } } @@ -1067,6 +1073,14 @@ export class Datepicker extends Component { ); if (this.endDate == null || !Datepicker._compareDates(selectedDate, this.endDate)) { + if ( + Datepicker._isDate(this.date) && + this.options.isDateRange && + Datepicker._comparePastDate(selectedDate, this.date) + ) { + return; + } + this.setDate( selectedDate, false, @@ -1136,18 +1150,19 @@ export class Datepicker extends Component { // Prevent change event from being fired when triggered by the plugin if (e['detail']?.firedBy === this) return; if (this.options.parse) { - date = this.options.parse(this.el.value, + date = this.options.parse((e.target as HTMLInputElement).value, typeof this.options.format === "function" ? this.options.format(new Date(this.el.value)) : this.options.format); } else { - date = new Date(Date.parse(this.el.value)); + date = new Date(Date.parse((e.target as HTMLInputElement).value)); } if (Datepicker._isDate(date)) { this.setDate(date, false, (e.target as HTMLElement) == this.endDateEl); if (e.type == 'date') { this.setDataDate(e, date); + this.setInputValues(); } } }