Skip to content

Commit

Permalink
#568 - fixed time change in same range dates, fixes #568
Browse files Browse the repository at this point in the history
  • Loading branch information
t1m0n committed Mar 5, 2024
1 parent 65aa163 commit 052d5c9
Show file tree
Hide file tree
Showing 8 changed files with 159 additions and 54 deletions.
2 changes: 1 addition & 1 deletion dist/air-datepicker.js

Large diffs are not rendered by default.

3 changes: 2 additions & 1 deletion dist/package.json
Expand Up @@ -32,7 +32,8 @@
"express": "^4.17.1",
"glob": "^7.1.7",
"html-webpack-plugin": "^5.3.1",
"jest": "^26.6.3",
"jest": "^29.7.0",
"jest-environment-jsdom": "^29.7.0",
"mini-css-extract-plugin": "^1.6.0",
"node-gzip": "^1.1.2",
"open-cli": "^6.0.1",
Expand Down
46 changes: 26 additions & 20 deletions index-dev.html
Expand Up @@ -6,52 +6,58 @@
<title>Air Datepicker - development</title>
<style type="text/css">

body {
/*width: 3000px;*/

}
.container {
max-width: 700px;
margin: 400px auto;
margin: 200px auto;
overflow: auto;
height: 500px;
position: relative;
display: flex;
flex-direction: column;
align-items: center;
}

input[type='text'] {
width: 300px;
height: 32px;
margin: 0 0 16px;
}

.input-wrap {
padding: 1px;
display: flex;
flex-direction: column;
justify-content: center;
align-items: center;
}

