From a5dc2d7c0b77a1bd1058a56da64f66de63e7811b Mon Sep 17 00:00:00 2001 From: Chris Pymm Date: Fri, 24 Jan 2025 13:17:49 +0000 Subject: [PATCH] refactor(date picker): Fix lint errors in datepicker and refactor setExcludedDates method (#1113) * style(date picker): fix all linting errors that dont require a refactor * refactor(date picker): refactor setExcludedDates for readability and to appease eslint The large map function in the setExcldedDates method was hard to read, and eslint didn't like it didn't have an obvious return value. This commit refactors part of the map into a parseDateRangeString function making the code much more readable and control flow more obvious. --- src/moj/components/date-picker/date-picker.js | 94 ++++++++++--------- 1 file changed, 49 insertions(+), 45 deletions(-) diff --git a/src/moj/components/date-picker/date-picker.js b/src/moj/components/date-picker/date-picker.js index 5949c5fc..1711661c 100644 --- a/src/moj/components/date-picker/date-picker.js +++ b/src/moj/components/date-picker/date-picker.js @@ -2,18 +2,18 @@ * Datepicker config * * @typedef {object} DatepickerConfig - * @property {string} [excludedDates] - Dates that cannot be selected - * @property {string} [excludedDays] - Days that cannot be selected + * @property {string} [excludedDates] - Dates that cannot be selected + * @property {string} [excludedDays] - Days that cannot be selected * @property {boolean} [leadingZeroes] - Whether to add leading zeroes when populating the field - * @property {string} [minDate] - The earliest available date - * @property {string} [maxDate] - The latest available date - * @property {string} [weekStartDay] - First day of the week in calendar view + * @property {string} [minDate] - The earliest available date + * @property {string} [maxDate] - The latest available date + * @property {string} [weekStartDay] - First day of the week in calendar view */ /** * @param {HTMLElement} $module - HTML element * @param {DatepickerConfig} config - config object - * @constructor + * @class */ function Datepicker($module, config = {}) { if (!$module) { @@ -251,7 +251,7 @@ Datepicker.prototype.toggleTemplate = function () { * HTML template for calendar dialog * * @param {string} [titleId] - Id attribute for dialog title - * @return {string} + * @returns {string} */ Datepicker.prototype.dialogTemplate = function (titleId) { return `
@@ -319,7 +319,7 @@ Datepicker.prototype.createCalendarHeaders = function () { * * @param {number} value - The value to be padded * @param {number} length - The length in characters of the output - * @return {string} + * @returns {string} */ Datepicker.prototype.leadingZeros = function (value, length = 2) { let ret = value.toString(); @@ -361,34 +361,43 @@ Datepicker.prototype.setExcludedDates = function () { .replace(/\s+/, " ") .split(" ") .map((item) => { - if (item.includes("-")) { - // parse the date range from the format "dd/mm/yyyy-dd/mm/yyyy" - const [startDate, endDate] = item - .split("-") - .map((d) => this.formattedDateFromString(d, null)); - if (startDate && endDate) { - const date = new Date(startDate.getTime()); - const dates = []; - while (date <= endDate) { - dates.push(new Date(date)); - date.setDate(date.getDate() + 1); - } - return dates; - } - } else { - return this.formattedDateFromString(item, null); - } + return item.includes("-") + ? this.parseDateRangeString(item) + : this.formattedDateFromString(item); }) .flat() .filter((item) => item); } }; +/* + * Parses a daterange string into an array of dates + * @param {String} datestring - A daterange string in the format "dd/mm/yyyy-dd/mm/yyyy" + * @returns {Date[]} + */ +Datepicker.prototype.parseDateRangeString = function (datestring) { + const dates = []; + const [startDate, endDate] = datestring + .split("-") + .map((d) => this.formattedDateFromString(d, null)); + + if (startDate && endDate) { + const date = new Date(startDate.getTime()); + /* eslint-disable no-unmodified-loop-condition */ + while (date <= endDate) { + dates.push(new Date(date)); + date.setDate(date.getDate() + 1); + } + /* eslint-enable no-unmodified-loop-condition */ + } + return dates; +}; + Datepicker.prototype.setExcludedDays = function () { if (this.config.excludedDays) { // lowercase and arrange dayLabels to put indexOf sunday == 0 for comparison // with getDay() function - let weekDays = this.dayLabels.map((item) => item.toLowerCase()); + const weekDays = this.dayLabels.map((item) => item.toLowerCase()); if (this.config.weekStartDay === "monday") { weekDays.unshift(weekDays.pop()); } @@ -410,7 +419,6 @@ Datepicker.prototype.setLeadingZeros = function () { } if (this.config.leadingZeros.toLowerCase() === "false") { this.config.leadingZeros = false; - return; } } }; @@ -430,8 +438,7 @@ Datepicker.prototype.setWeekStartDay = function () { * Determine if a date is selecteable * * @param {Date} date - the date to check - * @return {boolean} - * + * @returns {boolean} */ Datepicker.prototype.isExcludedDate = function (date) { // This comparison does not work correctly - it will exclude the mindate itself @@ -463,7 +470,7 @@ Datepicker.prototype.isExcludedDate = function (date) { * * @param {string} dateString - string in the format d/m/yyyy dd/mm/yyyy * @param {Date} fallback - date object to return if formatting fails - * @return {Date} + * @returns {Date} */ Datepicker.prototype.formattedDateFromString = function ( dateString, @@ -491,21 +498,21 @@ Datepicker.prototype.formattedDateFromString = function ( * Get a formatted date string from a Date object * * @param {Date} date - date to format to a string - * @return {string} + * @returns {string} */ Datepicker.prototype.formattedDateFromDate = function (date) { if (this.config.leadingZeros) { return `${this.leadingZeros(date.getDate())}/${this.leadingZeros(date.getMonth() + 1)}/${date.getFullYear()}`; - } else { - return `${date.getDate()}/${date.getMonth() + 1}/${date.getFullYear()}`; } + + return `${date.getDate()}/${date.getMonth() + 1}/${date.getFullYear()}`; }; /** * Get a human readable date in the format Monday 2 March 2024 * - * @param {Date} - date to format - * @return {string} + * @param {Date} date - date to format + * @returns {string} */ Datepicker.prototype.formattedDateHuman = function (date) { return `${this.dayLabels[(date.getDay() + 6) % 7]} ${date.getDate()} ${this.monthLabels[date.getMonth()]} ${date.getFullYear()}`; @@ -722,7 +729,7 @@ Datepicker.prototype.focusPreviousWeek = function () { Datepicker.prototype.focusFirstDayOfWeek = function () { const date = new Date(this.currentDate); - const firstDayOfWeekIndex = this.config.weekStartDay == "sunday" ? 0 : 1; + const firstDayOfWeekIndex = this.config.weekStartDay === "sunday" ? 0 : 1; const dayOfWeek = date.getDay(); const diff = dayOfWeek >= firstDayOfWeekIndex @@ -737,7 +744,7 @@ Datepicker.prototype.focusFirstDayOfWeek = function () { Datepicker.prototype.focusLastDayOfWeek = function () { const date = new Date(this.currentDate); - const lastDayOfWeekIndex = this.config.weekStartDay == "sunday" ? 6 : 0; + const lastDayOfWeekIndex = this.config.weekStartDay === "sunday" ? 6 : 0; const dayOfWeek = date.getDay(); const diff = dayOfWeek <= lastDayOfWeekIndex @@ -783,17 +790,14 @@ Datepicker.prototype.focusPreviousYear = function (event, focus = true) { /** * Parse dataset * - * Loop over an object and normalise each value using {@link normaliseString}, - * optionally expanding nested `i18n.field` - * - * @param {{ schema: Schema }} Component - Component class + * @param {Schema} schema - Component class * @param {DOMStringMap} dataset - HTML element dataset * @returns {Object} Normalised dataset */ Datepicker.prototype.parseDataset = function (schema, dataset) { const parsed = {}; - for (const [field, attributes] of Object.entries(schema.properties)) { + for (const [field, ,] of Object.entries(schema.properties)) { if (field in dataset) { parsed[field] = dataset[field]; } @@ -842,7 +846,7 @@ Datepicker.prototype.mergeConfigs = function (...configObjects) { * @param {number} row * @param {number} column * @param {Datepicker} picker - * @constructor + * @class */ function DSCalendarDay(button, index, row, column, picker) { this.index = index; @@ -865,12 +869,12 @@ DSCalendarDay.prototype.init = function () { * @param {boolean} disabled - is the day selectable or excluded */ DSCalendarDay.prototype.update = function (day, hidden, disabled) { - let label = day.getDate(); + const label = day.getDate(); let accessibleLabel = this.picker.formattedDateHuman(day); if (disabled) { this.button.setAttribute("aria-disabled", true); - accessibleLabel = "Excluded date, " + accessibleLabel; + accessibleLabel = `Excluded date, ${accessibleLabel}`; } else { this.button.removeAttribute("aria-disabled"); }