Skip to content

Commit

Permalink
fix(ui5-datepicker): display extreme values correctly (#75)
Browse files Browse the repository at this point in the history
* fix(ui5-datepicker): display extreme values correctly

Fixes #26

* fix(ui5-datepicker): display extreme values correctly

* fix(ui5-datepicker): display extreme values correctly

* add tests

* some more constants and a method extract
  • Loading branch information
a-z-ivanov committed Feb 22, 2019
1 parent 9038494 commit d1c7259
Show file tree
Hide file tree
Showing 10 changed files with 359 additions and 49 deletions.
Original file line number Diff line number Diff line change
Expand Up @@ -139,6 +139,10 @@ class ItemNavigation extends EventProvider {
this.currentIndex -= this.rowSize;
}

if (this.currentIndex < 0) {
this.currentIndex = 0;
}

const currentItem = items[this.currentIndex];

if (currentItem instanceof WebComponent) {
Expand Down
60 changes: 50 additions & 10 deletions packages/main/src/Calendar.js
Original file line number Diff line number Diff line change
Expand Up @@ -303,6 +303,10 @@ class Calendar extends WebComponent {
nextMonth.setDate(1);
nextMonth.setMonth(nextMonth.getMonth() + 1);

if (nextMonth.getYear() > YearPicker._MAX_YEAR) {
return;
}

this._focusFirstDayOfMonth(nextMonth);
this.timestamp = nextMonth.valueOf() / 1000;
}
Expand Down Expand Up @@ -333,14 +337,16 @@ class Calendar extends WebComponent {

const weekDaysCount = 7;

// find the DOM for the last day index
const lastDay = dayPicker.shadowRoot.querySelector(".sapWCDayPickerItemsContainer").children[parseInt(lastDayOfMonthIndex / weekDaysCount)].children[(lastDayOfMonthIndex % weekDaysCount)];
if (lastDayOfMonthIndex !== -1) {
// find the DOM for the last day index
const lastDay = dayPicker.shadowRoot.querySelector(".sapWCDayPickerItemsContainer").children[parseInt(lastDayOfMonthIndex / weekDaysCount)].children[(lastDayOfMonthIndex % weekDaysCount)];

// update current item in ItemNavigation
dayPicker._itemNav.current = lastDayOfMonthIndex;
// update current item in ItemNavigation
dayPicker._itemNav.current = lastDayOfMonthIndex;

// focus the item
lastDay.focus();
// focus the item
lastDay.focus();
}

if (iNewMonth > 11) {
iNewMonth = 0;
Expand All @@ -356,36 +362,60 @@ class Calendar extends WebComponent {
oNewDate.setYear(iNewYear);
oNewDate.setMonth(iNewMonth);


if (oNewDate.getYear() < YearPicker._MIN_YEAR) {
return;
}
this.timestamp = oNewDate.valueOf() / 1000;
}

_showNextYear() {
if (this._calendarDate.getYear() === YearPicker._MAX_YEAR) {
return;
}

const oNewDate = this._calendarDate;
oNewDate.setYear(this._calendarDate.getYear() + 1);

this.timestamp = oNewDate.valueOf() / 1000;
}

_showPrevYear() {
if (this._calendarDate.getYear() === YearPicker._MIN_YEAR) {
return;
}

const oNewDate = this._calendarDate;
oNewDate.setYear(this._calendarDate.getYear() - 1);

this.timestamp = oNewDate.valueOf() / 1000;
}

_showNextPageYears() {
if (!this._isYearInRange(this._yearPicker.timestamp,
YearPicker._ITEMS_COUNT - YearPicker._MIDDLE_ITEM_INDEX,
YearPicker._MIN_YEAR,
YearPicker._MAX_YEAR)) {
return;
}

this._yearPicker = Object.assign({}, this._yearPicker, {
// add 20 years to the timestamp of the monthpicker
timestamp: this._yearPicker.timestamp + (31536000 * 20),
timestamp: this._yearPicker.timestamp + (31536000 * YearPicker._ITEMS_COUNT),
});

this._isShiftingYears = true;
}

_showPrevPageYears() {
if (!this._isYearInRange(this._yearPicker.timestamp,
-YearPicker._MIDDLE_ITEM_INDEX - 1,
YearPicker._MIN_YEAR,
YearPicker._MAX_YEAR)) {
return;
}

this._yearPicker = Object.assign({}, this._yearPicker, {
// subtracts 20 years from the timestamp of the monthpicker
timestamp: this._yearPicker.timestamp - (31536000 * 20),
timestamp: this._yearPicker.timestamp - (31536000 * YearPicker._ITEMS_COUNT),
});

this._isShiftingYears = true;
Expand Down Expand Up @@ -436,6 +466,16 @@ class Calendar extends WebComponent {
this._oMonth._hidden = false;
}

_isYearInRange(timestamp, yearsoffset, min, max) {
if (timestamp) {
const oCalDate = CalendarDate.fromTimestamp(timestamp * 1000, this._primaryCalendarType);
oCalDate.setMonth(0);
oCalDate.setDate(1);
oCalDate.setYear(oCalDate.getYear() + yearsoffset);
return oCalDate.getYear() >= min && oCalDate.getYear() <= max;
}
}

static get calculateTemplateContext() {
return CalendarTemplateContext.calculate;
}
Expand Down
5 changes: 5 additions & 0 deletions packages/main/src/DatePicker.js
Original file line number Diff line number Diff line change
Expand Up @@ -464,6 +464,11 @@ class DatePicker extends WebComponent {
}

_changeCalendarSelection() {
if (this._calendarDate.getYear() < 1) {
// 0 is a valid year, but we cannot display it
return;
}

const oCalDate = this._calendarDate;
const timestamp = oCalDate.valueOf() / 1000;

Expand Down
42 changes: 23 additions & 19 deletions packages/main/src/DayPicker.hbs
Original file line number Diff line number Diff line change
Expand Up @@ -22,25 +22,29 @@
</div>
<div id="{{ctr._id}}-days" class="sapWCDayPickerItemsContainer" tabindex="-1">
{{#each ctr._weeks}}
<div style="display: flex;">
{{#each this}}
<div
id="{{this.id}}"
tabindex="{{this._tabIndex}}"
data-sap-timestamp="{{this.timestamp}}"
data-sap-index="{{this._index}}"
role="gridcell"
aria-selected="{{this.selected}}"
class="{{this.classes}} sapWCDayPickerDay">
<span
class="sapWCDayPickerDayText"
data-sap-timestamp="{{this.timestamp}}"
data-sap-index="{{this._index}}">
{{this.iDay}}
</span>
</div>
{{/each}}
</div>
{{#if this.length}}
<div style="display: flex;">
{{#each this}}
<div
id="{{this.id}}"
tabindex="{{this._tabIndex}}"
data-sap-timestamp="{{this.timestamp}}"
data-sap-index="{{this._index}}"
role="gridcell"
aria-selected="{{this.selected}}"
class="{{this.classes}} sapWCDayPickerDay">
<span
class="sapWCDayPickerDayText"
data-sap-timestamp="{{this.timestamp}}"
data-sap-index="{{this._index}}">
{{this.iDay}}
</span>
</div>
{{/each}}
</div>
{{else}}
<div class="sapWCEmptyWeek"></div>
{{/if}}
{{/each}}
</div>
</div>
Expand Down
20 changes: 16 additions & 4 deletions packages/main/src/DayPicker.js
Original file line number Diff line number Diff line change
Expand Up @@ -94,6 +94,9 @@ const metadata = {
},
};

const MAX_YEAR = 9999;
const MIN_YEAR = 1;

/**
* @class
*
Expand Down Expand Up @@ -164,7 +167,7 @@ class DayPicker extends WebComponent {
return d === timestamp;
}),
iDay: oCalDate.getDate(),
_index: i,
_index: i.toString(),
classes: `sapWCDayPickerItem sapWCDayPickerWDay${weekday}`,
};

Expand Down Expand Up @@ -206,11 +209,16 @@ class DayPicker extends WebComponent {
day.classes += " sapWCDayPickerItemWeekEnd";
}

if (day.classes.indexOf("sapWCDayPickerWDay6") !== -1) {
if (day.classes.indexOf("sapWCDayPickerWDay6") !== -1
|| _aVisibleDays.length - 1 === i) {
this._weeks.push(week);
week = [];
}
}

while (this._weeks.length < 6) {
this._weeks.push([]);
}
/* eslint-enable no-loop-func */

if (!isDaySelected && todayIndex && this._itemNav.current === 0) {
Expand Down Expand Up @@ -339,6 +347,10 @@ class DayPicker extends WebComponent {
oNewDate.setYear(iNewYear);
oNewDate.setMonth(iNewMonth);

if (oNewDate.getYear() < MIN_YEAR || oNewDate.getYear() > MAX_YEAR) {
return;
}

this.fireEvent("navigate", { timestamp: (oNewDate.valueOf() / 1000) });
}

Expand Down Expand Up @@ -382,12 +394,12 @@ class DayPicker extends WebComponent {
for (let i = 0; i < 42; i++) {
iYear = oDay.getYear();
oCalDate = new CalendarDate(oDay, this._primaryCalendarType);
if (bIncludeBCDates && iYear < 1) {
if (bIncludeBCDates && iYear < MIN_YEAR) {
// For dates before 0001-01-01 we should render only empty squares to keep
// the month square matrix correct.
oCalDate._bBeforeFirstYear = true;
_aVisibleDays.push(oCalDate);
} else if (iYear > 0 && iYear < 10000) {
} else if (iYear >= MIN_YEAR && iYear <= MAX_YEAR) {
// Days before 0001-01-01 or after 9999-12-31 should not be rendered.
_aVisibleDays.push(oCalDate);
}
Expand Down
44 changes: 31 additions & 13 deletions packages/main/src/YearPicker.js
Original file line number Diff line number Diff line change
Expand Up @@ -65,9 +65,6 @@ const metadata = {
},
};

const ITEMS_COUNT = 20;
const MIDDLE_ITEM_INDEX = 7;

/**
* @class
*
Expand Down Expand Up @@ -117,16 +114,29 @@ class YearPicker extends WebComponent {
const oCalDate = this._calendarDate;
oCalDate.setMonth(0);
oCalDate.setDate(1);
oCalDate.setYear(oCalDate.getYear() - MIDDLE_ITEM_INDEX - 1);
if (oCalDate.getYear() - YearPicker._MIDDLE_ITEM_INDEX - 1 > YearPicker._MAX_YEAR - YearPicker._ITEMS_COUNT) {
oCalDate.setYear(YearPicker._MAX_YEAR - YearPicker._ITEMS_COUNT);
} else if (oCalDate.getYear() - YearPicker._MIDDLE_ITEM_INDEX - 1 < YearPicker._MIN_YEAR) {
oCalDate.setYear(YearPicker._MIN_YEAR - 1);
} else {
oCalDate.setYear(oCalDate.getYear() - YearPicker._MIDDLE_ITEM_INDEX - 1);
}

const intervals = [];
let timestamp;

if (this._selectedYear === undefined) {
this._selectedYear = this._year;
}

for (let i = 0; i < ITEMS_COUNT; i++) {
for (let i = 0; i < YearPicker._ITEMS_COUNT; i++) {
const intervalIndex = parseInt(i / 4);
if (!intervals[intervalIndex]) {
intervals[intervalIndex] = [];
}

oCalDate.setYear(oCalDate.getYear() + 1);

timestamp = oCalDate.valueOf() / 1000;

const year = {
Expand All @@ -140,12 +150,8 @@ class YearPicker extends WebComponent {
year.classes += " sapWCYearPickerItemSel";
}

const intervalIndex = parseInt(i / 4);

if (intervals[intervalIndex]) {
intervals[intervalIndex].push(year);
} else {
intervals[intervalIndex] = [year];
}
}

Expand Down Expand Up @@ -183,7 +189,7 @@ class YearPicker extends WebComponent {
const timestamp = this.getTimestampFromDom(event.ui5target);
this.timestamp = timestamp;
this._selectedYear = this._year;
this._itemNav.current = MIDDLE_ITEM_INDEX;
this._itemNav.current = YearPicker._MIDDLE_ITEM_INDEX;
this.fireEvent("selectedYearChange", { timestamp });
}
}
Expand All @@ -204,7 +210,7 @@ class YearPicker extends WebComponent {

this.timestamp = timestamp;
this._selectedYear = this._year;
this._itemNav.current = MIDDLE_ITEM_INDEX;
this._itemNav.current = YearPicker._MIDDLE_ITEM_INDEX;
this.fireEvent("selectedYearChange", { timestamp });
}
}
Expand All @@ -227,15 +233,27 @@ class YearPicker extends WebComponent {
oCalDate.setDate(1);

if (event.end) {
oCalDate.setYear(oCalDate.getYear() + ITEMS_COUNT);
oCalDate.setYear(oCalDate.getYear() + YearPicker._ITEMS_COUNT);
} else if (event.start) {
oCalDate.setYear(oCalDate.getYear() - ITEMS_COUNT);
if (oCalDate.getYear() - YearPicker._MIDDLE_ITEM_INDEX < YearPicker._MIN_YEAR) {
return;
}
oCalDate.setYear(oCalDate.getYear() - YearPicker._ITEMS_COUNT);
}

if (oCalDate.getYear() - YearPicker._MIDDLE_ITEM_INDEX > YearPicker._MAX_YEAR) {
return;
}

this.timestamp = oCalDate.valueOf() / 1000;
}
}

YearPicker._ITEMS_COUNT = 20;
YearPicker._MIDDLE_ITEM_INDEX = 7;
YearPicker._MAX_YEAR = 9999;
YearPicker._MIN_YEAR = 1;

Bootstrap.boot().then(_ => {
YearPicker.define();
});
Expand Down
11 changes: 11 additions & 0 deletions packages/main/src/themes/base/DayPicker.less
Original file line number Diff line number Diff line change
Expand Up @@ -165,6 +165,13 @@ ui5-daypicker {

.sapWCDayPickerItemsContainer {
outline: none;
& > :first-child {
justify-content: flex-end;
}
}

.sapWCEmptyWeek {
height: 3rem;
}

.sapUiSizeCompact {
Expand All @@ -182,4 +189,8 @@ ui5-daypicker {
margin-top: 2px;
margin-right: 2px;
}

& .sapWCEmptyWeek {
height: 2.125rem;
}
}
Loading

0 comments on commit d1c7259

Please sign in to comment.