.air-datepicker.-anime- {
left: unset;
.actions {
margin: 16px 0;
display: flex;
grid-gap: 16px;
justify-content: center;
}

.air-datepicker.-disabled- {
--adp-cell-background-color-selected: rgba(0, 0, 0, 0.1);
--adp-cell-background-color-in-range: rgba(0, 0, 0, 0.05);
}

</style>
</head>
<body>
<div class="dp-custom"></div>
<div class="container">
<div class='input-wrap'>
<input type="text" readonly id="dp1" />
</div>

<!-- <div id='dp1' ></div>-->


<!-- <div id='dp2' />-->
<div class="container">
<div class='input-wrap'>
<input type="text" readonly id="dp1" />
</div>

<div class="actions">
<button id='update'>update</button>
<button id='destroy'>destory</button>
<button id='action'>action</button>
<input type='text' id='alt-field' placeholder='alt field'/>

<!-- <input type='text' id='dp2'/>-->
<!-- <input type='date'/>-->
</div>

</div>
</body>
</html>
1 change: 1 addition & 0 deletions jest.config.js
@@ -1,6 +1,7 @@
module.exports = {
clearMocks: true,
coverageDirectory: 'coverage',
testEnvironment: 'jsdom',
moduleDirectories: [
'src',
'node_modules'
Expand Down
3 changes: 2 additions & 1 deletion package.json
Expand Up @@ -33,7 +33,8 @@
"express": "^4.17.1",
"glob": "^7.1.7",
"html-webpack-plugin": "^5.3.1",
"jest": "^26.6.3",
"jest": "^29.7.0",
"jest-environment-jsdom": "^29.7.0",
"lodash": "^4.17.21",
"mini-css-extract-plugin": "^1.6.0",
"node-gzip": "^1.1.2",
Expand Down
43 changes: 18 additions & 25 deletions src/datepicker.js
Expand Up @@ -874,25 +874,35 @@ export default class Datepicker {
return alreadySelectedDate;
}

_handleAlreadySelectedDates(alreadySelectedDate, newSelectedDate) {
const {range, toggleSelected} = this.opts;
const isFunc = typeof toggleSelected === 'function';
let shouldToggle = isFunc ? toggleSelected({datepicker: this, date: newSelectedDate}) : toggleSelected;
_handleAlreadySelectedDates(alreadySelectedDate, cellDate) {
let {selectedDates, rangeDateFrom, rangeDateTo} = this;
let {range, toggleSelected} = this.opts;
let selectedDatesLen = selectedDates.length;
let isFunc = typeof toggleSelected === 'function';
let shouldToggle = isFunc ? toggleSelected({datepicker: this, date: cellDate}) : toggleSelected;
let datesAreSame = Boolean(range && selectedDatesLen === 1 && alreadySelectedDate);
// If range=true and user selects same date, then add new instance of same date to selectedDates
// to be able to change time independently on both dates
let cellDateCopy = datesAreSame ? copyDate(cellDate) : cellDate;

if (range) {
if (!shouldToggle) {
// Add possibility to select same date when range is true
if (this.selectedDates.length !== 2) {
this.selectDate(newSelectedDate);
if (selectedDatesLen !== 2) {
this.selectDate(cellDateCopy);
}
// Don't change lastSelectedDate if we have 2 same selected dates
if (selectedDatesLen === 2 && isSameDate(rangeDateFrom, rangeDateTo)) {
return;
}
}
}

if (shouldToggle) {
this.unselectDate(newSelectedDate);
this.unselectDate(cellDateCopy);
} else {
// Change last selected date to be able to change time when clicking on this cell
this._updateLastSelectedDate(alreadySelectedDate);
this._updateLastSelectedDate(datesAreSame ? cellDateCopy : alreadySelectedDate);
}
}

Expand All @@ -912,19 +922,6 @@ export default class Datepicker {
this.setCurrentView(this.viewIndexes[nextView]);
}

_handleRangeOnFocus() {
if (this.selectedDates.length === 1) {
let selectedDate = this.selectedDates[0];
if (isDateBigger(selectedDate, this.focusDate)) {
this.rangeDateTo = this.selectedDates[0];
this.rangeDateFrom = this.focusDate;
} else {
this.rangeDateTo = this.focusDate;
this.rangeDateFrom = this.selectedDates[0];
}
}
}

_scheduleCallAfterTransition = (cb) => {
this._cancelScheduledCall();

Expand Down Expand Up @@ -982,10 +979,6 @@ export default class Datepicker {

this.focusDate = date;

if (this.opts.range && date) {
this._handleRangeOnFocus();
}

this.trigger(consts.eventChangeFocusDate, date, params);
}

Expand Down
22 changes: 18 additions & 4 deletions src/datepickerCell.js
Expand Up @@ -187,11 +187,25 @@ export default class DatepickerCell {
}

_handleRangeStatus() {
let {rangeDateFrom, rangeDateTo} = this.dp;
const {selectedDates, focusDate, rangeDateTo, rangeDateFrom} = this.dp;
const selectedDatesLen = selectedDates.length;

if (!selectedDatesLen) return;

let from = rangeDateFrom;
let to = rangeDateTo;

if (selectedDatesLen === 1 && focusDate) {
const focusDateIsLargerThenSelected = isDateBigger(focusDate, selectedDates[0]);

from = focusDateIsLargerThenSelected ? selectedDates[0] : focusDate;
to = focusDateIsLargerThenSelected ? focusDate : selectedDates[0];
}

let classes = classNames({
'-in-range-': rangeDateFrom && rangeDateTo && isDateBetween(this.date, rangeDateFrom, rangeDateTo),
'-range-from-': rangeDateFrom && isSameDate(this.date, rangeDateFrom, this.type),
'-range-to-': rangeDateTo && isSameDate(this.date, rangeDateTo, this.type)
'-in-range-': from && to && isDateBetween(this.date, from, to),
'-range-from-': from && isSameDate(this.date, from, this.type),
'-range-to-': to && isSameDate(this.date, to, this.type)
});

this.$cell.classList.remove('-range-from-', '-range-to-', '-in-range-');
Expand Down
93 changes: 91 additions & 2 deletions tests/options.test.js
Expand Up @@ -7,6 +7,8 @@ import consts from 'consts';
import {DAY} from './helpers';

let $input, $altInput, dp, $datepicker;
const timeFormat = new Intl.DateTimeFormat('ru', {hour: 'numeric', minute: 'numeric'});


beforeAll(() => {
$input = document.createElement('input');
Expand Down Expand Up @@ -600,7 +602,7 @@ describe('OPTIONS TESTS', () => {
});

describe('selectedDates', () => {
it('should select dates on init', async (done) => {
it('should select dates on init', async () => {
const date = new Date('2022-12-08');
init({
visible: false,
Expand All @@ -613,7 +615,6 @@ describe('OPTIONS TESTS', () => {

expect(dp.$el).toHaveValue('08.12.2022');
expect(dp.selectedDates).toHaveLength(1);
done();
});

it('should select dates with time on init with correct day period', async () => {
Expand Down Expand Up @@ -727,4 +728,92 @@ describe('OPTIONS TESTS', () => {
expect($dayCells).toHaveLength(28);
});
});

describe('range', () => {
it('should enable range mode', () => {
init({
range: true
});

dp.selectDate(['2023-10-10', '2023-10-22']);

expect(Boolean(dp.rangeDateFrom && dp.rangeDateTo)).toBeTruthy();
});

it('should select dates in proper', () => {
init({
range: true
});

// Select larger date first
dp.selectDate(['2023-10-22', '2023-10-10']);

expect(dp.rangeDateFrom.toLocaleDateString('ru')).toEqual('10.10.2023');
});

it('should change lastSelectedDate if toggleSelected=false', () => {
init({
range: true,
toggleSelected: false,
});
const from = '2023-10-10';
const to = '2023-10-22';

dp.selectDate([from, to]);
dp.getCell(from).click();

expect(dp.lastSelectedDate.toLocaleDateString('ru')).toEqual('10.10.2023');
});

it('should be able to change time by clicking on selected range dates', () => {
init({
range: true,
toggleSelected: false,
timepicker: true
});
const from = '2023-10-10';
const to = '2023-10-22';

dp.selectDate([from, to]);
// Change time in `to` date
dp.trigger(consts.eventChangeTime, {
hours: 20,
minutes: 20,
});

// Update lastSelectedDate and update time in `from` date
dp.getCell(from).click();
dp.trigger(consts.eventChangeTime, {
hours: 10,
minutes: 10,
});

expect(timeFormat.format(dp.selectedDates[0])).toEqual('10:10');
expect(timeFormat.format(dp.selectedDates[1])).toEqual('20:20');
});

it('should handle time correctly when range dates are the same', () => {
init({
range: true,
toggleSelected: false,
timepicker: true
});
const date = '2023-10-10';

dp.getCell(date).click();
dp.trigger(consts.eventChangeTime, {
hours: 10,
minutes: 10,
});

dp.getCell(date).click();
dp.trigger(consts.eventChangeTime, {
hours: 20,
minutes: 20,
});

expect(timeFormat.format(dp.selectedDates[0])).toEqual('10:10');
expect(timeFormat.format(dp.selectedDates[1])).toEqual('20:20');
});
});
});

0 comments on commit 052d5c9

Please sign in to comment.