From 6f1fcab2d81caedd96d9404386bc92f9884c30ce Mon Sep 17 00:00:00 2001 From: janekptacijarabaci Date: Fri, 30 Mar 2018 20:56:33 +0200 Subject: Bug 1363672 - Add step support to date picker --- toolkit/content/browser-content.js | 3 +- toolkit/content/widgets/datekeeper.js | 60 +++++++++++++++++++++----- toolkit/content/widgets/datepicker.js | 6 ++- toolkit/content/widgets/datetimepopup.xml | 2 + toolkit/themes/shared/datetimeinputpickers.css | 11 +++-- 5 files changed, 64 insertions(+), 18 deletions(-) diff --git a/toolkit/content/browser-content.js b/toolkit/content/browser-content.js index 731b55185..b955bd29d 100644 --- a/toolkit/content/browser-content.js +++ b/toolkit/content/browser-content.js @@ -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; diff --git a/toolkit/content/widgets/datekeeper.js b/toolkit/content/widgets/datekeeper.js index 9777ee647..9517e2154 100644 --- a/toolkit/content/widgets/datekeeper.js +++ b/toolkit/content/widgets/datekeeper.js @@ -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} 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 diff --git a/toolkit/content/widgets/datepicker.js b/toolkit/content/widgets/datepicker.js index 317f0ae94..25b15dae6 100644 --- a/toolkit/content/widgets/datepicker.js +++ b/toolkit/content/widgets/datepicker.js @@ -22,6 +22,8 @@ function DatePicker(context) { * {Number} date [optional] * {String} min * {String} max + * {Number} step + * {Number} stepBase * {Number} firstDayOfWeek * {Array} weekends * {Array} 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 }); diff --git a/toolkit/content/widgets/datetimepopup.xml b/toolkit/content/widgets/datetimepopup.xml index 52df7de75..1cb9617ea 100644 --- a/toolkit/content/widgets/datetimepopup.xml +++ b/toolkit/content/widgets/datetimepopup.xml @@ -169,6 +169,8 @@ locale, min: detail.min, max: detail.max, + step: detail.step, + stepBase: detail.stepBase, } }); break; diff --git a/toolkit/themes/shared/datetimeinputpickers.css b/toolkit/themes/shared/datetimeinputpickers.css index a0c046f6f..42f2bc517 100644 --- a/toolkit/themes/shared/datetimeinputpickers.css +++ b/toolkit/themes/shared/datetimeinputpickers.css @@ -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); } -- cgit v1.2.3