Bug 1363672 - Add step support to date picker

This commit is contained in:
janekptacijarabaci 2018-03-30 20:56:33 +02:00 committed by Roy Tam
commit 1cca8d40f3
5 changed files with 64 additions and 18 deletions

View file

@ -1728,9 +1728,10 @@ let DateTimePickerListener = {
// element's value.
value: Object.keys(value).length > 0 ? value
: this._inputElement.value,
step: this._inputElement.step,
min: this._inputElement.min,
max: this._inputElement.max,
step: this._inputElement.getStep(),
stepBase: this._inputElement.getStepBase(),
},
});
break;

View file

@ -45,18 +45,21 @@ function DateKeeper(props) {
* @param {Number} day
* @param {String} min
* @param {String} max
* @param {Number} step
* @param {Number} stepBase
* @param {Number} firstDayOfWeek
* @param {Array<Number>} weekends
* @param {Number} calViewSize
*/
init({ year, month, day, min, max, firstDayOfWeek = 0, weekends = [0], calViewSize = 42 }) {
init({ year, month, day, min, max, step, stepBase, firstDayOfWeek = 0, weekends = [0], calViewSize = 42 }) {
const today = new Date();
const isDateSet = year != undefined && month != undefined && day != undefined;
this.state = {
firstDayOfWeek, weekends, calViewSize,
step, firstDayOfWeek, weekends, calViewSize,
min: new Date(min != undefined ? min : MIN_DATE),
max: new Date(max != undefined ? max : MAX_DATE),
stepBase: new Date(stepBase),
today: this._newUTCDate(today.getFullYear(), today.getMonth(), today.getDate()),
weekHeaders: this._getWeekHeaders(firstDayOfWeek, weekends),
years: [],
@ -192,33 +195,50 @@ function DateKeeper(props) {
* }
*/
getDays() {
// TODO: add step support
const firstDayOfMonth = this._getFirstCalendarDate(this.state.dateObj, this.state.firstDayOfWeek);
const month = this.month;
let days = [];
for (let i = 0; i < this.state.calViewSize; i++) {
const dateObj = this._newUTCDate(firstDayOfMonth.getUTCFullYear(), firstDayOfMonth.getUTCMonth(), firstDayOfMonth.getUTCDate() + i);
const dateObj = this._newUTCDate(firstDayOfMonth.getUTCFullYear(),
firstDayOfMonth.getUTCMonth(),
firstDayOfMonth.getUTCDate() + i);
let classNames = [];
let enabled = true;
if (this.state.weekends.includes(dateObj.getUTCDay())) {
const isWeekend = this.state.weekends.includes(dateObj.getUTCDay());
const isCurrentMonth = month == dateObj.getUTCMonth();
const isSelection = this.state.selection.year == dateObj.getUTCFullYear() &&
this.state.selection.month == dateObj.getUTCMonth() &&
this.state.selection.day == dateObj.getUTCDate();
const isOutOfRange = dateObj.getTime() < this.state.min.getTime() ||
dateObj.getTime() > this.state.max.getTime();
const isToday = this.state.today.getTime() == dateObj.getTime();
const isOffStep = this._checkIsOffStep(dateObj,
this._newUTCDate(dateObj.getUTCFullYear(),
dateObj.getUTCMonth(),
dateObj.getUTCDate() + 1));
if (isWeekend) {
classNames.push("weekend");
}
if (month != dateObj.getUTCMonth()) {
if (!isCurrentMonth) {
classNames.push("outside");
}
if (this.state.selection.year == dateObj.getUTCFullYear() &&
this.state.selection.month == dateObj.getUTCMonth() &&
this.state.selection.day == dateObj.getUTCDate()) {
if (isSelection && !isOutOfRange && !isOffStep) {
classNames.push("selection");
}
if (dateObj.getTime() < this.state.min.getTime() || dateObj.getTime() > this.state.max.getTime()) {
if (isOutOfRange) {
classNames.push("out-of-range");
enabled = false;
}
if (this.state.today.getTime() == dateObj.getTime()) {
if (isToday) {
classNames.push("today");
}
if (isOffStep) {
classNames.push("off-step");
enabled = false;
}
days.push({
dateObj,
classNames,
@ -228,6 +248,24 @@ function DateKeeper(props) {
return days;
},
/**
* Check if a date is off step given a starting point and the next increment
* @param {Date} start
* @param {Date} next
* @return {Boolean}
*/
_checkIsOffStep(start, next) {
// If the increment is larger or equal to the step, it must not be off-step.
if (next - start >= this.state.step) {
return false;
}
// Calculate the last valid date
const lastValidStep = Math.floor((next - 1 - this.state.stepBase) / this.state.step);
const lastValidTimeInMs = lastValidStep * this.state.step + this.state.stepBase.getTime();
// The date is off-step if the last valid date is smaller than the start date
return lastValidTimeInMs < start.getTime();
},
/**
* Get week headers for calendar
* @param {Number} firstDayOfWeek

View file

@ -22,6 +22,8 @@ function DatePicker(context) {
* {Number} date [optional]
* {String} min
* {String} max
* {Number} step
* {Number} stepBase
* {Number} firstDayOfWeek
* {Array<Number>} weekends
* {Array<String>} monthStrings
@ -41,10 +43,10 @@ function DatePicker(context) {
* Set initial date picker states.
*/
_setDefaultState() {
const { year, month, day, min, max, firstDayOfWeek, weekends,
const { year, month, day, min, max, step, stepBase, firstDayOfWeek, weekends,
monthStrings, weekdayStrings, locale } = this.props;
const dateKeeper = new DateKeeper({
year, month, day, min, max, firstDayOfWeek, weekends,
year, month, day, min, max, step, stepBase, firstDayOfWeek, weekends,
calViewSize: CAL_VIEW_SIZE
});

View file

@ -169,6 +169,8 @@
locale,
min: detail.min,
max: detail.max,
step: detail.step,
stepBase: detail.stepBase,
}
});
break;

View file

@ -232,12 +232,14 @@ button.month-year.active::after {
color: var(--weekend-outside-font-color);
}
.days-view > .out-of-range {
.days-view > .out-of-range,
.days-view > .off-step {
color: var(--weekday-disabled-font-color);
background: var(--disabled-fill-color);
}
.days-view > .out-of-range.weekend {
.days-view > .out-of-range.weekend,
.days-view > .off-step.weekend {
color: var(--weekend-disabled-font-color);
}
@ -245,7 +247,8 @@ button.month-year.active::after {
font-weight: bold;
}
.days-view > .out-of-range::before {
.days-view > .out-of-range::before,
.days-view > .off-step::before {
display: none;
}
@ -341,7 +344,7 @@ button.month-year.active::after {
}
.spinner-container > .spinner:not(.scrolling) > div.selection,
.calendar-container .days-view > div.selection:not(.out-of-range) {
.calendar-container .days-view > div.selection {
color: var(--selected-font-color);
}