Instructions#
Expectation: Click on a specific day to automatically select the start and end dates of the week that day belongs to.
Current situation: This is a requirement for selecting a date range. The Date Range Picker does not have a built-in feature for week selection. For a date range, you need to click once for the start and once for the end.
Therefore, it needs to be implemented manually, with the following steps.
Include week-picker.css
#
.daterangepicker .calendar-table th,
.daterangepicker .calendar-table td { /* tighter */
min-width: 20px !important;
}
.daterangepicker tr td.week { /* wider */
width: 44px;
color: #1a6cb3;
}
.daterangepicker tbody tr:hover {
background-color: #f2f2f2;
}
.daterangepicker td.off {
background-color: transparent !important;
}
.daterangepicker td.off.in-range {
/*background-color: #ebf4f8 !important;*/
background-color: #e4eaec !important;
}
.daterangepicker td.off.start-date,
.daterangepicker td.off.end-date {
background-color: #5188b7 !important;
}
.daterangepicker tbody tr.active td.week {
color: #357ebd !important;
background-color: #f2f2f2 !important;
font-weight: bold;
}
.daterangepicker td.today,
.daterangepicker td.today.off {
background-color: #ecf6f9 !important;
}
Include week-picker.js
#
/*
Code source: https://jsfiddle.net/dj_floyd/f2hoygdw/
Usage:
1. Include week-picker.css
2. Include week-picker.js
3. Add an input element on the page, set id to week-dp
<input type="text" class="form-control datetimepicker-input" id="week-dp" data-toggle="datetimepicker" data-target="#week-dp">
4. In the page's js file, call the initWeekPicker function, passing '#week-dp' as a parameter
Get value: $('#week-dp').val()
*/
//moment.locale('ru') //depending on locale you can move start of week
/**
* Initialize week picker
*
* Because the displayed value is set asynchronously, the way to get the value becomes:
* $(domSelector).data('weekStart');
* $(domSelector).data('weekEnd');
* @param {any} domSelector '#week-dp'
* @param {any} format default 'YYYY-MM-DD'
*/
function initWeekPicker(domSelector, format) {
const set_picker_start_end = (picker, when) => {
//console.log('set_picker_start_end')
let m = (when == 'now') ? moment() : moment(when); //moment
let week_start = m.startOf('isoweek');
let week_end = m.clone().endOf('isoweek');
// Because setStartDate and setEndDate will format the selected date for display,
// but since we set singleDatePicker to true, it won't include the end date when formatting
// Therefore, we set a delay here to set the value after setStartDate and setEndDate
// This will cause a flickering issue, but it's not a big deal, just consider it an animation effect
setTimeout(() => {
$(domSelector).val(week_start.format(format ?? 'YYYY-MM-DD') + ' ~ ' + week_end.format(format ??'YYYY-MM-DD'));
}, 0);
// Because the above is a delayed value setting, after the external initWeekPicker, getting $(domSelector).val() only has the value of week_start (because singleDatePicker is set to true, setEndDate no longer takes effect)
// So here we put the real values in data, displayed asynchronously on the page, and when getting values externally, take them from data, so there won't be a problem of not being able to get the week range value after calling initWeekPicker
$(domSelector).data({
weekStart: week_start.format(format ?? 'YYYY-MM-DD'),
weekEnd: week_end.format(format ?? 'YYYY-MM-DD'),
});
//console.log(week_start.format('YYYY-MM-DD'), week_end.format('YYYY-MM-DD'));
picker.setStartDate(week_start);
picker.setEndDate(week_end);
};
$(domSelector).daterangepicker({
"showDropdowns": true,
"showISOWeekNumbers": false,
"autoApply": true,
"showCustomRangeLabel": false,
//"startDate": '', //not work because of one calendar. will be set further
//"endDate": '', //not work because of one calendar. will be set further
"drops": "down",
// The daterangepicker component requires clicking start and end twice to select a date range. To achieve the effect of selecting a week with one click, set it to single selection
// But this causes a problem, that is /picker.setStartDate(week_start);picker.setEndDate(week_end); after, the format only has week_start
// Because we set singleDatePicker to true, it won't include the end date when formatting
"singleDatePicker": true, //to make one click and one calendar
"locale": {
"format": "YYYY-MM-DD",
//"weekLabel": "#",
},
});
set_picker_start_end($(domSelector).data('daterangepicker'), 'now') //set current week selected
$(domSelector).on('show.daterangepicker', function (ev, picker) {
//console.log('show.daterangepicker', ev, picker);
let active_cell = picker.container[0].querySelector('td.start-date');
active_cell.parentElement.classList.add('active'); //tr goes active
});
// fix: solve the problem that after the daterangepicker is displayed, if no date is clicked, clicking elsewhere will automatically close the picker due to autoApply: true, and then the date becomes only startDate
$(domSelector).on('hide.daterangepicker', function (ev, picker) {
//console.log('hide.daterangepicker', ev, picker);
set_picker_start_end(picker, picker.startDate);
});
$(domSelector).on('apply.daterangepicker', function (ev, picker) {
//console.log('apply.daterangepicker', ev, picker);
set_picker_start_end(picker, picker.startDate);
});
}
Usage#
html:
<input type="text" class="form-control datetimepicker-input" id="week-dp" data-toggle="datetimepicker" data-target="#week-dp">
js:
initWeekPicker('#week-dp');