Bug 1363672 - Add step support to date picker. r=mconley

MozReview-Commit-ID: 62IfiKArN34

--HG--
extra : rebase_source : 79f38ecd1617d4eb2ea6a9d4e612d172b832c427
This commit is contained in:
Scott Wu 2017-05-11 12:16:18 +08:00
Родитель 1ad55fc00a
Коммит 4a3697d589
5 изменённых файлов: 64 добавлений и 18 удалений

Просмотреть файл

@ -1768,9 +1768,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;

Просмотреть файл

@ -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

Просмотреть файл

@ -26,6 +26,8 @@ function DatePicker(context) {
* {Number} date [optional]
* {String} min
* {String} max
* {Number} step
* {Number} stepBase
* {Number} firstDayOfWeek
* {Array<Number>} weekends
* {Array<String>} monthStrings
@ -44,10 +46,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, dir } = 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
});

Просмотреть файл

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

Просмотреть файл

@ -250,16 +250,19 @@ 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);
}
.days-view > .out-of-range::before {
.days-view > .out-of-range::before,
.days-view > .off-step::before {
display: none;
}
@ -351,7 +354,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);
}