Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Calendar get prev get next focus on same day instead of first #3355

Merged
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Jump to
Jump to file
Failed to load files.
Diff view
Diff view
16 changes: 8 additions & 8 deletions e2e-app/src/app/datepicker/focus/datepicker-focus.e2e-spec.ts
Expand Up @@ -270,36 +270,36 @@ describe('Datepicker', () => {
await expectFocused(page.getDayElement(new Date(2018, 7, 31)), `Last day of month should be focused`);
});

it(`should focus first day of previous month with 'PageUp'`, async() => {
it(`should focus same day of previous month with 'PageUp'`, async() => {
await page.preSelectDate(); // 10 AUG 2018
await page.openDatepicker();

await sendKey(Key.PAGE_UP);
await expectFocused(page.getDayElement(new Date(2018, 6, 1)), `First day of previous month should be focused`);
await expectFocused(page.getDayElement(new Date(2018, 6, 10)), `Same day of previous month should be focused`);
});

it(`should focus first day of next month with 'PageDown'`, async() => {
it(`should focus same day of next month with 'PageDown'`, async() => {
await page.preSelectDate(); // 10 AUG 2018
await page.openDatepicker();

await sendKey(Key.PAGE_DOWN);
await expectFocused(page.getDayElement(new Date(2018, 8, 1)), `First day of next month should be focused`);
await expectFocused(page.getDayElement(new Date(2018, 8, 10)), `Same day of next month should be focused`);
});

it(`should focus first day of previous year with 'Shift+PageUp'`, async() => {
it(`should focus same day of previous year with 'Shift+PageUp'`, async() => {
await page.preSelectDate(); // 10 AUG 2018
await page.openDatepicker();

await sendKey(Key.SHIFT, Key.PAGE_UP);
await expectFocused(page.getDayElement(new Date(2017, 0, 1)), `First day of previous year should be focused`);
await expectFocused(page.getDayElement(new Date(2017, 7, 10)), `Same day of previous year should be focused`);
});

it(`should focus first day of next year with 'Shift+PageDown'`, async() => {
it(`should focus same day of next year with 'Shift+PageDown'`, async() => {
await page.preSelectDate(); // 10 AUG 2018
await page.openDatepicker();

await sendKey(Key.SHIFT, Key.PAGE_DOWN);
await expectFocused(page.getDayElement(new Date(2019, 0, 1)), `First day of next year should be focused`);
await expectFocused(page.getDayElement(new Date(2019, 7, 10)), `Same day of next year should be focused`);
});

it(`should focus min available day with 'Shift+Home'`, async() => {
Expand Down
8 changes: 4 additions & 4 deletions src/datepicker/datepicker-service.spec.ts
Expand Up @@ -1022,20 +1022,20 @@ describe('ngb-datepicker-service', () => {
// months
service.focus(date);
service.focusMove('m', 1);
expect(model.focusDate).toEqual(new NgbDate(2017, 6, 1));
expect(model.focusDate).toEqual(new NgbDate(2017, 6, 5));

service.focus(date);
service.focusMove('m', -1);
expect(model.focusDate).toEqual(new NgbDate(2017, 4, 1));
expect(model.focusDate).toEqual(new NgbDate(2017, 4, 5));

// years
service.focus(date);
service.focusMove('y', 1);
expect(model.focusDate).toEqual(new NgbDate(2018, 1, 1));
expect(model.focusDate).toEqual(new NgbDate(2018, 5, 5));

service.focus(date);
service.focusMove('y', -1);
expect(model.focusDate).toEqual(new NgbDate(2016, 1, 1));
expect(model.focusDate).toEqual(new NgbDate(2016, 5, 5));
});

it(`should move focus when 'minDate' changes`, () => {
Expand Down
7 changes: 4 additions & 3 deletions src/datepicker/datepicker-tools.ts
Expand Up @@ -78,11 +78,12 @@ export function generateSelectBoxYears(date: NgbDate, minDate: NgbDate, maxDate:
}

export function nextMonthDisabled(calendar: NgbCalendar, date: NgbDate, maxDate: NgbDate) {
return maxDate && calendar.getNext(date, 'm').after(maxDate);
const nextDate = Object.assign(calendar.getNext(date, 'm'), {day: 1});
return maxDate && nextDate.after(maxDate);
}

export function prevMonthDisabled(calendar: NgbCalendar, date: NgbDate, minDate: NgbDate) {
const prevDate = calendar.getPrev(date, 'm');
const prevDate = Object.assign(calendar.getPrev(date, 'm'), {day: 1});
return minDate && (prevDate.year === minDate.year && prevDate.month < minDate.month ||
prevDate.year < minDate.year && minDate.month === 1);
}
Expand All @@ -96,7 +97,7 @@ export function buildMonths(

// generate new first dates, nullify or reuse months
const firstDates = Array.from({length: displayMonths}, (_, i) => {
const firstDate = calendar.getNext(date, 'm', i);
const firstDate = Object.assign(calendar.getNext(date, 'm', i), {day: 1});
months[i] = null;

if (!force) {
Expand Down
12 changes: 6 additions & 6 deletions src/datepicker/datepicker.spec.ts
Expand Up @@ -980,24 +980,24 @@ describe('ngb-datepicker', () => {

triggerKeyDown(getMonthContainer(datepicker), 33 /* page up */);
fixture.detectChanges();
expectFocusedDate(datepicker, new NgbDate(2016, 7, 1));
expectFocusedDate(datepicker, new NgbDate(2016, 7, 2));
expectSelectedDate(datepicker, null);

triggerKeyDown(getMonthContainer(datepicker), 34 /* page down */);
fixture.detectChanges();
expectFocusedDate(datepicker, new NgbDate(2016, 8, 1));
expectFocusedDate(datepicker, new NgbDate(2016, 8, 2));
expectSelectedDate(datepicker, null);

triggerKeyDown(getMonthContainer(datepicker), 34 /* page down */);
fixture.detectChanges();

expectFocusedDate(datepicker, new NgbDate(2016, 9, 1));
expectFocusedDate(datepicker, new NgbDate(2016, 9, 2));
expectSelectedDate(datepicker, null);

triggerKeyDown(getMonthContainer(datepicker), 34 /* page down */);
fixture.detectChanges();
datepicker = fixture.debugElement.query(By.directive(NgbDatepicker));
expectFocusedDate(datepicker, new NgbDate(2016, 10, 1));
expectFocusedDate(datepicker, new NgbDate(2016, 10, 2));
expectSelectedDate(datepicker, null);
});

Expand All @@ -1016,13 +1016,13 @@ describe('ngb-datepicker', () => {
triggerKeyDown(getMonthContainer(datepicker), 33 /* page up */, true /* shift */);
fixture.detectChanges();

expectFocusedDate(datepicker, new NgbDate(2015, 1, 1), true);
expectFocusedDate(datepicker, new NgbDate(2015, 8, 1), true);
expectSelectedDate(datepicker, null);

triggerKeyDown(getMonthContainer(datepicker), 34 /* page down */, true /* shift */);
fixture.detectChanges();

expectFocusedDate(datepicker, new NgbDate(2016, 1, 1));
expectFocusedDate(datepicker, new NgbDate(2016, 8, 1));
expectSelectedDate(datepicker, null);
});

Expand Down
32 changes: 24 additions & 8 deletions src/datepicker/ngb-calendar.spec.ts
Expand Up @@ -43,25 +43,41 @@ describe('ngb-calendar-gregorian', () => {
});

it('should add months to date', () => {
expect(calendar.getNext(new NgbDate(2016, 7, 22), 'm')).toEqual(new NgbDate(2016, 8, 1));
expect(calendar.getNext(new NgbDate(2016, 7, 22), 'm')).toEqual(new NgbDate(2016, 8, 22));
expect(calendar.getNext(new NgbDate(2016, 7, 1), 'm')).toEqual(new NgbDate(2016, 8, 1));
expect(calendar.getNext(new NgbDate(2016, 12, 22), 'm')).toEqual(new NgbDate(2017, 1, 1));
expect(calendar.getNext(new NgbDate(2016, 12, 22), 'm')).toEqual(new NgbDate(2017, 1, 22));
expect(calendar.getNext(new NgbDate(2016, 1, 29), 'm')).toEqual(new NgbDate(2016, 2, 29));
expect(calendar.getNext(new NgbDate(2016, 1, 30), 'm')).toEqual(new NgbDate(2016, 2, 29));
expect(calendar.getNext(new NgbDate(2016, 10, 30), 'm', 6)).toEqual(new NgbDate(2017, 4, 30));
expect(calendar.getNext(new NgbDate(2016, 10, 31), 'm', 6)).toEqual(new NgbDate(2017, 4, 30));
});

it('should subtract months from date', () => {
expect(calendar.getPrev(new NgbDate(2016, 7, 22), 'm')).toEqual(new NgbDate(2016, 6, 1));
expect(calendar.getPrev(new NgbDate(2016, 7, 22), 'm')).toEqual(new NgbDate(2016, 6, 22));
expect(calendar.getPrev(new NgbDate(2016, 8, 1), 'm')).toEqual(new NgbDate(2016, 7, 1));
expect(calendar.getPrev(new NgbDate(2017, 1, 22), 'm')).toEqual(new NgbDate(2016, 12, 1));
expect(calendar.getPrev(new NgbDate(2017, 1, 22), 'm')).toEqual(new NgbDate(2016, 12, 22));
expect(calendar.getPrev(new NgbDate(2016, 3, 29), 'm')).toEqual(new NgbDate(2016, 2, 29));
expect(calendar.getPrev(new NgbDate(2016, 3, 30), 'm')).toEqual(new NgbDate(2016, 2, 29));
expect(calendar.getPrev(new NgbDate(2016, 10, 30), 'm', 4)).toEqual(new NgbDate(2016, 6, 30));
expect(calendar.getPrev(new NgbDate(2016, 10, 31), 'm', 4)).toEqual(new NgbDate(2016, 6, 30));
});

it('should add years to date', () => {
expect(calendar.getNext(new NgbDate(2016, 1, 22), 'y')).toEqual(new NgbDate(2017, 1, 1));
expect(calendar.getNext(new NgbDate(2017, 12, 22), 'y')).toEqual(new NgbDate(2018, 1, 1));
expect(calendar.getNext(new NgbDate(2016, 1, 22), 'y')).toEqual(new NgbDate(2017, 1, 22));
expect(calendar.getNext(new NgbDate(2017, 12, 22), 'y')).toEqual(new NgbDate(2018, 12, 22));
expect(calendar.getNext(new NgbDate(2016, 2, 29), 'y')).toEqual(new NgbDate(2017, 2, 28));
expect(calendar.getNext(new NgbDate(2016, 2, 28), 'y')).toEqual(new NgbDate(2017, 2, 28));
expect(calendar.getNext(new NgbDate(2016, 2, 29), 'y', 4)).toEqual(new NgbDate(2020, 2, 29));
expect(calendar.getNext(new NgbDate(2016, 2, 29), 'y', 3)).toEqual(new NgbDate(2019, 2, 28));
});

it('should subtract years from date', () => {
expect(calendar.getPrev(new NgbDate(2016, 12, 22), 'y')).toEqual(new NgbDate(2015, 1, 1));
expect(calendar.getPrev(new NgbDate(2017, 1, 22), 'y')).toEqual(new NgbDate(2016, 1, 1));
expect(calendar.getPrev(new NgbDate(2016, 12, 22), 'y')).toEqual(new NgbDate(2015, 12, 22));
expect(calendar.getPrev(new NgbDate(2017, 1, 22), 'y')).toEqual(new NgbDate(2016, 1, 22));
expect(calendar.getPrev(new NgbDate(2016, 2, 28), 'y')).toEqual(new NgbDate(2015, 2, 28));
expect(calendar.getPrev(new NgbDate(2016, 2, 29), 'y')).toEqual(new NgbDate(2015, 2, 28));
expect(calendar.getPrev(new NgbDate(2016, 2, 29), 'y', 4)).toEqual(new NgbDate(2012, 2, 29));
expect(calendar.getPrev(new NgbDate(2016, 2, 29), 'y', 3)).toEqual(new NgbDate(2013, 2, 28));
});

it('should properly recognize invalid javascript date', () => {
Expand Down
19 changes: 17 additions & 2 deletions src/datepicker/ngb-calendar.ts
Expand Up @@ -98,20 +98,35 @@ export class NgbCalendarGregorian extends NgbCalendar {

getNext(date: NgbDate, period: NgbPeriod = 'd', number = 1) {
let jsDate = toJSDate(date);
let checkMonth = true;
let expectedMonth = jsDate.getMonth();

switch (period) {
case 'y':
return new NgbDate(date.year + number, 1, 1);
jsDate.setFullYear(jsDate.getFullYear() + number);
break;
case 'm':
jsDate = new Date(date.year, date.month + number - 1, 1, 12);
expectedMonth += number;
jsDate.setMonth(expectedMonth);
expectedMonth = expectedMonth % 12;
if (expectedMonth < 0) {
expectedMonth = expectedMonth + 12;
}
break;
case 'd':
jsDate.setDate(jsDate.getDate() + number);
checkMonth = false;
break;
default:
return date;
}

if (checkMonth && jsDate.getMonth() !== expectedMonth) {
// this means the destination month has less days than the initial month
// let's go back to the end of the previous month:
jsDate.setDate(0);
}

return fromJSDate(jsDate);
}

Expand Down