Skip to content

Commit

Permalink
refactor(date picker): Fix lint errors in datepicker and refactor set…
Browse files Browse the repository at this point in the history
…ExcludedDates 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.
  • Loading branch information
chrispymm authored Jan 24, 2025
1 parent 3400152 commit a5dc2d7
Showing 1 changed file with 49 additions and 45 deletions.
94 changes: 49 additions & 45 deletions src/moj/components/date-picker/date-picker.js
Original file line number Diff line number Diff line change
Expand Up @@ -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) {
Expand Down Expand Up @@ -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 `<div class="moj-datepicker__dialog-header">
Expand Down Expand Up @@ -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();
Expand Down Expand Up @@ -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());
}
Expand All @@ -410,7 +419,6 @@ Datepicker.prototype.setLeadingZeros = function () {
}
if (this.config.leadingZeros.toLowerCase() === "false") {
this.config.leadingZeros = false;
return;
}
}
};
Expand All @@ -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
Expand Down Expand Up @@ -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,
Expand Down Expand Up @@ -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()}`;
Expand Down Expand Up @@ -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
Expand All @@ -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
Expand Down Expand Up @@ -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];
}
Expand Down Expand Up @@ -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;
Expand All @@ -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");
}
Expand Down

0 comments on commit a5dc2d7

Please sign in to comment.