Skip to content

Commit

Permalink
feat: add option to start on Monday (#18) (#70)
Browse files Browse the repository at this point in the history
* feat: add option to start on Monday (#18)

* feat: change startOnMonday option to weekStart option

* chore: apply code review

* chore: apply code review

* chore: apply code review
  • Loading branch information
lja1018 committed Mar 18, 2021
1 parent 4eb857f commit dddb9d2
Show file tree
Hide file tree
Showing 7 changed files with 108 additions and 19 deletions.
7 changes: 4 additions & 3 deletions src/js/calendar/body.js
Original file line number Diff line number Diff line change
Expand Up @@ -23,8 +23,9 @@ var TYPE_YEAR = constants.TYPE_YEAR;
*/
var Body = defineClass(
/** @lends Body.prototype */ {
init: function(bodyContainer, option) {
var language = option.language;
init: function(bodyContainer, options) {
var language = options.language;
var weekStartDay = options.weekStartDay;

/**
* Body container element
Expand All @@ -38,7 +39,7 @@ var Body = defineClass(
* @type {DateLayer}
* @private
*/
this._dateLayer = new DateLayer(language);
this._dateLayer = new DateLayer(language, weekStartDay);

/**
* MonthLayer
Expand Down
8 changes: 6 additions & 2 deletions src/js/calendar/index.js
Original file line number Diff line number Diff line change
Expand Up @@ -20,6 +20,7 @@ var constants = require('../constants');
var dateUtil = require('../dateUtil');
var util = require('../util');

var DEFAULT_WEEK_START_DAY = constants.DEFAULT_WEEK_START_DAY;
var DEFAULT_LANGUAGE_TYPE = constants.DEFAULT_LANGUAGE_TYPE;

var TYPE_DATE = constants.TYPE_DATE;
Expand Down Expand Up @@ -51,6 +52,7 @@ var BODY_SELECTOR = '.tui-calendar-body';
* @param {boolean} [options.showToday = true] - Show today.
* @param {boolean} [options.showJumpButtons = false] - Show the yearly jump buttons (move to the previous and next year in 'date' Calendar)
* @param {boolean} [options.usageStatistics = true] - Send a hostname to Google Analytics (default: true)
* @param {string} [options.weekStartDay = 'Sun'] - Start of the week. 'Sun', 'Mon', ..., 'Sat'(default: 'Sun'(start on Sunday))
* @example
* import DatePicker from 'tui-date-picker' // ES6
* // const DatePicker = require('tui-date-picker'); // CommonJS
Expand All @@ -61,7 +63,8 @@ var BODY_SELECTOR = '.tui-calendar-body';
* showToday: true,
* showJumpButtons: false,
* date: new Date(),
* type: 'date'
* type: 'date',
* weekStartDay: 'Mon',
* });
*
* calendar.on('draw', function(event) {
Expand All @@ -87,7 +90,8 @@ var Calendar = defineClass(
showJumpButtons: false,
date: new Date(),
type: TYPE_DATE,
usageStatistics: true
usageStatistics: true,
weekStartDay: DEFAULT_WEEK_START_DAY
},
options
);
Expand Down
49 changes: 43 additions & 6 deletions src/js/calendar/layerBody/date.js
Original file line number Diff line number Diff line change
Expand Up @@ -11,8 +11,10 @@ var dateUtil = require('../../dateUtil');
var bodyTmpl = require('./../../../template/calendar/dateLayer');
var LayerBase = require('./base');
var TYPE_DATE = require('../../constants').TYPE_DATE;
var WEEK_START_DAY_MAP = require('../../constants').WEEK_START_DAY_MAP;

var DATE_SELECTOR = '.tui-calendar-date';
var DAYS_OF_WEEK = 7;

/**
* @ignore
Expand All @@ -23,8 +25,10 @@ var DATE_SELECTOR = '.tui-calendar-date';
var DateLayer = defineClass(
LayerBase,
/** @lends DateLayer.prototype */ {
init: function(language) {
init: function(language, weekStartDay) {
LayerBase.call(this, language);

this.weekStartDay = WEEK_START_DAY_MAP[String(weekStartDay).toLowerCase()] || 0;
},

/**
Expand All @@ -41,12 +45,20 @@ var DateLayer = defineClass(
*/
_makeContext: function(date) {
var daysShort = this._localeText.titles.D;
var year, month;
var year, month, days, i;

date = date || new Date();
year = date.getFullYear();
month = date.getMonth() + 1;

if (this.weekStartDay) {
days = daysShort.slice();
for (i = 0; i < this.weekStartDay; i += 1) {
days.push(days.shift());
}
daysShort = days;
}

return {
Sun: daysShort[0],
Mon: daysShort[1],
Expand All @@ -72,14 +84,24 @@ var DateLayer = defineClass(
var weekNumber = 0;
var weeksCount = 6; // Fix for no changing height
var weeks = [];
var dates, i;
var week, dates, i;

for (; weekNumber < weeksCount; weekNumber += 1) {
while (weekNumber < weeksCount) {
dates = [];
for (i = 0; i < 7; i += 1) {

for (i = this.weekStartDay; i < DAYS_OF_WEEK + this.weekStartDay; i += 1) {
dates.push(dateUtil.getDateOfWeek(year, month, weekNumber, i));
}
weeks.push(this._getWeek(year, month, dates));

week = this._getWeek(year, month, dates);

if (this.weekStartDay && !_isFirstWeek(weekNumber, week[0].dayInMonth)) {
weeks.push(this._getFirstWeek(year, month));
weeksCount -= 1; // Fix for no changing height
}

weeks.push(week);
weekNumber += 1;
}

return weeks;
Expand Down Expand Up @@ -148,8 +170,23 @@ var DateLayer = defineClass(
*/
getDateElements: function() {
return this._element.querySelectorAll(DATE_SELECTOR);
},

_getFirstWeek: function(year, month) {
var firstWeekDates = [];
var i;

for (i = this.weekStartDay; i < DAYS_OF_WEEK + this.weekStartDay; i += 1) {
firstWeekDates.push(dateUtil.getDateOfWeek(year, month, -1, i));
}

return this._getWeek(year, month, firstWeekDates);
}
}
);

function _isFirstWeek(weekIndex, dayInMonth) {
return weekIndex || dayInMonth === 1 || dayInMonth > DAYS_OF_WEEK;
}

module.exports = DateLayer;
13 changes: 12 additions & 1 deletion src/js/constants.js
Original file line number Diff line number Diff line change
Expand Up @@ -22,5 +22,16 @@ module.exports = {
CLASS_NAME_PREV_MONTH_BTN: 'tui-calendar-btn-prev-month',
CLASS_NAME_PREV_YEAR_BTN: 'tui-calendar-btn-prev-year',
CLASS_NAME_NEXT_YEAR_BTN: 'tui-calendar-btn-next-year',
CLASS_NAME_NEXT_MONTH_BTN: 'tui-calendar-btn-next-month'
CLASS_NAME_NEXT_MONTH_BTN: 'tui-calendar-btn-next-month',

DEFAULT_WEEK_START_DAY: 'Sun',
WEEK_START_DAY_MAP: {
sun: 0,
mon: 1,
tue: 2,
wed: 3,
thu: 4,
fri: 5,
sat: 6
}
};
14 changes: 10 additions & 4 deletions src/js/dateRangePicker/index.js
Original file line number Diff line number Diff line change
Expand Up @@ -32,10 +32,12 @@ var CLASS_NAME_SELECTED_RANGE = 'tui-is-selected-range';
* @param {HTMLElement|string} options.startpicker.input - Startpicker input element or selector
* @param {HTMLElement|string} options.startpicker.container - Startpicker container element or selector
* @param {Date|number} [options.startpicker.date] - Initial date of the start picker. Set by a Date instance or a number(timestamp). (default: no initial date)
* @param {string} [options.startpicker.weekStartDay = 'Sun'] - Start of the week. 'Sun', 'Mon', ..., 'Sat'(default: 'Sun'(start on Sunday))
* @param {object} options.endpicker - Endpicker options
* @param {HTMLElement|string} options.endpicker.input - Endpicker input element or selector
* @param {HTMLElement|string} options.endpicker.container - Endpicker container element or selector
* @param {Date|number} [options.endpicker.date] - Initial date of the end picker. Set by a Date instance or a number(timestamp). (default: no initial date)
* @param {string} [options.endpicker.weekStartDay = 'Sun'] - Start of the week. 'Sun', 'Mon', ..., 'Sat'(default: 'Sun'(start on Sunday))
* @param {('date'|'month'|'year')} [options.type = 'date'] - DatePicker type. Determine whether to choose a date, month, or year.
* @param {string} [options.language='en'] - Language code. English('en') and Korean('ko') are provided as default. To use the other languages, use {@link DatePicker#localeTexts DatePicker.localeTexts}.
* @param {object|boolean} [options.timePicker] - [TimePicker](https://nhn.github.io/tui.time-picker/latest) options. Refer to the [TimePicker instance's options](https://nhn.github.io/tui.time-picker/latest/TimePicker). To create the TimePicker without customization, set to true.
Expand All @@ -54,11 +56,13 @@ var CLASS_NAME_SELECTED_RANGE = 'tui-is-selected-range';
* startpicker: {
* input: '#start-input',
* container: '#start-container'
* date: new Date(2019, 3, 1)
* date: new Date(2019, 3, 1),
* weekStartDay: 'Mon',
* },
* endpicker: {
* input: '#end-input',
* container: '#end-container'
* container: '#end-container',
* weekStartDay: 'Mon',
* },
* type: 'date',
* format: 'yyyy-MM-dd'
Expand Down Expand Up @@ -118,14 +122,16 @@ var DateRangePicker = defineClass(
element: startInput,
format: options.format
},
date: options.startpicker.date
date: options.startpicker.date,
weekStartDay: options.startpicker.weekStartDay
});
var endpickerOpt = extend({}, options, {
input: {
element: endInput,
format: options.format
},
date: options.endpicker.date
date: options.endpicker.date,
weekStartDay: options.endpicker.weekStartDay
});

this._startpicker = new DatePicker(startpickerContainer, startpickerOpt);
Expand Down
11 changes: 8 additions & 3 deletions src/js/datepicker/index.js
Original file line number Diff line number Diff line change
Expand Up @@ -33,6 +33,7 @@ var mouseTouchEvent = require('../mouseTouchEvent');
var tmpl = require('../../template/datepicker/index');
var DatePickerInput = require('./input');

var DEFAULT_WEEK_START_DAY = constants.DEFAULT_WEEK_START_DAY;
var DEFAULT_LANGUAGE_TYPE = constants.DEFAULT_LANGUAGE_TYPE;
var TYPE_DATE = constants.TYPE_DATE;
var TYPE_MONTH = constants.TYPE_MONTH;
Expand Down Expand Up @@ -78,7 +79,8 @@ var mergeDefaultOption = function(option) {
selectableRanges: null,
openers: [],
autoClose: true,
usageStatistics: true
usageStatistics: true,
weekStartDay: DEFAULT_WEEK_START_DAY
},
option
);
Expand Down Expand Up @@ -128,6 +130,7 @@ var mergeDefaultOption = function(option) {
* @param {boolean} [options.showAlways = false] - Show the DatePicker always
* @param {boolean} [options.autoClose = true] - Close the DatePicker after clicking the date
* @param {boolean} [options.usageStatistics = true] - Send a hostname to Google Analytics (default: true)
* @param {string} [options.weekStartDay = 'Sun'] - Start of the week. 'Sun', 'Mon', ..., 'Sat'(default: 'Sun'(start on Sunday))
* @example
* import DatePicker from 'tui-date-picker' // ES6
* // const DatePicker = require('tui-date-picker'); // CommonJS
Expand Down Expand Up @@ -162,7 +165,8 @@ var mergeDefaultOption = function(option) {
* type: 'date',
* date: new Date(2015, 0, 1)
* selectableRanges: [range1, range2],
* openers: ['#opener']
* openers: ['#opener'],
* weekStartDay: 'Mon',
* });
*/
var DatePicker = defineClass(
Expand Down Expand Up @@ -237,7 +241,8 @@ var DatePicker = defineClass(
this._calendar = new Calendar(
this._element.querySelector(SELECTOR_CALENDAR_CONTAINER),
extend(options.calendar, {
usageStatistics: options.usageStatistics
usageStatistics: options.usageStatistics,
weekStartDay: options.weekStartDay
})
);

Expand Down
25 changes: 25 additions & 0 deletions test/calendar/dateLayer.spec.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,25 @@
/**
* @fileoverview Calendar date layer spec
* @author NHN. FE Development Lab <dl_javascript@nhn.com>
*/
'use strict';

var DateLayer = require('../../src/js/calendar/layerBody/date');

describe('Calendar - date layer', function() {
var dateLayer;

it('should have a default value of 0', function() {
dateLayer = new DateLayer('en');

expect(dateLayer.weekStartDay).toBe(0);
});

it('should change start day of week', function() {
['Sun', 'Mon', 'Tue', 'Wed', 'Thu', 'Fri', 'Sat'].forEach(function(day, index) {
dateLayer = new DateLayer('en', day);

expect(dateLayer.weekStartDay).toBe(index);
});
});
});

0 comments on commit dddb9d2

Please sign in to comment.