Skip to content

Commit

Permalink
Merge 8cb34b9 into b1730dd
Browse files Browse the repository at this point in the history
  • Loading branch information
limscoder committed Mar 1, 2016
2 parents b1730dd + 8cb34b9 commit 8b580ac
Show file tree
Hide file tree
Showing 2 changed files with 312 additions and 90 deletions.
213 changes: 130 additions & 83 deletions src/DayPicker.js
Expand Up @@ -5,7 +5,9 @@ import * as LocaleUtils from "./LocaleUtils";

const keys = {
LEFT: 37,
UP: 38,
RIGHT: 39,
DOWN: 40,
ENTER: 13,
SPACE: 32
};
Expand All @@ -25,7 +27,7 @@ class Caption extends Component {
export default class DayPicker extends Component {

static propTypes = {

tabIndex: PropTypes.number,
initialMonth: PropTypes.instanceOf(Date),
numberOfMonths: PropTypes.number,

Expand Down Expand Up @@ -54,7 +56,6 @@ export default class DayPicker extends Component {
renderDay: PropTypes.func,

captionElement: PropTypes.element

};

static defaultProps = {
Expand Down Expand Up @@ -85,21 +86,13 @@ export default class DayPicker extends Component {
}

allowPreviousMonth() {
const { fromMonth } = this.props;
if (!fromMonth) {
return true;
}
const { currentMonth } = this.state;
return Helpers.getMonthsDiff(currentMonth, fromMonth) < 0;
const previousMonth = DateUtils.addMonths(this.state.currentMonth, -1)
return this.allowMonth(previousMonth);
}

allowNextMonth() {
const { toMonth, numberOfMonths } = this.props;
if (!toMonth) {
return true;
}
const { currentMonth } = this.state;
return Helpers.getMonthsDiff(currentMonth, toMonth) >= numberOfMonths;
const nextMonth = DateUtils.addMonths(this.state.currentMonth, this.props.numberOfMonths);
return this.allowMonth(nextMonth);
}

allowMonth(d) {
Expand All @@ -111,24 +104,18 @@ export default class DayPicker extends Component {
return true;
}

showMonth(d) {
showMonth(d, callback) {
if (!this.allowMonth(d)) {
return;
}

this.setState({
currentMonth: Helpers.startOfMonth(d)
});
}, callback);
}

showNextMonth(callback) {
if (!this.allowNextMonth()) {
return;
}
const { currentMonth } = this.state;
const nextMonth = DateUtils.addMonths(currentMonth, 1);
this.setState({
currentMonth: nextMonth
}, () => {
showMonthAndCallHandler(d, callback) {
this.showMonth(d, () => {
if (callback) {
callback();
}
Expand All @@ -138,79 +125,119 @@ export default class DayPicker extends Component {
});
}

showNextMonth(callback) {
if (this.allowNextMonth()) {
const nextMonth = DateUtils.addMonths(this.state.currentMonth, 1);
this.showMonthAndCallHandler(nextMonth, callback);
}
}

showPreviousMonth(callback) {
if (!this.allowPreviousMonth()) {
return;
if (this.allowPreviousMonth()) {
const previousMonth = DateUtils.addMonths(this.state.currentMonth, -1);
this.showMonthAndCallHandler(previousMonth, callback);
}
const { currentMonth } = this.state;
const prevMonth = DateUtils.addMonths(currentMonth, -1);
this.setState({
currentMonth: prevMonth
}, () => {
if (callback) {
callback();
}
if (this.props.onMonthChange) {
this.props.onMonthChange(this.state.currentMonth);
}
});
}

focusPreviousDay(dayNode) {
const body = dayNode.parentNode.parentNode.parentNode.parentNode;
let dayNodes = body.querySelectorAll(".DayPicker-Day:not(.DayPicker-Day--outside)");
let nodeIndex;
showNextYear(callback) {
const nextMonth = DateUtils.addMonths(this.state.currentMonth, 12);
this.showMonthAndCallHandler(nextMonth, callback);
}

showPreviousYear(callback) {
const nextMonth = DateUtils.addMonths(this.state.currentMonth, -12);
this.showMonthAndCallHandler(nextMonth, callback);
}

getDayNodes() {
return this.refs.dayPicker.querySelectorAll(".DayPicker-Day:not(.DayPicker-Day--outside)");
}

getDayNodeIndex(dayNode, dayNodes) {
for (let i = 0; i < dayNodes.length; i++) {
if (dayNodes[i] === dayNode) {
nodeIndex = i;
break;
return i;
}
}
if (nodeIndex === 0) {
const { currentMonth } = this.state;
const { numberOfMonths } = this.props;
const prevMonth = DateUtils.addMonths(currentMonth, -numberOfMonths);
this.setState({
currentMonth: prevMonth
}, () => {
dayNodes = body.querySelectorAll(".DayPicker-Day:not(.DayPicker-Day--outside)");
dayNodes[dayNodes.length - 1].focus();
});

return -1;
}

focusFirstDayOfMonth() {
this.getDayNodes()[0].focus();
}

focusLastDayOfMonth() {
const dayNodes = this.getDayNodes();
dayNodes[dayNodes.length - 1].focus();
}

focusPreviousDay(dayNode) {
const dayNodes = this.getDayNodes();
const dayNodeIndex = this.getDayNodeIndex(dayNode, dayNodes);

if (dayNodeIndex === 0) {
this.showPreviousMonth(() => { this.focusLastDayOfMonth() })
}
else {
dayNodes[nodeIndex - 1].focus();
dayNodes[dayNodeIndex - 1].focus();
}
}

focusNextDay(dayNode) {
const body = dayNode.parentNode.parentNode.parentNode.parentNode;
let dayNodes = body.querySelectorAll(".DayPicker-Day:not(.DayPicker-Day--outside)");
let nodeIndex;
for (let i = 0; i < dayNodes.length; i++) {
if (dayNodes[i] === dayNode) {
nodeIndex = i;
break;
}
const dayNodes = this.getDayNodes();
const dayNodeIndex = this.getDayNodeIndex(dayNode, dayNodes);

if (dayNodeIndex === dayNodes.length - 1) {
this.showNextMonth(() => { this.focusFirstDayOfMonth() });
}
else {
dayNodes[dayNodeIndex + 1].focus();
}
}

if (nodeIndex === dayNodes.length - 1) {
const { currentMonth } = this.state;
const { numberOfMonths } = this.props;
const nextMonth = DateUtils.addMonths(currentMonth, numberOfMonths);
this.setState({
currentMonth: nextMonth
}, () => {
dayNodes = body.querySelectorAll(".DayPicker-Day:not(.DayPicker-Day--outside)");
dayNodes[0].focus();
focusNextWeek(dayNode) {
const dayNodes = this.getDayNodes();
const dayNodeIndex = this.getDayNodeIndex(dayNode, dayNodes);
const isInLastWeekOfMonth = dayNodeIndex > dayNodes.length - 8;

if (isInLastWeekOfMonth) {
this.showNextMonth(() => {
const daysAfterIndex = dayNodes.length - dayNodeIndex;
const nextMonthDayNodeIndex = 7 - daysAfterIndex;
this.getDayNodes()[nextMonthDayNodeIndex].focus();
});
}
else {
dayNodes[nodeIndex + 1].focus();
dayNodes[dayNodeIndex + 7].focus();
}
}

focusPreviousWeek(dayNode) {
const dayNodes = this.getDayNodes();
const dayNodeIndex = this.getDayNodeIndex(dayNode, dayNodes);
const isInFirstWeekOfMonth = dayNodeIndex <= 6;

if (isInFirstWeekOfMonth) {
this.showPreviousMonth(() => {
const previousMonthDayNodes = this.getDayNodes();
const startOfLastWeekOfMonth = previousMonthDayNodes.length - 7;
const previousMonthDayNodeIndex = startOfLastWeekOfMonth + dayNodeIndex;
previousMonthDayNodes[previousMonthDayNodeIndex].focus();
});
}
else {
dayNodes[dayNodeIndex - 7].focus();
}
}

// Event handlers

cancelEvent(e) {
e.preventDefault();
e.stopPropagation();
}

handleKeyDown(e) {
e.persist();

Expand All @@ -229,6 +256,12 @@ export default class DayPicker extends Component {
case keys.RIGHT:
this.showNextMonth(callback);
break;
case keys.UP:
this.showPreviousYear(callback);
break;
case keys.DOWN:
this.showNextYear(callback);
break;
}
}
}
Expand All @@ -237,19 +270,24 @@ export default class DayPicker extends Component {
e.persist();
switch (e.keyCode) {
case keys.LEFT:
e.preventDefault();
e.stopPropagation();
this.cancelEvent(e);
this.focusPreviousDay(e.target);
break;
case keys.RIGHT:
e.preventDefault();
e.stopPropagation();
this.cancelEvent(e);
this.focusNextDay(e.target);
break;
case keys.UP:
this.cancelEvent(e);
this.focusPreviousWeek(e.target);
break;
case keys.DOWN:
this.cancelEvent(e);
this.focusNextWeek(e.target);
break;
case keys.ENTER:
case keys.SPACE:
e.preventDefault();
e.stopPropagation();
this.cancelEvent(e);
if (this.props.onDayClick) {
this.handleDayClick(e, day, modifiers);
}
Expand Down Expand Up @@ -318,6 +356,7 @@ export default class DayPicker extends Component {

const leftButton = isRTL ? this.allowNextMonth() : this.allowPreviousMonth();
const rightButton = isRTL ? this.allowPreviousMonth() : this.allowNextMonth();

return (
<div className="DayPicker-NavBar">
{ leftButton &&
Expand Down Expand Up @@ -353,12 +392,12 @@ export default class DayPicker extends Component {

{ caption }

<div className="DayPicker-Weekdays">
<div className="DayPicker-WeekdaysRow">
<div className="DayPicker-Weekdays" role="rowgroup">
<div className="DayPicker-WeekdaysRow" role="columnheader">
{ this.renderWeekDays() }
</div>
</div>
<div className="DayPicker-Body">
<div className="DayPicker-Body" role="rowgroup">
{ this.renderWeeksInMonth(date) }
</div>
</div>
Expand Down Expand Up @@ -429,10 +468,17 @@ export default class DayPicker extends Component {
tabIndex = this.props.tabIndex;
}
}

const ariaLabel = this.props.localeUtils.formatDate ?
this.props.localeUtils.formatDate(day) : day.toDateString();
const ariaDisabled = isOutside ? "true" : "false";

return (
<div key={ key } className={ className }
tabIndex={ tabIndex }
role="gridcell"
aria-label={ ariaLabel }
aria-disabled={ ariaDisabled }
onKeyDown={
(e) => this.handleDayKeyDown(e, day, modifiers) }
onMouseEnter= { onDayMouseEnter ?
Expand Down Expand Up @@ -470,6 +516,7 @@ export default class DayPicker extends Component {

return (
<div className={ className }
ref="dayPicker"
role="widget"
tabIndex={ canChangeMonth && attributes.tabIndex }
onKeyDown={ e => this.handleKeyDown(e) }
Expand Down

0 comments on commit 8b580ac

Please sign in to comment.