From 22b4ca835e957c1013805a0f8128138523f68d92 Mon Sep 17 00:00:00 2001 From: Max Okorokov Date: Fri, 4 Oct 2019 16:18:51 +0200 Subject: [PATCH] fix(datepicker): performance issues when huge min/max dates (#3357) Fixes #3338 --- src/datepicker/datepicker-service.spec.ts | 10 ++++++---- src/datepicker/datepicker-tools.spec.ts | 6 +++--- src/datepicker/datepicker-tools.ts | 12 +++++++++--- 3 files changed, 18 insertions(+), 10 deletions(-) diff --git a/src/datepicker/datepicker-service.spec.ts b/src/datepicker/datepicker-service.spec.ts index 722e0d663f..1a21f310a4 100644 --- a/src/datepicker/datepicker-service.spec.ts +++ b/src/datepicker/datepicker-service.spec.ts @@ -552,7 +552,7 @@ describe('ngb-datepicker-service', () => { expect(model.selectBoxes.years).toEqual(range(2010, 2030)); }); - it(`should generate [min, +10] 'years' when max date is missing`, () => { + it(`should generate [min/-500, +10] 'years' when max date is missing`, () => { service.minDate = new NgbDate(2010, 1, 1); service.open(new NgbDate(2011, 1, 1)); expect(model.selectBoxes.years).toEqual(range(2010, 2021)); @@ -560,11 +560,12 @@ describe('ngb-datepicker-service', () => { service.minDate = new NgbDate(2015, 1, 1); expect(model.selectBoxes.years).toEqual(range(2015, 2025)); + // -500 service.minDate = new NgbDate(1000, 1, 1); - expect(model.selectBoxes.years).toEqual(range(1000, 2025)); + expect(model.selectBoxes.years).toEqual(range(1515, 2025)); }); - it(`should generate [min, +10] 'years' when min date is missing`, () => { + it(`should generate [-10, +500/max] 'years' when min date is missing`, () => { service.maxDate = new NgbDate(2010, 1, 1); service.open(new NgbDate(2009, 1, 1)); expect(model.selectBoxes.years).toEqual(range(1999, 2010)); @@ -572,8 +573,9 @@ describe('ngb-datepicker-service', () => { service.maxDate = new NgbDate(2005, 1, 1); expect(model.selectBoxes.years).toEqual(range(1995, 2005)); + // +500 service.maxDate = new NgbDate(3000, 1, 1); - expect(model.selectBoxes.years).toEqual(range(1995, 3000)); + expect(model.selectBoxes.years).toEqual(range(1995, 2505)); }); it(`should generate 'months' when min/max dates are missing`, () => { diff --git a/src/datepicker/datepicker-tools.spec.ts b/src/datepicker/datepicker-tools.spec.ts index 89916c51be..01d88a06e3 100644 --- a/src/datepicker/datepicker-tools.spec.ts +++ b/src/datepicker/datepicker-tools.spec.ts @@ -566,17 +566,17 @@ describe(`datepicker-tools`, () => { it(`should generate years correctly`, () => { // both 'min' and 'max' are set test(new NgbDate(2017, 1, 1), new NgbDate(2018, 1, 1), new NgbDate(2019, 1, 1), range(2017, 2019)); - test(new NgbDate(2000, 1, 1), new NgbDate(2018, 1, 1), new NgbDate(3000, 1, 1), range(2000, 3000)); + test(new NgbDate(1000, 1, 1), new NgbDate(2018, 1, 1), new NgbDate(3000, 1, 1), range(1518, 2518)); test(new NgbDate(2018, 1, 1), new NgbDate(2018, 1, 1), new NgbDate(2018, 1, 1), [2018]); // 'min' is not set test(null, new NgbDate(2018, 1, 1), new NgbDate(2019, 1, 1), range(2008, 2019)); - test(null, new NgbDate(2018, 1, 1), new NgbDate(3000, 1, 1), range(2008, 3000)); + test(null, new NgbDate(2018, 1, 1), new NgbDate(3000, 1, 1), range(2008, 2518)); test(null, new NgbDate(2018, 1, 1), new NgbDate(2018, 1, 1), range(2008, 2018)); // 'max' is not set test(new NgbDate(2017, 1, 1), new NgbDate(2018, 1, 1), null, range(2017, 2028)); - test(new NgbDate(2000, 1, 1), new NgbDate(2018, 1, 1), null, range(2000, 2028)); + test(new NgbDate(1000, 1, 1), new NgbDate(2018, 1, 1), null, range(1518, 2028)); test(new NgbDate(2018, 1, 1), new NgbDate(2018, 1, 1), null, range(2018, 2028)); // both are not set diff --git a/src/datepicker/datepicker-tools.ts b/src/datepicker/datepicker-tools.ts index 631211722f..74fe233a80 100644 --- a/src/datepicker/datepicker-tools.ts +++ b/src/datepicker/datepicker-tools.ts @@ -71,10 +71,16 @@ export function generateSelectBoxYears(date: NgbDate, minDate: NgbDate, maxDate: return []; } - const start = minDate && minDate.year || date.year - 10; - const end = maxDate && maxDate.year || date.year + 10; + const start = minDate ? Math.max(minDate.year, date.year - 500) : date.year - 10; + const end = maxDate ? Math.min(maxDate.year, date.year + 500) : date.year + 10; - return Array.from({length: end - start + 1}, (e, i) => start + i); + const length = end - start + 1; + const numbers = Array(length); + for (let i = 0; i < length; i++) { + numbers[i] = start + i; + } + + return numbers; } export function nextMonthDisabled(calendar: NgbCalendar, date: NgbDate, maxDate: NgbDate) {