🚀 Big News:Socket Has Acquired Secure Annex.Learn More
Socket
Book a DemoSign in
Socket

rc-calendar

Package Overview
Dependencies
Maintainers
1
Versions
239
Alerts
File Explorer

Advanced tools

Socket logo

Install Socket

Detect and block malicious and high-risk dependencies

Install

rc-calendar - npm Package Compare versions

Comparing version
3.4.2
to
3.5.0
+596
lib/Calendar.js
'use strict';
var _createClass = (function () { function defineProperties(target, props) { for (var i = 0; i < props.length; i++) { var descriptor = props[i]; descriptor.enumerable = descriptor.enumerable || false; descriptor.configurable = true; if ('value' in descriptor) descriptor.writable = true; Object.defineProperty(target, descriptor.key, descriptor); } } return function (Constructor, protoProps, staticProps) { if (protoProps) defineProperties(Constructor.prototype, protoProps); if (staticProps) defineProperties(Constructor, staticProps); return Constructor; }; })();
var _get = function get(_x, _x2, _x3) { var _again = true; _function: while (_again) { var object = _x, property = _x2, receiver = _x3; desc = parent = getter = undefined; _again = false; var desc = Object.getOwnPropertyDescriptor(object, property); if (desc === undefined) { var parent = Object.getPrototypeOf(object); if (parent === null) { return undefined; } else { _x = parent; _x2 = property; _x3 = receiver; _again = true; continue _function; } } else if ('value' in desc) { return desc.value; } else { var getter = desc.get; if (getter === undefined) { return undefined; } return getter.call(receiver); } } };
function _classCallCheck(instance, Constructor) { if (!(instance instanceof Constructor)) { throw new TypeError('Cannot call a class as a function'); } }
function _inherits(subClass, superClass) { if (typeof superClass !== 'function' && superClass !== null) { throw new TypeError('Super expression must either be null or a function, not ' + typeof superClass); } subClass.prototype = Object.create(superClass && superClass.prototype, { constructor: { value: subClass, enumerable: false, writable: true, configurable: true } }); if (superClass) subClass.__proto__ = superClass; }
var React = require('react');
var DATE_ROW_COUNT = 6;
var DATE_COL_COUNT = 7;
var DateTimeFormat = require('gregorian-calendar-format');
var GregorianCalendar = require('gregorian-calendar');
var rcUtil = require('rc-util');
var KeyCode = rcUtil.KeyCode;
var MonthPanel = require('./MonthPanel');
var Time = require('./Time');
function noop() {}
function getIdFromDate(d) {
return 'rc-calendar-' + d.getYear() + '-' + d.getMonth() + '-' + d.getDayOfMonth();
}
function goStartMonth() {
var next = this.state.value.clone();
next.setDayOfMonth(1);
this.setState({ value: next });
}
function goEndMonth() {
var next = this.state.value.clone();
next.setDayOfMonth(next.getActualMaximum(GregorianCalendar.MONTH));
this.setState({ value: next });
}
function goMonth(direction) {
var next = this.state.value.clone();
next.addMonth(direction);
this.setState({ value: next });
}
function goYear(direction) {
var next = this.state.value.clone();
next.addYear(direction);
this.setState({ value: next });
}
function goWeek(direction) {
var next = this.state.value.clone();
next.addWeekOfYear(direction);
this.setState({ value: next });
}
function goDay(direction) {
var next = this.state.value.clone();
next.addDayOfMonth(direction);
this.setState({ value: next });
}
function isSameDay(one, two) {
return one.getYear() === two.getYear() && one.getMonth() === two.getMonth() && one.getDayOfMonth() === two.getDayOfMonth();
}
function beforeCurrentMonthYear(current, today) {
if (current.getYear() < today.getYear()) {
return 1;
}
return current.getYear() === today.getYear() && current.getMonth() < today.getMonth();
}
function afterCurrentMonthYear(current, today) {
if (current.getYear() > today.getYear()) {
return 1;
}
return current.getYear() === today.getYear() && current.getMonth() > today.getMonth();
}
function onFocus() {
if (this._blurTimer) {
clearTimeout(this._blurTimer);
this._blurTimer = null;
} else {
this.props.onFocus();
}
}
function onBlur() {
var _this = this;
if (this._blurTimer) {
clearTimeout(this._blurTimer);
}
this._blurTimer = setTimeout(function () {
_this.props.onBlur();
}, 100);
}
function chooseToday() {
var today = this.state.value.clone();
today.setTime(Date.now());
this.handleSelect(today);
}
function handleDayClick(current) {
this.handleSelect(current);
}
function handleSelect(current, keyDownEvent) {
var props = this.props;
this.setState({
value: current
});
if (!keyDownEvent) {
props.onSelect(current);
}
}
function clear() {
this.props.onClear();
}
function onMonthPanelSelect(current) {
this.setState({
value: current,
showMonthPanel: 0
});
}
function handleKeyDown(e) {
var keyCode = e.keyCode;
// mac
var ctrlKey = e.ctrlKey || e.metaKey;
switch (keyCode) {
case KeyCode.DOWN:
goWeek.call(this, 1);
e.preventDefault();
return true;
case KeyCode.UP:
goWeek.call(this, -1);
e.preventDefault();
return true;
case KeyCode.LEFT:
if (ctrlKey) {
this.previousYear();
} else {
goDay.call(this, -1);
}
e.preventDefault();
return true;
case KeyCode.RIGHT:
if (ctrlKey) {
this.nextYear();
} else {
goDay.call(this, 1);
}
e.preventDefault();
return true;
case KeyCode.HOME:
goStartMonth.call(this);
e.preventDefault();
return true;
case KeyCode.END:
goEndMonth.call(this);
e.preventDefault();
return true;
case KeyCode.PAGE_DOWN:
this.nextMonth();
e.preventDefault();
return true;
case KeyCode.PAGE_UP:
this.previousMonth();
e.preventDefault();
return true;
case KeyCode.ENTER:
this.props.onSelect(this.state.value);
e.preventDefault();
return true;
default:
this.props.onKeyDown(e);
return true;
}
}
function showMonthPanel() {
this.setState({
showMonthPanel: 1
});
}
var Calendar = (function (_React$Component) {
function Calendar(props) {
_classCallCheck(this, Calendar);
_get(Object.getPrototypeOf(Calendar.prototype), 'constructor', this).call(this, props);
var value = props.value || props.defaultValue;
if (!value) {
value = new GregorianCalendar();
value.setTime(Date.now());
}
this.dateFormatter = new DateTimeFormat(props.locale.dateFormat);
this.state = {
orient: props.orient,
prefixCls: props.prefixCls || 'rc-calendar',
value: value
};
// bind methods
this.onBlur = onBlur.bind(this);
this.onFocus = onFocus.bind(this);
this.prefixClsFn = require('./prefixClsFn').bind(this);
this.nextMonth = goMonth.bind(this, 1);
this.previousMonth = goMonth.bind(this, -1);
this.nextYear = goYear.bind(this, 1);
this.previousYear = goYear.bind(this, -1);
this.chooseToday = chooseToday.bind(this);
this.clear = clear.bind(this);
this.handleSelect = handleSelect.bind(this);
this.onMonthPanelSelect = onMonthPanelSelect.bind(this);
this.handleKeyDown = handleKeyDown.bind(this);
this.showMonthPanel = showMonthPanel.bind(this);
}
_inherits(Calendar, _React$Component);
_createClass(Calendar, [{
key: 'shouldComponentUpdate',
value: function shouldComponentUpdate() {
return rcUtil.PureRenderMixin.shouldComponentUpdate.apply(this, arguments);
}
}, {
key: 'componentWillReceiveProps',
value: function componentWillReceiveProps(nextProps) {
var value = nextProps.value;
if (value !== undefined) {
if (!value) {
value = this.state.value.clone();
value.setTime(Date.now());
}
this.setState({
value: value
});
}
if (nextProps.orient) {
this.setState({
orient: nextProps.orient
});
}
if (nextProps.locale !== this.props.locale) {
this.dateFormatter = new DateTimeFormat(nextProps.locale.dateFormat);
}
}
}, {
key: 'renderDates',
value: function renderDates() {
var props = this.props;
var i, j, current;
var dateTable = [];
var showWeekNumber = props.showWeekNumber;
var value = this.state.value;
var today = value.clone();
var prefixClsFn = this.prefixClsFn;
var cellClass = prefixClsFn('cell');
var weekNumberCellClass = prefixClsFn('week-number-cell');
var dateClass = prefixClsFn('date');
var dateRender = props.dateRender;
var disabledDate = props.disabledDate;
var dateFormatter = this.dateFormatter;
var todayClass = prefixClsFn('today');
var selectedClass = prefixClsFn('selected-day');
var lastMonthDayClass = prefixClsFn('last-month-cell');
var nextMonthDayClass = prefixClsFn('next-month-btn-day');
var disabledClass = prefixClsFn('disabled-cell');
today.setTime(Date.now());
var month1 = value.clone();
month1.set(value.getYear(), value.getMonth(), 1);
var day = month1.getDayOfWeek();
var lastMonthDiffDay = (day + 7 - value.getFirstDayOfWeek()) % 7;
// calculate last month
var lastMonth1 = month1.clone();
lastMonth1.addDayOfMonth(0 - lastMonthDiffDay);
var passed = 0;
for (i = 0; i < DATE_ROW_COUNT; i++) {
for (j = 0; j < DATE_COL_COUNT; j++) {
current = lastMonth1;
if (passed) {
current = current.clone();
current.addDayOfMonth(passed);
}
dateTable.push(current);
passed++;
}
}
var tableHtml = [];
passed = 0;
for (i = 0; i < DATE_ROW_COUNT; i++) {
var weekNumberCell;
var dateCells = [];
if (showWeekNumber) {
weekNumberCell = React.createElement(
'td',
{ key: dateTable[passed].getWeekOfYear(), role: 'gridcell', className: weekNumberCellClass },
dateTable[passed].getWeekOfYear()
);
}
for (j = 0; j < DATE_COL_COUNT; j++) {
current = dateTable[passed];
var cls = cellClass;
var disabled = false;
var selected = false;
if (isSameDay(current, today)) {
cls += ' ' + todayClass;
}
if (isSameDay(current, value)) {
cls += ' ' + selectedClass;
selected = true;
}
if (beforeCurrentMonthYear(current, value)) {
cls += ' ' + lastMonthDayClass;
}
if (afterCurrentMonthYear(current, value)) {
cls += ' ' + nextMonthDayClass;
}
if (disabledDate && disabledDate(current, value)) {
cls += ' ' + disabledClass;
disabled = true;
}
var dateHtml;
if (!(dateRender && (dateHtml = dateRender(current, value)))) {
dateHtml = React.createElement(
'span',
{
key: getIdFromDate(current),
className: dateClass,
'aria-selected': selected,
'aria-disabled': disabled },
current.getDayOfMonth()
);
}
dateCells.push(React.createElement(
'td',
{ key: passed, onClick: disabled ? noop : handleDayClick.bind(this, current), role: 'gridcell', title: dateFormatter.format(current), className: cls },
dateHtml
));
passed++;
}
tableHtml.push(React.createElement(
'tr',
{
key: i,
role: 'row' },
weekNumberCell,
dateCells
));
}
this.dateTable = dateTable;
return tableHtml;
}
}, {
key: 'getTodayTime',
value: function getTodayTime() {
var value = this.state.value;
var today = value.clone();
today.setTime(Date.now());
return this.dateFormatter.format(today);
}
}, {
key: 'getMonthYear',
value: function getMonthYear() {
var locale = this.props.locale;
var value = this.state.value;
return new DateTimeFormat(locale.monthYearFormat).format(value);
}
}, {
key: 'render',
value: function render() {
// console.log('re render');
var showWeekNumberEl;
var props = this.props;
var locale = props.locale;
var state = this.state;
var value = state.value;
var veryShortWeekdays = [];
var weekDays = [];
var firstDayOfWeek = value.getFirstDayOfWeek();
var prefixCls = state.prefixCls;
var prefixClsFn = this.prefixClsFn;
for (var i = 0; i < DATE_COL_COUNT; i++) {
var index = (firstDayOfWeek + i) % DATE_COL_COUNT;
veryShortWeekdays[i] = locale.format.veryShortWeekdays[index];
weekDays[i] = locale.format.weekdays[index];
}
if (props.showWeekNumber) {
showWeekNumberEl = React.createElement(
'th',
{ role: 'columnheader', className: prefixClsFn('column-header', 'week-number-header') },
React.createElement(
'span',
{ className: prefixClsFn('column-header-inner') },
'x'
)
);
}
var weekDaysEls = weekDays.map(function (day, xindex) {
return React.createElement(
'th',
{ key: xindex, role: 'columnheader', title: day, className: prefixClsFn('column-header') },
React.createElement(
'span',
{ className: prefixClsFn('column-header-inner') },
veryShortWeekdays[xindex]
)
);
});
var footerEl;
if (props.showToday || props.showTime) {
var todayEl;
if (props.showToday) {
todayEl = React.createElement(
'a',
{ className: prefixClsFn('today-btn'),
role: 'button',
onClick: this.chooseToday,
title: this.getTodayTime() },
locale.today
);
}
var clearEl;
if (props.showClear) {
clearEl = React.createElement(
'a',
{ className: prefixClsFn('clear-btn'),
role: 'button',
onClick: this.clear },
locale.clear
);
}
var footerBtn;
if (todayEl || clearEl) {
footerBtn = React.createElement(
'div',
{ className: prefixClsFn('footer-btn') },
todayEl,
' ',
clearEl
);
}
var timeEl;
if (props.showTime) {
timeEl = React.createElement(Time, { value: value, rootPrefixCls: prefixCls, prefixClsFn: prefixClsFn, locale: locale, onChange: this.handleSelect });
}
footerEl = React.createElement(
'div',
{ className: prefixClsFn('footer') },
timeEl,
footerBtn
);
}
var monthPanel;
if (state.showMonthPanel) {
monthPanel = React.createElement(MonthPanel, { locale: locale, value: value, rootPrefixCls: state.prefixCls, onSelect: this.onMonthPanelSelect });
}
var className = prefixCls;
if (props.className) {
className += ' ' + props.className;
}
var orient = state.orient;
if (orient) {
orient.forEach(function (o) {
className += ' ' + prefixClsFn('orient-' + o);
});
}
return React.createElement(
'div',
{ className: className, tabIndex: '0', onFocus: this.onFocus, onBlur: this.onBlur, onKeyDown: this.handleKeyDown },
React.createElement(
'div',
{ style: { outline: 'none' } },
React.createElement(
'div',
{ className: prefixClsFn('header') },
React.createElement(
'a',
{ className: prefixClsFn('prev-year-btn'),
role: 'button',
onClick: this.previousYear,
title: locale.previousYear },
'«'
),
React.createElement(
'a',
{ className: prefixClsFn('prev-month-btn'),
role: 'button',
onClick: this.previousMonth,
title: locale.previousMonth },
'‹'
),
React.createElement(
'a',
{ className: prefixClsFn('month-select'),
role: 'button',
onClick: this.showMonthPanel,
title: locale.monthSelect },
React.createElement(
'span',
{ className: prefixClsFn('month-select-content') },
this.getMonthYear()
),
React.createElement(
'span',
{ className: prefixClsFn('month-select-arrow') },
'x'
)
),
React.createElement(
'a',
{ className: prefixClsFn('next-month-btn'),
onClick: this.nextMonth,
title: locale.nextMonth },
'›'
),
React.createElement(
'a',
{ className: prefixClsFn('next-year-btn'),
onClick: this.nextYear,
title: locale.nextYear },
'»'
)
),
React.createElement(
'div',
{ className: prefixClsFn('calendar-body') },
React.createElement(
'table',
{ className: prefixClsFn('table'), cellSpacing: '0', role: 'grid' },
React.createElement(
'thead',
null,
React.createElement(
'tr',
{ role: 'row' },
showWeekNumberEl,
weekDaysEls
)
),
React.createElement(
'tbody',
{ className: prefixClsFn('tbody') },
this.renderDates()
)
)
),
footerEl
),
monthPanel
);
}
}]);
return Calendar;
})(React.Component);
Calendar.propTypes = {
value: React.PropTypes.object,
defaultValue: React.PropTypes.object,
className: React.PropTypes.string,
orient: React.PropTypes.arrayOf(React.PropTypes.oneOf(['left', 'top', 'right', 'bottom'])),
locale: React.PropTypes.object,
showWeekNumber: React.PropTypes.bool,
showToday: React.PropTypes.bool,
showTime: React.PropTypes.bool,
onSelect: React.PropTypes.func,
onBlur: React.PropTypes.func
};
Calendar.defaultProps = {
locale: require('./locale/en-us'),
onKeyDown: noop,
className: '',
showToday: true,
onSelect: noop,
onFocus: noop,
onBlur: noop,
onClear: noop
};
module.exports = Calendar;
'use strict';
var _createClass = (function () { function defineProperties(target, props) { for (var i = 0; i < props.length; i++) { var descriptor = props[i]; descriptor.enumerable = descriptor.enumerable || false; descriptor.configurable = true; if ('value' in descriptor) descriptor.writable = true; Object.defineProperty(target, descriptor.key, descriptor); } } return function (Constructor, protoProps, staticProps) { if (protoProps) defineProperties(Constructor.prototype, protoProps); if (staticProps) defineProperties(Constructor, staticProps); return Constructor; }; })();
var _get = function get(_x, _x2, _x3) { var _again = true; _function: while (_again) { var object = _x, property = _x2, receiver = _x3; desc = parent = getter = undefined; _again = false; var desc = Object.getOwnPropertyDescriptor(object, property); if (desc === undefined) { var parent = Object.getPrototypeOf(object); if (parent === null) { return undefined; } else { _x = parent; _x2 = property; _x3 = receiver; _again = true; continue _function; } } else if ('value' in desc) { return desc.value; } else { var getter = desc.get; if (getter === undefined) { return undefined; } return getter.call(receiver); } } };
function _classCallCheck(instance, Constructor) { if (!(instance instanceof Constructor)) { throw new TypeError('Cannot call a class as a function'); } }
function _inherits(subClass, superClass) { if (typeof superClass !== 'function' && superClass !== null) { throw new TypeError('Super expression must either be null or a function, not ' + typeof superClass); } subClass.prototype = Object.create(superClass && superClass.prototype, { constructor: { value: subClass, enumerable: false, writable: true, configurable: true } }); if (superClass) subClass.__proto__ = superClass; }
var React = require('react');
var ROW = 4;
var COL = 3;
var cx = require('rc-util').classSet;
function goYear(direction) {
var next = this.state.value.clone();
next.addYear(direction);
this.setState({
value: next
});
}
function chooseDecade(year, e) {
var next = this.state.value.clone();
next.setYear(year);
this.props.onSelect(next);
e.preventDefault();
}
var DecadePanel = (function (_React$Component) {
function DecadePanel(props) {
_classCallCheck(this, DecadePanel);
_get(Object.getPrototypeOf(DecadePanel.prototype), 'constructor', this).call(this, props);
this.state = {
value: props.value,
prefixCls: props.rootPrefixCls + '-decade-panel'
};
// bind methods
this.prefixClsFn = require('./prefixClsFn').bind(this);
this.nextCentury = goYear.bind(this, 100);
this.previousCentury = goYear.bind(this, -100);
}
_inherits(DecadePanel, _React$Component);
_createClass(DecadePanel, [{
key: 'render',
value: function render() {
var _this = this;
var value = this.state.value;
var locale = this.props.locale;
var currentYear = value.getYear();
var startYear = parseInt(currentYear / 100, 10) * 100;
var preYear = startYear - 10;
var endYear = startYear + 99;
var decades = [];
var index = 0;
var prefixClsFn = this.prefixClsFn;
for (var i = 0; i < ROW; i++) {
decades[i] = [];
for (var j = 0; j < COL; j++) {
decades[i][j] = {
startDecade: preYear + index * 10,
endDecade: preYear + index * 10 + 9
};
index++;
}
}
var decadesEls = decades.map(function (row, decadeIndex) {
var tds = row.map(function (d) {
var startDecade = d.startDecade;
var endDecade = d.endDecade;
var classNameMap = {};
classNameMap[prefixClsFn('cell')] = 1;
classNameMap[prefixClsFn('selected-cell')] = startDecade <= currentYear && currentYear <= endDecade;
classNameMap[prefixClsFn('last-century-cell')] = startDecade < startYear;
classNameMap[prefixClsFn('next-century-cell')] = endDecade > endYear;
return React.createElement(
'td',
{
key: startDecade,
onClick: chooseDecade.bind(_this, startDecade),
role: 'gridcell',
className: cx(classNameMap)
},
React.createElement(
'a',
{
className: prefixClsFn('decade') },
startDecade,
' - ',
endDecade
)
);
});
return React.createElement(
'tr',
{ key: decadeIndex, role: 'row' },
tds
);
});
return React.createElement(
'div',
{ className: this.state.prefixCls },
React.createElement(
'div',
{ className: prefixClsFn('header') },
React.createElement(
'a',
{ className: prefixClsFn('prev-century-btn'),
role: 'button',
onClick: this.previousCentury,
title: locale.previousCentury },
'«'
),
React.createElement(
'div',
{ className: prefixClsFn('century') },
startYear,
'-',
endYear
),
React.createElement(
'a',
{ className: prefixClsFn('next-century-btn'),
role: 'button',
onClick: this.nextCentury,
title: locale.nextCentury },
'»'
)
),
React.createElement(
'div',
{ className: prefixClsFn('body') },
React.createElement(
'table',
{ className: prefixClsFn('table'), cellSpacing: '0', role: 'grid' },
React.createElement(
'tbody',
{ className: prefixClsFn('tbody') },
decadesEls
)
)
)
);
}
}]);
return DecadePanel;
})(React.Component);
DecadePanel.defaultProps = {
onSelect: function onSelect() {}
};
module.exports = DecadePanel;
'use strict';
module.exports = require('./Calendar');
module.exports.Picker = require('./Picker');
'use strict';
var _createClass = (function () { function defineProperties(target, props) { for (var i = 0; i < props.length; i++) { var descriptor = props[i]; descriptor.enumerable = descriptor.enumerable || false; descriptor.configurable = true; if ('value' in descriptor) descriptor.writable = true; Object.defineProperty(target, descriptor.key, descriptor); } } return function (Constructor, protoProps, staticProps) { if (protoProps) defineProperties(Constructor.prototype, protoProps); if (staticProps) defineProperties(Constructor, staticProps); return Constructor; }; })();
var _get = function get(_x, _x2, _x3) { var _again = true; _function: while (_again) { var object = _x, property = _x2, receiver = _x3; desc = parent = getter = undefined; _again = false; var desc = Object.getOwnPropertyDescriptor(object, property); if (desc === undefined) { var parent = Object.getPrototypeOf(object); if (parent === null) { return undefined; } else { _x = parent; _x2 = property; _x3 = receiver; _again = true; continue _function; } } else if ('value' in desc) { return desc.value; } else { var getter = desc.get; if (getter === undefined) { return undefined; } return getter.call(receiver); } } };
function _classCallCheck(instance, Constructor) { if (!(instance instanceof Constructor)) { throw new TypeError('Cannot call a class as a function'); } }
function _inherits(subClass, superClass) { if (typeof superClass !== 'function' && superClass !== null) { throw new TypeError('Super expression must either be null or a function, not ' + typeof superClass); } subClass.prototype = Object.create(superClass && superClass.prototype, { constructor: { value: subClass, enumerable: false, writable: true, configurable: true } }); if (superClass) subClass.__proto__ = superClass; }
var React = require('react');
var DateTimeFormat = require('gregorian-calendar-format');
var ROW = 3;
var COL = 4;
var cx = require('rc-util').classSet;
var YearPanel = require('./YearPanel');
function goYear(direction) {
var next = this.state.value.clone();
next.addYear(direction);
this.setState({
value: next
});
}
function showYearPanel() {
this.setState({
showYearPanel: 1
});
}
function chooseMonth(month) {
var next = this.state.value.clone();
next.setMonth(month);
this.props.onSelect(next);
}
function onYearPanelSelect(current) {
this.setState({
value: current,
showYearPanel: 0
});
}
var MonthPanel = (function (_React$Component) {
function MonthPanel(props) {
_classCallCheck(this, MonthPanel);
_get(Object.getPrototypeOf(MonthPanel.prototype), 'constructor', this).call(this, props);
this.state = {
value: this.props.value,
prefixCls: this.props.rootPrefixCls + '-month-panel'
};
// bind methods
this.nextYear = goYear.bind(this, 1);
this.previousYear = goYear.bind(this, -1);
this.showYearPanel = showYearPanel.bind(this);
this.onYearPanelSelect = onYearPanelSelect.bind(this);
this.prefixClsFn = require('./prefixClsFn').bind(this);
}
_inherits(MonthPanel, _React$Component);
_createClass(MonthPanel, [{
key: 'getMonths',
value: function getMonths() {
var props = this.props;
var value = this.state.value;
var current = value.clone();
var locale = props.locale;
var monthYearFormat = locale.monthYearFormat;
var dateFormatter = new DateTimeFormat(monthYearFormat);
var months = [];
var shortMonths = locale.format.shortMonths;
var index = 0;
for (var i = 0; i < ROW; i++) {
months[i] = [];
for (var j = 0; j < COL; j++) {
current.setMonth(index);
months[i][j] = {
value: index,
content: shortMonths[index],
title: dateFormatter.format(current)
};
index++;
}
}
return months;
}
}, {
key: 'render',
value: function render() {
var _this = this;
var props = this.props;
var value = this.state.value;
var locale = props.locale;
var months = this.getMonths();
var year = value.getYear();
var currentMonth = value.getMonth();
var prefixClsFn = this.prefixClsFn;
var monthsEls = months.map(function (month, index) {
var tds = month.map(function (m) {
var classNameMap = {};
classNameMap[prefixClsFn('cell')] = 1;
classNameMap[prefixClsFn('selected-cell')] = m.value === currentMonth;
return React.createElement(
'td',
{ role: 'gridcell',
key: m.value,
onClick: chooseMonth.bind(_this, m.value),
title: m.title,
className: cx(classNameMap) },
React.createElement(
'a',
{
className: prefixClsFn('month') },
m.content
)
);
});
return React.createElement(
'tr',
{ key: index, role: 'row' },
tds
);
});
var yearPanel;
if (this.state.showYearPanel) {
yearPanel = React.createElement(YearPanel, { locale: locale, value: value, rootPrefixCls: props.rootPrefixCls, onSelect: this.onYearPanelSelect });
}
return React.createElement(
'div',
{ className: this.state.prefixCls },
React.createElement(
'div',
null,
React.createElement(
'div',
{ className: prefixClsFn('header') },
React.createElement(
'a',
{ className: prefixClsFn('prev-year-btn'),
role: 'button',
onClick: this.previousYear,
title: locale.previousYear },
'«'
),
React.createElement(
'a',
{ className: prefixClsFn('year-select'),
role: 'button',
onClick: this.showYearPanel,
title: locale.yearSelect },
React.createElement(
'span',
{ className: prefixClsFn('year-select-content') },
year
),
React.createElement(
'span',
{ className: prefixClsFn('year-select-arrow') },
'x'
)
),
React.createElement(
'a',
{ className: prefixClsFn('next-year-btn'),
role: 'button',
onClick: this.nextYear,
title: locale.nextYear },
'»'
)
),
React.createElement(
'div',
{ className: prefixClsFn('body') },
React.createElement(
'table',
{ className: prefixClsFn('table'), cellSpacing: '0', role: 'grid' },
React.createElement(
'tbody',
{ className: prefixClsFn('tbody') },
monthsEls
)
)
)
),
yearPanel
);
}
}]);
return MonthPanel;
})(React.Component);
MonthPanel.defaultProps = {
onSelect: function onSelect() {}
};
module.exports = MonthPanel;
'use strict';
var _createClass = (function () { function defineProperties(target, props) { for (var i = 0; i < props.length; i++) { var descriptor = props[i]; descriptor.enumerable = descriptor.enumerable || false; descriptor.configurable = true; if ('value' in descriptor) descriptor.writable = true; Object.defineProperty(target, descriptor.key, descriptor); } } return function (Constructor, protoProps, staticProps) { if (protoProps) defineProperties(Constructor.prototype, protoProps); if (staticProps) defineProperties(Constructor, staticProps); return Constructor; }; })();
var _get = function get(_x, _x2, _x3) { var _again = true; _function: while (_again) { var object = _x, property = _x2, receiver = _x3; desc = parent = getter = undefined; _again = false; var desc = Object.getOwnPropertyDescriptor(object, property); if (desc === undefined) { var parent = Object.getPrototypeOf(object); if (parent === null) { return undefined; } else { _x = parent; _x2 = property; _x3 = receiver; _again = true; continue _function; } } else if ('value' in desc) { return desc.value; } else { var getter = desc.get; if (getter === undefined) { return undefined; } return getter.call(receiver); } } };
function _classCallCheck(instance, Constructor) { if (!(instance instanceof Constructor)) { throw new TypeError('Cannot call a class as a function'); } }
function _inherits(subClass, superClass) { if (typeof superClass !== 'function' && superClass !== null) { throw new TypeError('Super expression must either be null or a function, not ' + typeof superClass); } subClass.prototype = Object.create(superClass && superClass.prototype, { constructor: { value: subClass, enumerable: false, writable: true, configurable: true } }); if (superClass) subClass.__proto__ = superClass; }
var React = require('react');
var DateTimeFormat = require('gregorian-calendar-format');
var rcUtil = require('rc-util');
var KeyCode = require('rc-util').KeyCode;
var domAlign = require('dom-align');
var orientMap = {
tl: ['top', 'left'],
tr: ['top', 'right'],
bl: ['bottom', 'left'],
br: ['bottom', 'right']
};
function getImmutableOrient(orient) {
if (orient) {
for (var i in orientMap) {
var original = orientMap[i];
if (original[0] === orient[0] && original[1] === orient[1]) {
return original;
}
}
}
}
function refFn(field, component) {
this[field] = component;
}
/**
* DatePicker = wrap input using Calendar
*/
var Picker = (function (_React$Component) {
function Picker(props) {
var _this = this;
_classCallCheck(this, Picker);
_get(Object.getPrototypeOf(Picker.prototype), 'constructor', this).call(this, props);
this.state = {
open: props.open,
value: props.value || props.defaultValue
};
var events = ['handleInputClick', 'handleCalendarBlur', 'handleTriggerClick', 'handleCalendarClear', 'handleCalendarKeyDown', 'handleKeyDown', 'handleCalendarSelect'];
// bind methods
events.forEach(function (m) {
_this[m] = _this[m].bind(_this);
});
this.saveCalendarRef = refFn.bind(this, 'calendarInstance');
this.saveInputRef = refFn.bind(this, 'inputInstance');
}
_inherits(Picker, _React$Component);
_createClass(Picker, [{
key: 'componentWillReceiveProps',
value: function componentWillReceiveProps(nextProps) {
if (nextProps.value) {
this.setState({
value: nextProps.value
});
}
}
}, {
key: 'open',
value: function open(callback) {
this.setState({
open: true
}, callback);
}
}, {
key: 'close',
value: function close(callback) {
this.setState({
open: false
}, callback);
}
}, {
key: 'handleInputClick',
value: function handleInputClick() {
this.toggle();
}
}, {
key: 'handleTriggerClick',
value: function handleTriggerClick() {
this.toggle();
}
}, {
key: 'toggle',
value: function toggle(callback) {
this.setState({
open: !this.state.open
}, callback);
}
}, {
key: 'handleKeyDown',
value: function handleKeyDown(e) {
// down
if (e.keyCode === KeyCode.DOWN) {
e.preventDefault();
this.open();
}
}
}, {
key: 'handleCalendarKeyDown',
value: function handleCalendarKeyDown(e) {
var _this2 = this;
if (e.keyCode === KeyCode.ESC) {
e.stopPropagation();
this.close(function () {
React.findDOMNode(_this2.inputInstance).focus();
});
}
}
}, {
key: 'handleCalendarSelect',
value: function handleCalendarSelect(value) {
var _this3 = this;
this.props.calendar.props.onSelect(value);
var currentValue = this.state.value;
if (this.props.calendar.props.showTime) {
this.setState({
value: value
});
} else {
this.setState({
value: value,
open: false
}, function () {
React.findDOMNode(_this3.inputInstance).focus();
});
}
if (!currentValue || currentValue.getTime() !== value.getTime()) {
this.props.onChange(value);
}
}
}, {
key: 'handleCalendarBlur',
value: function handleCalendarBlur() {
// if invisible, will not trigger blur
this.setState({
open: false
});
}
}, {
key: 'handleCalendarClear',
value: function handleCalendarClear() {
var _this4 = this;
this.props.calendar.props.onClear();
this.setState({
open: false,
value: null
}, function () {
React.findDOMNode(_this4.inputInstance).focus();
});
if (this.state.value !== null) {
this.props.onChange(null);
}
}
}, {
key: 'componentDidMount',
value: function componentDidMount() {
this.componentDidUpdate();
}
}, {
key: 'componentDidUpdate',
value: function componentDidUpdate() {
if (this.state.open && !this._lastOpen) {
var orient = this._cacheCalendar.props.orient;
var points = ['tl', 'bl'];
var offset = [0, 5];
if (orient.indexOf('top') !== -1 && orient.indexOf('left') !== -1) {
points = ['tl', 'bl'];
} else if (orient.indexOf('top') !== -1 && orient.indexOf('right') !== -1) {
points = ['tr', 'br'];
} else if (orient.indexOf('bottom') !== -1 && orient.indexOf('left') !== -1) {
points = ['bl', 'tl'];
offset = [0, -5];
} else if (orient.indexOf('bottom') !== -1 && orient.indexOf('right') !== -1) {
points = ['br', 'tr'];
offset = [0, -5];
}
var align = domAlign(React.findDOMNode(this.calendarInstance), React.findDOMNode(this.inputInstance), {
points: points,
offset: offset,
overflow: {
adjustX: 1,
adjustY: 1
}
});
points = align.points;
var newOrient = orientMap[points[0]];
this.calendarInstance.setState({
orient: newOrient
});
React.findDOMNode(this.calendarInstance).focus();
}
this._lastOpen = this.state.open;
}
}, {
key: 'render',
value: function render() {
var props = this.props;
// var input = React.Children.only(props.children); bug 0.13.0
/*
children: Object
.0: (...)
get .0: function () {
set .0: function (value) {
_reactDidWarn: false
_reactFragment: Object
__proto__: Object
*/
var input = props.children;
if (!React.isValidElement(input)) {
var children = input;
React.Children.forEach(children, function (m) {
input = m;
});
}
var state = this.state;
var value = state.value;
var calendar = this._cacheCalendar;
if (state.open) {
var calendarInstance = this.calendarInstance;
var calendarProp = props.calendar;
this._cacheCalendar = calendar = React.cloneElement(calendarProp, {
ref: rcUtil.createChainedFunction(calendarProp.props.ref, this.saveCalendarRef),
value: value,
// focused: true,
orient: calendarInstance && calendarInstance.state.orient || getImmutableOrient(calendarProp.props.orient) || orientMap.tl,
onBlur: this.handleCalendarBlur,
onKeyDown: this.handleCalendarKeyDown,
onSelect: this.handleCalendarSelect,
onClear: this.handleCalendarClear
});
}
var inputValue = '';
if (value) {
inputValue = props.formatter.format(value);
}
input = React.cloneElement(input, {
ref: rcUtil.createChainedFunction(input.props.ref, this.saveInputRef),
readOnly: true,
onClick: this.handleInputClick,
value: inputValue,
onKeyDown: this.handleKeyDown
});
var classes = [props.prefixCls];
if (state.open) {
classes.push(props.prefixCls + '-open');
}
var trigger = props.trigger;
if (trigger) {
trigger = React.cloneElement(trigger, {
onClick: this.handleTriggerClick,
unselectable: true,
onMouseDown: prevent
});
}
return React.createElement(
'span',
{ className: classes.join(' ') },
[input, calendar, trigger]
);
}
}]);
return Picker;
})(React.Component);
function prevent(e) {
e.preventDefault();
}
Picker.propTypes = {
onChange: React.PropTypes.func
};
Picker.defaultProps = {
prefixCls: 'rc-calendar-picker',
onChange: function onChange() {},
formatter: new DateTimeFormat('yyyy-MM-dd')
};
module.exports = Picker;
'use strict';
var _extends = Object.assign || function (target) { for (var i = 1; i < arguments.length; i++) { var source = arguments[i]; for (var key in source) { if (Object.prototype.hasOwnProperty.call(source, key)) { target[key] = source[key]; } } } return target; };
var _createClass = (function () { function defineProperties(target, props) { for (var i = 0; i < props.length; i++) { var descriptor = props[i]; descriptor.enumerable = descriptor.enumerable || false; descriptor.configurable = true; if ('value' in descriptor) descriptor.writable = true; Object.defineProperty(target, descriptor.key, descriptor); } } return function (Constructor, protoProps, staticProps) { if (protoProps) defineProperties(Constructor.prototype, protoProps); if (staticProps) defineProperties(Constructor, staticProps); return Constructor; }; })();
var _get = function get(_x, _x2, _x3) { var _again = true; _function: while (_again) { var object = _x, property = _x2, receiver = _x3; desc = parent = getter = undefined; _again = false; var desc = Object.getOwnPropertyDescriptor(object, property); if (desc === undefined) { var parent = Object.getPrototypeOf(object); if (parent === null) { return undefined; } else { _x = parent; _x2 = property; _x3 = receiver; _again = true; continue _function; } } else if ('value' in desc) { return desc.value; } else { var getter = desc.get; if (getter === undefined) { return undefined; } return getter.call(receiver); } } };
function _classCallCheck(instance, Constructor) { if (!(instance instanceof Constructor)) { throw new TypeError('Cannot call a class as a function'); } }
function _inherits(subClass, superClass) { if (typeof superClass !== 'function' && superClass !== null) { throw new TypeError('Super expression must either be null or a function, not ' + typeof superClass); } subClass.prototype = Object.create(superClass && superClass.prototype, { constructor: { value: subClass, enumerable: false, writable: true, configurable: true } }); if (superClass) subClass.__proto__ = superClass; }
var React = require('react');
var rcUtil = require('rc-util');
var KeyCode = rcUtil.KeyCode;
var TimePanel = require('./TimePanel');
var setHourOfDay = 'setHourOfDay';
var setMinutes = 'setMinutes';
var setSeconds = 'setSeconds';
function padding(number) {
if (number < 10) {
number = '0' + number;
}
return number;
}
function loop(value, min, max) {
if (value === min - 1) {
value = max;
} else if (value === max + 1) {
value = min;
}
return value;
}
function keyDownWrap(method, min, max) {
return function (e) {
var value = e.target.value;
var number = parseInt(value, 10);
var keyCode = e.keyCode;
var handled;
if (keyCode === KeyCode.DOWN) {
number++;
e.stopPropagation();
e.preventDefault();
handled = 1;
} else if (keyCode === KeyCode.UP) {
number--;
e.stopPropagation();
e.preventDefault();
handled = 1;
}
if (handled) {
number = loop(number, min, max);
var time = this.props.value.clone();
time[method](number);
this.props.onChange(time, e);
}
};
}
var Time = (function (_React$Component) {
function Time(props) {
var _this = this;
_classCallCheck(this, Time);
_get(Object.getPrototypeOf(Time.prototype), 'constructor', this).call(this, props);
this.state = {
showHourPanel: 0,
showMinutePanel: 0,
showSecondPanel: 0
};
var events = ['onHourKeyDown', 'onMinuteKeyDown', 'onSecondKeyDown', 'onHourClick', 'onMinuteClick', 'onSecondClick', 'onSelectPanel'];
events.forEach(function (m) {
_this[m] = _this[m].bind(_this);
});
}
_inherits(Time, _React$Component);
_createClass(Time, [{
key: 'onSelectPanel',
value: function onSelectPanel(value, setter) {
var _this2 = this;
this.setState({
showHourPanel: 0,
showMinutePanel: 0,
showSecondPanel: 0
}, function () {
// ie9 has broken focus
React.findDOMNode(_this2.refs[setter]).focus();
});
this.props.onChange(value);
}
}, {
key: 'onHourClick',
value: function onHourClick() {
this.setState({
showHourPanel: 1,
showMinutePanel: 0,
showSecondPanel: 0
});
}
}, {
key: 'onMinuteClick',
value: function onMinuteClick() {
this.setState({
showHourPanel: 0,
showMinutePanel: 1,
showSecondPanel: 0
});
}
}, {
key: 'onSecondClick',
value: function onSecondClick() {
this.setState({
showHourPanel: 0,
showMinutePanel: 0,
showSecondPanel: 1
});
}
}, {
key: 'shouldComponentUpdate',
value: function shouldComponentUpdate() {
return rcUtil.PureRenderMixin.shouldComponentUpdate.apply(this, arguments);
}
}, {
key: 'render',
value: function render() {
var state = this.state;
var props = this.props;
var prefixClsFn = props.prefixClsFn;
var value = props.value;
var locale = props.locale;
var hour = value.getHourOfDay();
var minute = value.getMinutes();
var second = value.getSeconds();
var panel;
var commonProps = {
value: value,
onSelect: this.onSelectPanel,
rootPrefixCls: props.rootPrefixCls
};
if (state.showHourPanel) {
panel = React.createElement(TimePanel, _extends({ rowCount: 6, colCount: 4, getter: 'getHourOfDay', setter: setHourOfDay,
title: locale.hourPanelTitle
}, commonProps));
} else if (state.showMinutePanel) {
panel = React.createElement(TimePanel, _extends({ rowCount: 6, colCount: 10, getter: 'getMinutes', setter: setMinutes,
title: locale.minutePanelTitle
}, commonProps));
} else if (state.showSecondPanel) {
panel = React.createElement(TimePanel, _extends({ rowCount: 6, colCount: 10, getter: 'getSeconds', setter: setSeconds,
title: locale.secondPanelTitle
}, commonProps));
}
return React.createElement(
'div',
null,
React.createElement('input', { className: prefixClsFn('time-input'), title: locale.hourInput,
ref: setHourOfDay,
readOnly: true, value: padding(hour),
onClick: this.onHourClick,
onKeyDown: this.onHourKeyDown }),
React.createElement(
'span',
null,
' : '
),
React.createElement('input', { className: prefixClsFn('time-input'), title: locale.minuteInput,
ref: setMinutes,
readOnly: true, value: padding(minute),
onClick: this.onMinuteClick,
onKeyDown: this.onMinuteKeyDown }),
React.createElement(
'span',
null,
' : '
),
React.createElement('input', { className: prefixClsFn('time-input'), title: locale.secondInput,
ref: setSeconds,
readOnly: true, value: padding(second),
onClick: this.onSecondClick,
onKeyDown: this.onSecondKeyDown }),
panel
);
}
}]);
return Time;
})(React.Component);
Time.prototype.onHourKeyDown = keyDownWrap('setHourOfDay', 0, 23);
Time.prototype.onMinuteKeyDown = keyDownWrap('setMinutes', 0, 59);
Time.prototype.onSecondKeyDown = keyDownWrap('setSeconds', 0, 59);
module.exports = Time;
'use strict';
var _createClass = (function () { function defineProperties(target, props) { for (var i = 0; i < props.length; i++) { var descriptor = props[i]; descriptor.enumerable = descriptor.enumerable || false; descriptor.configurable = true; if ('value' in descriptor) descriptor.writable = true; Object.defineProperty(target, descriptor.key, descriptor); } } return function (Constructor, protoProps, staticProps) { if (protoProps) defineProperties(Constructor.prototype, protoProps); if (staticProps) defineProperties(Constructor, staticProps); return Constructor; }; })();
var _get = function get(_x, _x2, _x3) { var _again = true; _function: while (_again) { var object = _x, property = _x2, receiver = _x3; desc = parent = getter = undefined; _again = false; var desc = Object.getOwnPropertyDescriptor(object, property); if (desc === undefined) { var parent = Object.getPrototypeOf(object); if (parent === null) { return undefined; } else { _x = parent; _x2 = property; _x3 = receiver; _again = true; continue _function; } } else if ('value' in desc) { return desc.value; } else { var getter = desc.get; if (getter === undefined) { return undefined; } return getter.call(receiver); } } };
function _classCallCheck(instance, Constructor) { if (!(instance instanceof Constructor)) { throw new TypeError('Cannot call a class as a function'); } }
function _inherits(subClass, superClass) { if (typeof superClass !== 'function' && superClass !== null) { throw new TypeError('Super expression must either be null or a function, not ' + typeof superClass); } subClass.prototype = Object.create(superClass && superClass.prototype, { constructor: { value: subClass, enumerable: false, writable: true, configurable: true } }); if (superClass) subClass.__proto__ = superClass; }
var React = require('react');
var cx = require('rc-util').classSet;
function choose(hour, e) {
var next = this.state.value.clone();
var method = this.props.setter;
next[method](hour);
this.props.onSelect(next, method);
e.preventDefault();
}
var TimePanel = (function (_React$Component) {
function TimePanel(props) {
_classCallCheck(this, TimePanel);
_get(Object.getPrototypeOf(TimePanel.prototype), 'constructor', this).call(this, props);
this.state = {
value: props.value,
prefixCls: props.rootPrefixCls + '-time-panel'
};
this.prefixClsFn = require('./prefixClsFn').bind(this);
}
_inherits(TimePanel, _React$Component);
_createClass(TimePanel, [{
key: 'render',
value: function render() {
var _this = this;
var value = this.state.value;
var props = this.props;
var method = props.getter;
var currentHour = value[method]();
var data = [];
var prefixClsFn = this.prefixClsFn;
var ROW = props.rowCount;
var COL = props.colCount;
for (var i = 0; i < ROW; i++) {
data[i] = [];
for (var j = 0; j < COL; j++) {
data[i][j] = i * COL + j;
}
}
var hoursEls = data.map(function (row, index) {
var tds = row.map(function (d) {
var classNameMap = {};
classNameMap[prefixClsFn('cell')] = 1;
classNameMap[prefixClsFn('selected-cell')] = d === currentHour;
return React.createElement(
'td',
{
key: d,
onClick: choose.bind(_this, d),
role: 'gridcell',
className: cx(classNameMap) },
React.createElement(
'a',
{
className: prefixClsFn('time') },
d
)
);
});
return React.createElement(
'tr',
{ key: index, role: 'row' },
tds
);
});
return React.createElement(
'div',
{ className: this.state.prefixCls },
React.createElement(
'div',
{ className: prefixClsFn('header') },
React.createElement(
'div',
{ className: prefixClsFn('title') },
props.title
)
),
React.createElement(
'div',
{ className: prefixClsFn('body') },
React.createElement(
'table',
{ className: prefixClsFn('table'), cellSpacing: '0', role: 'grid' },
React.createElement(
'tbody',
{ className: prefixClsFn('tbody') },
hoursEls
)
)
)
);
}
}]);
return TimePanel;
})(React.Component);
TimePanel.defaultProps = {
onSelect: function onSelect() {}
};
module.exports = TimePanel;
'use strict';
var _createClass = (function () { function defineProperties(target, props) { for (var i = 0; i < props.length; i++) { var descriptor = props[i]; descriptor.enumerable = descriptor.enumerable || false; descriptor.configurable = true; if ('value' in descriptor) descriptor.writable = true; Object.defineProperty(target, descriptor.key, descriptor); } } return function (Constructor, protoProps, staticProps) { if (protoProps) defineProperties(Constructor.prototype, protoProps); if (staticProps) defineProperties(Constructor, staticProps); return Constructor; }; })();
var _get = function get(_x, _x2, _x3) { var _again = true; _function: while (_again) { var object = _x, property = _x2, receiver = _x3; desc = parent = getter = undefined; _again = false; var desc = Object.getOwnPropertyDescriptor(object, property); if (desc === undefined) { var parent = Object.getPrototypeOf(object); if (parent === null) { return undefined; } else { _x = parent; _x2 = property; _x3 = receiver; _again = true; continue _function; } } else if ('value' in desc) { return desc.value; } else { var getter = desc.get; if (getter === undefined) { return undefined; } return getter.call(receiver); } } };
function _classCallCheck(instance, Constructor) { if (!(instance instanceof Constructor)) { throw new TypeError('Cannot call a class as a function'); } }
function _inherits(subClass, superClass) { if (typeof superClass !== 'function' && superClass !== null) { throw new TypeError('Super expression must either be null or a function, not ' + typeof superClass); } subClass.prototype = Object.create(superClass && superClass.prototype, { constructor: { value: subClass, enumerable: false, writable: true, configurable: true } }); if (superClass) subClass.__proto__ = superClass; }
var React = require('react');
var DateTimeFormat = require('gregorian-calendar-format');
var ROW = 3;
var COL = 4;
var cx = require('rc-util').classSet;
var DecadePanel = require('./DecadePanel');
function goYear(direction) {
var next = this.state.value.clone();
next.addYear(direction);
this.setState({ value: next });
}
function chooseYear(year) {
var next = this.state.value.clone();
next.setYear(year);
this.props.onSelect(next);
}
var YearPanel = (function (_React$Component) {
function YearPanel(props) {
var _this = this;
_classCallCheck(this, YearPanel);
_get(Object.getPrototypeOf(YearPanel.prototype), 'constructor', this).call(this, props);
this.prefixClsFn = require('./prefixClsFn').bind(this);
this.state = {
value: props.value,
prefixCls: props.rootPrefixCls + '-year-panel'
};
this.nextDecade = goYear.bind(this, 10);
this.previousDecade = goYear.bind(this, -10);
['showDecadePanel', 'onDecadePanelSelect'].forEach(function (m) {
_this[m] = _this[m].bind(_this);
});
}
_inherits(YearPanel, _React$Component);
_createClass(YearPanel, [{
key: 'showDecadePanel',
value: function showDecadePanel() {
this.setState({
showDecadePanel: 1
});
}
}, {
key: 'onDecadePanelSelect',
value: function onDecadePanelSelect(current) {
this.setState({
value: current,
showDecadePanel: 0
});
}
}, {
key: 'getYears',
value: function getYears() {
var value = this.state.value;
var currentYear = value.getYear();
var startYear = parseInt(currentYear / 10, 10) * 10;
var preYear = startYear - 1;
var current = value.clone();
var locale = this.props.locale;
var yearFormat = locale.yearFormat;
var dateFormatter = new DateTimeFormat(yearFormat);
var years = [];
var index = 0;
for (var i = 0; i < ROW; i++) {
years[i] = [];
for (var j = 0; j < COL; j++) {
current.setYear(preYear + index);
years[i][j] = {
content: preYear + index,
title: dateFormatter.format(current)
};
index++;
}
}
return years;
}
}, {
key: 'render',
value: function render() {
var _this2 = this;
var props = this.props;
var value = this.state.value;
var locale = props.locale;
var years = this.getYears();
var currentYear = value.getYear();
var startYear = parseInt(currentYear / 10, 10) * 10;
var endYear = startYear + 9;
var prefixClsFn = this.prefixClsFn;
var yeasEls = years.map(function (row, index) {
var tds = row.map(function (y) {
var classNameMap = {};
classNameMap[prefixClsFn('cell')] = 1;
classNameMap[prefixClsFn('selected-cell')] = y.content === currentYear;
classNameMap[prefixClsFn('last-decade-cell')] = y.content < startYear;
classNameMap[prefixClsFn('next-decade-cell')] = y.content > endYear;
return React.createElement(
'td',
{ role: 'gridcell',
title: y.title,
key: y.content,
onClick: chooseYear.bind(_this2, y.content),
className: cx(classNameMap)
},
React.createElement(
'a',
{
className: prefixClsFn('year') },
y.content
)
);
});
return React.createElement(
'tr',
{ key: index, role: 'row' },
tds
);
});
var decadePanel;
if (this.state.showDecadePanel) {
decadePanel = React.createElement(DecadePanel, { locale: locale, value: value, rootPrefixCls: props.rootPrefixCls, onSelect: this.onDecadePanelSelect });
}
return React.createElement(
'div',
{ className: this.state.prefixCls },
React.createElement(
'div',
null,
React.createElement(
'div',
{ className: prefixClsFn('header') },
React.createElement(
'a',
{ className: prefixClsFn('prev-decade-btn'),
role: 'button',
onClick: this.previousDecade,
title: locale.previousDecade },
'«'
),
React.createElement(
'a',
{ className: prefixClsFn('decade-select'),
role: 'button',
onClick: this.showDecadePanel,
title: locale.decadeSelect },
React.createElement(
'span',
{ className: prefixClsFn('decade-select-content') },
startYear,
'-',
endYear
),
React.createElement(
'span',
{ className: prefixClsFn('decade-select-arrow') },
'x'
)
),
React.createElement(
'a',
{ className: prefixClsFn('next-decade-btn'),
role: 'button',
onClick: this.nextDecade,
title: locale.nextDecade },
'»'
)
),
React.createElement(
'div',
{ className: prefixClsFn('body') },
React.createElement(
'table',
{ className: prefixClsFn('table'), cellSpacing: '0', role: 'grid' },
React.createElement(
'tbody',
{ className: prefixClsFn('tbody') },
yeasEls
)
)
)
),
decadePanel
);
}
}]);
return YearPanel;
})(React.Component);
YearPanel.defaultProps = {
onSelect: function onSelect() {}
};
module.exports = YearPanel;
'use strict';
var React = require('react');
var DATE_ROW_COUNT = 6;
var DATE_COL_COUNT = 7;
var DateTimeFormat = require('gregorian-calendar-format');
var GregorianCalendar = require('gregorian-calendar');
var rcUtil = require('rc-util');
var KeyCode = rcUtil.KeyCode;
var MonthPanel = require('./MonthPanel');
var Time = require('./Time');
function noop() {
}
function getIdFromDate(d) {
return 'rc-calendar-' + d.getYear() +
'-' + d.getMonth() + '-' +
d.getDayOfMonth();
}
function goStartMonth() {
var next = this.state.value.clone();
next.setDayOfMonth(1);
this.setState({value: next});
}
function goEndMonth() {
var next = this.state.value.clone();
next.setDayOfMonth(next.getActualMaximum(GregorianCalendar.MONTH));
this.setState({value: next});
}
function goMonth(direction) {
var next = this.state.value.clone();
next.addMonth(direction);
this.setState({value: next});
}
function goYear(direction) {
var next = this.state.value.clone();
next.addYear(direction);
this.setState({value: next});
}
function goWeek(direction) {
var next = this.state.value.clone();
next.addWeekOfYear(direction);
this.setState({value: next});
}
function goDay(direction) {
var next = this.state.value.clone();
next.addDayOfMonth(direction);
this.setState({value: next});
}
function isSameDay(one, two) {
return one.getYear() === two.getYear() &&
one.getMonth() === two.getMonth() &&
one.getDayOfMonth() === two.getDayOfMonth();
}
function beforeCurrentMonthYear(current, today) {
if (current.getYear() < today.getYear()) {
return 1;
}
return current.getYear() === today.getYear() &&
current.getMonth() < today.getMonth();
}
function afterCurrentMonthYear(current, today) {
if (current.getYear() > today.getYear()) {
return 1;
}
return current.getYear() === today.getYear() &&
current.getMonth() > today.getMonth();
}
function onFocus() {
if (this._blurTimer) {
clearTimeout(this._blurTimer);
this._blurTimer = null;
} else {
this.props.onFocus();
}
}
function onBlur() {
if (this._blurTimer) {
clearTimeout(this._blurTimer);
}
this._blurTimer = setTimeout(()=> {
this.props.onBlur();
}, 100);
}
function chooseToday() {
var today = this.state.value.clone();
today.setTime(Date.now());
this.handleSelect(today);
}
function handleDayClick(current) {
this.handleSelect(current);
}
function handleSelect(current, keyDownEvent) {
var props = this.props;
this.setState({
value: current
});
if (!keyDownEvent) {
props.onSelect(current);
}
}
function clear() {
this.props.onClear();
}
function onMonthPanelSelect(current) {
this.setState({
value: current,
showMonthPanel: 0
});
}
function handleKeyDown(e) {
var keyCode = e.keyCode;
// mac
var ctrlKey = e.ctrlKey || e.metaKey;
switch (keyCode) {
case KeyCode.DOWN:
goWeek.call(this, 1);
e.preventDefault();
return true;
case KeyCode.UP:
goWeek.call(this, -1);
e.preventDefault();
return true;
case KeyCode.LEFT:
if (ctrlKey) {
this.previousYear();
} else {
goDay.call(this, -1);
}
e.preventDefault();
return true;
case KeyCode.RIGHT:
if (ctrlKey) {
this.nextYear();
} else {
goDay.call(this, 1);
}
e.preventDefault();
return true;
case KeyCode.HOME:
goStartMonth.call(this);
e.preventDefault();
return true;
case KeyCode.END:
goEndMonth.call(this);
e.preventDefault();
return true;
case KeyCode.PAGE_DOWN:
this.nextMonth();
e.preventDefault();
return true;
case KeyCode.PAGE_UP:
this.previousMonth();
e.preventDefault();
return true;
case KeyCode.ENTER:
this.props.onSelect(this.state.value);
e.preventDefault();
return true;
default:
this.props.onKeyDown(e);
return true;
}
}
function showMonthPanel() {
this.setState({
showMonthPanel: 1
});
}
class Calendar extends React.Component {
constructor(props) {
super(props);
var value = props.value || props.defaultValue;
if (!value) {
value = new GregorianCalendar();
value.setTime(Date.now());
}
this.dateFormatter = new DateTimeFormat(props.locale.dateFormat);
this.state = {
orient: props.orient,
prefixCls: props.prefixCls || 'rc-calendar',
value: value
};
// bind methods
this.onBlur = onBlur.bind(this);
this.onFocus = onFocus.bind(this);
this.prefixClsFn = require('./prefixClsFn').bind(this);
this.nextMonth = goMonth.bind(this, 1);
this.previousMonth = goMonth.bind(this, -1);
this.nextYear = goYear.bind(this, 1);
this.previousYear = goYear.bind(this, -1);
this.chooseToday = chooseToday.bind(this);
this.clear = clear.bind(this);
this.handleSelect = handleSelect.bind(this);
this.onMonthPanelSelect = onMonthPanelSelect.bind(this);
this.handleKeyDown = handleKeyDown.bind(this);
this.showMonthPanel = showMonthPanel.bind(this);
}
shouldComponentUpdate() {
return rcUtil.PureRenderMixin.shouldComponentUpdate.apply(this, arguments);
}
componentWillReceiveProps(nextProps) {
var value = nextProps.value;
if (value !== undefined) {
if (!value) {
value = this.state.value.clone();
value.setTime(Date.now());
}
this.setState({
value: value
});
}
if (nextProps.orient) {
this.setState({
orient: nextProps.orient
});
}
if (nextProps.locale !== this.props.locale) {
this.dateFormatter = new DateTimeFormat(nextProps.locale.dateFormat);
}
}
renderDates() {
var props = this.props;
var i, j, current;
var dateTable = [];
var showWeekNumber = props.showWeekNumber;
var value = this.state.value;
var today = value.clone();
var prefixClsFn = this.prefixClsFn;
var cellClass = prefixClsFn('cell');
var weekNumberCellClass = prefixClsFn('week-number-cell');
var dateClass = prefixClsFn('date');
var dateRender = props.dateRender;
var disabledDate = props.disabledDate;
var dateFormatter = this.dateFormatter;
var todayClass = prefixClsFn('today');
var selectedClass = prefixClsFn('selected-day');
var lastMonthDayClass = prefixClsFn('last-month-cell');
var nextMonthDayClass = prefixClsFn('next-month-btn-day');
var disabledClass = prefixClsFn('disabled-cell');
today.setTime(Date.now());
var month1 = value.clone();
month1.set(value.getYear(), value.getMonth(), 1);
var day = month1.getDayOfWeek();
var lastMonthDiffDay = (day + 7 - value.getFirstDayOfWeek()) % 7;
// calculate last month
var lastMonth1 = month1.clone();
lastMonth1.addDayOfMonth(0 - lastMonthDiffDay);
var passed = 0;
for (i = 0; i < DATE_ROW_COUNT; i++) {
for (j = 0; j < DATE_COL_COUNT; j++) {
current = lastMonth1;
if (passed) {
current = current.clone();
current.addDayOfMonth(passed);
}
dateTable.push(current);
passed++;
}
}
var tableHtml = [];
passed = 0;
for (i = 0; i < DATE_ROW_COUNT; i++) {
var weekNumberCell;
var dateCells = [];
if (showWeekNumber) {
weekNumberCell = (
<td key={dateTable[passed].getWeekOfYear()} role="gridcell" className = {weekNumberCellClass}>{dateTable[passed].getWeekOfYear()}</td>
);
}
for (j = 0; j < DATE_COL_COUNT; j++) {
current = dateTable[passed];
var cls = cellClass;
var disabled = false;
var selected = false;
if (isSameDay(current, today)) {
cls += ' ' + todayClass;
}
if (isSameDay(current, value)) {
cls += ' ' + selectedClass;
selected = true;
}
if (beforeCurrentMonthYear(current, value)) {
cls += ' ' + lastMonthDayClass;
}
if (afterCurrentMonthYear(current, value)) {
cls += ' ' + nextMonthDayClass;
}
if (disabledDate && disabledDate(current, value)) {
cls += ' ' + disabledClass;
disabled = true;
}
var dateHtml;
if (!(dateRender && (dateHtml = dateRender(current, value)))) {
dateHtml = (
<span
key={getIdFromDate(current)}
className = {dateClass}
aria-selected={selected}
aria-disabled={disabled}>
{current.getDayOfMonth()}
</span>);
}
dateCells.push(
<td key={passed} onClick={disabled ? noop : handleDayClick.bind(this, current)} role="gridcell" title={dateFormatter.format(current)} className = {cls}>
{dateHtml}
</td>);
passed++;
}
tableHtml.push(
<tr
key={i}
role="row">
{weekNumberCell}
{dateCells}
</tr>);
}
this.dateTable = dateTable;
return tableHtml;
}
getTodayTime() {
var value = this.state.value;
var today = value.clone();
today.setTime(Date.now());
return this.dateFormatter.format(today);
}
getMonthYear() {
var locale = this.props.locale;
var value = this.state.value;
return new DateTimeFormat(locale.monthYearFormat).format(value);
}
render() {
// console.log('re render');
var showWeekNumberEl;
var props = this.props;
var locale = props.locale;
var state = this.state;
var value = state.value;
var veryShortWeekdays = [];
var weekDays = [];
var firstDayOfWeek = value.getFirstDayOfWeek();
var prefixCls = state.prefixCls;
var prefixClsFn = this.prefixClsFn;
for (var i = 0; i < DATE_COL_COUNT; i++) {
var index = (firstDayOfWeek + i) % DATE_COL_COUNT;
veryShortWeekdays[i] = locale.format.veryShortWeekdays[index];
weekDays[i] = locale.format.weekdays[index];
}
if (props.showWeekNumber) {
showWeekNumberEl = (
<th role="columnheader" className = {prefixClsFn('column-header', 'week-number-header')}>
<span className ={prefixClsFn('column-header-inner')}>x</span>
</th>);
}
var weekDaysEls = weekDays.map((day, xindex)=> {
return (
<th key={xindex} role="columnheader" title={day} className ={prefixClsFn('column-header')}>
<span className = {prefixClsFn('column-header-inner')}>
{veryShortWeekdays[xindex]}
</span>
</th>);
});
var footerEl;
if (props.showToday || props.showTime) {
var todayEl;
if (props.showToday) {
todayEl = (<a className = {prefixClsFn('today-btn')}
role="button"
onClick={this.chooseToday}
title={this.getTodayTime()}>{locale.today}</a>);
}
var clearEl;
if (props.showClear) {
clearEl = (<a className = {prefixClsFn('clear-btn')}
role="button"
onClick={this.clear}>{locale.clear}</a>);
}
var footerBtn;
if (todayEl || clearEl) {
footerBtn = <div className={prefixClsFn('footer-btn')}>{todayEl} {clearEl}</div>;
}
var timeEl;
if (props.showTime) {
timeEl = (<Time value={value} rootPrefixCls={prefixCls} prefixClsFn={prefixClsFn} locale={locale} onChange={this.handleSelect}/>);
}
footerEl = (
<div className = {prefixClsFn('footer')}>
{timeEl}
{footerBtn}
</div>);
}
var monthPanel;
if (state.showMonthPanel) {
monthPanel = <MonthPanel locale={locale} value={value} rootPrefixCls={state.prefixCls} onSelect={this.onMonthPanelSelect}/>;
}
var className = prefixCls;
if (props.className) {
className += ' ' + props.className;
}
var orient = state.orient;
if (orient) {
orient.forEach(o => {
className += ' ' + prefixClsFn('orient-' + o);
});
}
return (
<div className = {className} tabIndex="0" onFocus={this.onFocus} onBlur={this.onBlur} onKeyDown={this.handleKeyDown}>
<div style={{outline: 'none'}}>
<div className = {prefixClsFn('header')}>
<a className ={prefixClsFn('prev-year-btn')}
role="button"
onClick={this.previousYear}
title={locale.previousYear}>
«
</a>
<a className = {prefixClsFn('prev-month-btn')}
role="button"
onClick={this.previousMonth}
title={locale.previousMonth}>
</a>
<a className = {prefixClsFn('month-select')}
role="button"
onClick={this.showMonthPanel}
title={locale.monthSelect}>
<span className = {prefixClsFn('month-select-content')}>{this.getMonthYear()}</span>
<span className = {prefixClsFn('month-select-arrow')}>x</span>
</a>
<a className = {prefixClsFn('next-month-btn')}
onClick={this.nextMonth}
title={locale.nextMonth}>
</a>
<a className = {prefixClsFn('next-year-btn')}
onClick={this.nextYear}
title={locale.nextYear}>
»
</a>
</div>
<div className = {prefixClsFn('calendar-body')}>
<table className = {prefixClsFn('table')} cellSpacing="0" role="grid">
<thead>
<tr role="row">
{showWeekNumberEl}
{weekDaysEls}
</tr>
</thead>
<tbody className = {prefixClsFn('tbody')}>
{this.renderDates()}
</tbody>
</table>
</div>
{footerEl}
</div>
{monthPanel}
</div>);
}
}
Calendar.propTypes = {
value: React.PropTypes.object,
defaultValue: React.PropTypes.object,
className: React.PropTypes.string,
orient: React.PropTypes.arrayOf(React.PropTypes.oneOf(['left', 'top', 'right', 'bottom'])),
locale: React.PropTypes.object,
showWeekNumber: React.PropTypes.bool,
showToday: React.PropTypes.bool,
showTime: React.PropTypes.bool,
onSelect: React.PropTypes.func,
onBlur: React.PropTypes.func
};
Calendar.defaultProps = {
locale: require('./locale/en-us'),
onKeyDown: noop,
className: '',
showToday: true,
onSelect: noop,
onFocus: noop,
onBlur: noop,
onClear: noop
};
module.exports = Calendar;
'use strict';
var React = require('react');
var ROW = 4;
var COL = 3;
var cx = require('rc-util').classSet;
function goYear(direction) {
var next = this.state.value.clone();
next.addYear(direction);
this.setState({
value: next
});
}
function chooseDecade(year, e) {
var next = this.state.value.clone();
next.setYear(year);
this.props.onSelect(next);
e.preventDefault();
}
class DecadePanel extends React.Component {
constructor(props) {
super(props);
this.state = {
value: props.value,
prefixCls: props.rootPrefixCls + '-decade-panel'
};
// bind methods
this.prefixClsFn = require('./prefixClsFn').bind(this);
this.nextCentury = goYear.bind(this, 100);
this.previousCentury = goYear.bind(this, -100);
}
render() {
var value = this.state.value;
var locale = this.props.locale;
var currentYear = value.getYear();
var startYear = parseInt(currentYear / 100, 10) * 100;
var preYear = startYear - 10;
var endYear = startYear + 99;
var decades = [];
var index = 0;
var prefixClsFn = this.prefixClsFn;
for (var i = 0; i < ROW; i++) {
decades[i] = [];
for (var j = 0; j < COL; j++) {
decades[i][j] = {
startDecade: preYear + index * 10,
endDecade: preYear + index * 10 + 9
};
index++;
}
}
var decadesEls = decades.map((row, decadeIndex) => {
var tds = row.map(d => {
var startDecade = d.startDecade;
var endDecade = d.endDecade;
var classNameMap = {};
classNameMap[prefixClsFn('cell')] = 1;
classNameMap[prefixClsFn('selected-cell')] = startDecade <= currentYear && currentYear <= endDecade;
classNameMap[prefixClsFn('last-century-cell')] = startDecade < startYear;
classNameMap[prefixClsFn('next-century-cell')] = endDecade > endYear;
return (<td
key={startDecade}
onClick={chooseDecade.bind(this, startDecade)}
role="gridcell"
className = {cx(classNameMap)}
>
<a
className={prefixClsFn('decade')}>
{startDecade} - {endDecade}
</a>
</td>);
});
return (<tr key={decadeIndex} role="row">{tds}</tr>);
});
return (
<div className={this.state.prefixCls}>
<div className = {prefixClsFn('header')}>
<a className = {prefixClsFn('prev-century-btn')}
role="button"
onClick={this.previousCentury}
title={locale.previousCentury}>
«
</a>
<div className = {prefixClsFn('century')}>
{startYear}-{endYear}
</div>
<a className = {prefixClsFn('next-century-btn')}
role="button"
onClick={this.nextCentury}
title={locale.nextCentury}>
»
</a>
</div>
<div className = {prefixClsFn('body')}>
<table className = {prefixClsFn('table')} cellSpacing="0" role="grid">
<tbody className = {prefixClsFn('tbody')}>
{decadesEls}
</tbody>
</table>
</div>
</div>);
}
}
DecadePanel.defaultProps = {
onSelect() {
}
};
module.exports = DecadePanel;
module.exports = require('./Calendar');
module.exports.Picker = require('./Picker');
'use strict';
module.exports = ({
today: 'Today',
clear: 'Clear',
hourPanelTitle: 'Select hour',
minutePanelTitle: 'Select minute',
secondPanelTitle: 'Select second',
monthSelect: 'Choose a month',
yearSelect: 'Choose a year',
decadeSelect: 'Choose a decade',
yearFormat: 'yyyy',
dateFormat: 'M/d/yyyy',
monthYearFormat: 'MMMM yyyy',
previousMonth: 'Previous month (PageUp)',
nextMonth: 'Next month (PageDown)',
hourInput: 'Last hour(Up), Next hour(Down)',
minuteInput: 'Last minute(Up), Next minute(Down)',
secondInput: 'Last second(Up), Next second(Down)',
previousYear: 'Last year (Control + left)',
nextYear: 'Next year (Control + right)',
previousDecade: 'Last decade',
nextDecade: 'Next decade',
previousCentury: 'Last century',
nextCentury: 'Next century',
format: require('gregorian-calendar-format/lib/locale/en-us')
});
'use strict';
module.exports = ({
today: '今天',
clear: '清除',
previousMonth: '上个月 (翻页上键)',
nextMonth: '下个月 (翻页下键)',
monthSelect: '选择月份',
yearSelect: '选择年份',
decadeSelect: '选择年代',
hourInput: '上一小时(上方向键), 下一小时(下方向键)',
minuteInput: '上一分钟(上方向键), 下一分钟(下方向键)',
secondInput: '上一秒(上方向键), 下一小时(下方向键)',
hourPanelTitle: '选择小时',
minutePanelTitle: '选择分钟',
secondPanelTitle: '选择秒',
yearFormat: 'yyyy\'年\'',
monthYearFormat: 'yyyy\'年\'M\'月\'',
dateFormat: 'yyyy\'年\'M\'月\'d\'日\'',
previousYear: '上一年 (Control键加左方向键)',
nextYear: '下一年 (Control键加右方向键)',
previousDecade: '上一年代',
nextDecade: '下一年代',
previousCentury: '上一世纪',
nextCentury: '下一世纪',
format: require('gregorian-calendar-format/lib/locale/zh-cn')
});
'use strict';
var React = require('react');
var DateTimeFormat = require('gregorian-calendar-format');
var ROW = 3;
var COL = 4;
var cx = require('rc-util').classSet;
var YearPanel = require('./YearPanel');
function goYear(direction) {
var next = this.state.value.clone();
next.addYear(direction);
this.setState({
value: next
});
}
function showYearPanel() {
this.setState({
showYearPanel: 1
});
}
function chooseMonth(month) {
var next = this.state.value.clone();
next.setMonth(month);
this.props.onSelect(next);
}
function onYearPanelSelect(current) {
this.setState({
value: current,
showYearPanel: 0
});
}
class MonthPanel extends React.Component {
constructor(props) {
super(props);
this.state = {
value: this.props.value,
prefixCls: this.props.rootPrefixCls + '-month-panel'
};
// bind methods
this.nextYear = goYear.bind(this, 1);
this.previousYear = goYear.bind(this, -1);
this.showYearPanel = showYearPanel.bind(this);
this.onYearPanelSelect = onYearPanelSelect.bind(this);
this.prefixClsFn = require('./prefixClsFn').bind(this);
}
getMonths() {
var props = this.props;
var value = this.state.value;
var current = value.clone();
var locale = props.locale;
var monthYearFormat = locale.monthYearFormat;
var dateFormatter = new DateTimeFormat(monthYearFormat);
var months = [];
var shortMonths = locale.format.shortMonths;
var index = 0;
for (var i = 0; i < ROW; i++) {
months[i] = [];
for (var j = 0; j < COL; j++) {
current.setMonth(index);
months[i][j] = {
value: index,
content: shortMonths[index],
title: dateFormatter.format(current)
};
index++;
}
}
return months;
}
render() {
var props = this.props;
var value = this.state.value;
var locale = props.locale;
var months = this.getMonths();
var year = value.getYear();
var currentMonth = value.getMonth();
var prefixClsFn = this.prefixClsFn;
var monthsEls = months.map((month, index)=> {
var tds = month.map(m => {
var classNameMap = {};
classNameMap[prefixClsFn('cell')] = 1;
classNameMap[prefixClsFn('selected-cell')] = m.value === currentMonth;
return (
<td role="gridcell"
key={m.value}
onClick={chooseMonth.bind(this, m.value)}
title={m.title}
className = {cx(classNameMap)}>
<a
className = {prefixClsFn('month')}>
{m.content}
</a>
</td>);
});
return (<tr key={index} role="row">{tds}</tr>);
});
var yearPanel;
if (this.state.showYearPanel) {
yearPanel = <YearPanel locale={locale} value={value} rootPrefixCls={props.rootPrefixCls} onSelect={this.onYearPanelSelect}/>;
}
return (
<div className= {this.state.prefixCls}>
<div>
<div className = {prefixClsFn('header')}>
<a className = {prefixClsFn('prev-year-btn')}
role="button"
onClick={this.previousYear}
title={locale.previousYear}>
«
</a>
<a className = {prefixClsFn('year-select')}
role="button"
onClick={this.showYearPanel}
title={locale.yearSelect}>
<span className = {prefixClsFn('year-select-content')}>{year}</span>
<span className = {prefixClsFn('year-select-arrow')}>x</span>
</a>
<a className = {prefixClsFn('next-year-btn')}
role="button"
onClick={this.nextYear}
title={locale.nextYear}>
»
</a>
</div>
<div className = {prefixClsFn('body')}>
<table className = {prefixClsFn('table')} cellSpacing="0" role="grid">
<tbody className = {prefixClsFn('tbody')}>
{monthsEls}
</tbody>
</table>
</div>
</div>
{yearPanel}
</div>);
}
}
MonthPanel.defaultProps = {
onSelect() {
}
};
module.exports = MonthPanel;
'use strict';
var React = require('react');
var DateTimeFormat = require('gregorian-calendar-format');
var rcUtil = require('rc-util');
var KeyCode = require('rc-util').KeyCode;
var domAlign = require('dom-align');
var orientMap = {
tl: ['top', 'left'],
tr: ['top', 'right'],
bl: ['bottom', 'left'],
br: ['bottom', 'right']
};
function getImmutableOrient(orient) {
if (orient) {
for (var i in orientMap) {
var original = orientMap[i];
if (original[0] === orient[0] && original[1] === orient[1]) {
return original;
}
}
}
}
function refFn(field, component) {
this[field] = component;
}
/**
* DatePicker = wrap input using Calendar
*/
class Picker extends React.Component {
constructor(props) {
super(props);
this.state = {
open: props.open,
value: props.value || props.defaultValue
};
var events = [
'handleInputClick', 'handleCalendarBlur', 'handleTriggerClick',
'handleCalendarClear', 'handleCalendarKeyDown',
'handleKeyDown', 'handleCalendarSelect'
];
// bind methods
events.forEach(m => {
this[m] = this[m].bind(this);
});
this.saveCalendarRef = refFn.bind(this, 'calendarInstance');
this.saveInputRef = refFn.bind(this, 'inputInstance');
}
componentWillReceiveProps(nextProps) {
if (nextProps.value) {
this.setState({
value: nextProps.value
});
}
}
open(callback) {
this.setState({
open: true
}, callback);
}
close(callback) {
this.setState({
open: false
}, callback);
}
handleInputClick() {
this.toggle();
}
handleTriggerClick() {
this.toggle();
}
toggle(callback) {
this.setState({
open: !this.state.open
}, callback);
}
handleKeyDown(e) {
// down
if (e.keyCode === KeyCode.DOWN) {
e.preventDefault();
this.open();
}
}
handleCalendarKeyDown(e) {
if (e.keyCode === KeyCode.ESC) {
e.stopPropagation();
this.close(() => {
React.findDOMNode(this.inputInstance).focus();
});
}
}
handleCalendarSelect(value) {
this.props.calendar.props.onSelect(value);
var currentValue = this.state.value;
if (this.props.calendar.props.showTime) {
this.setState({
value: value
});
} else {
this.setState({
value: value,
open: false
}, () => {
React.findDOMNode(this.inputInstance).focus();
});
}
if (!currentValue || currentValue.getTime() !== value.getTime()) {
this.props.onChange(value);
}
}
handleCalendarBlur() {
// if invisible, will not trigger blur
this.setState({
open: false
});
}
handleCalendarClear() {
this.props.calendar.props.onClear();
this.setState({
open: false,
value: null
}, ()=> {
React.findDOMNode(this.inputInstance).focus();
});
if (this.state.value !== null) {
this.props.onChange(null);
}
}
componentDidMount() {
this.componentDidUpdate();
}
componentDidUpdate() {
if (this.state.open && !this._lastOpen) {
var orient = this._cacheCalendar.props.orient;
var points = ['tl', 'bl'];
var offset = [0, 5];
if (orient.indexOf('top') !== -1 && orient.indexOf('left') !== -1) {
points = ['tl', 'bl'];
} else if (orient.indexOf('top') !== -1 && orient.indexOf('right') !== -1) {
points = ['tr', 'br'];
} else if (orient.indexOf('bottom') !== -1 && orient.indexOf('left') !== -1) {
points = ['bl', 'tl'];
offset = [0, -5];
} else if (orient.indexOf('bottom') !== -1 && orient.indexOf('right') !== -1) {
points = ['br', 'tr'];
offset = [0, -5];
}
var align = domAlign(React.findDOMNode(this.calendarInstance), React.findDOMNode(this.inputInstance), {
points: points,
offset: offset,
overflow: {
adjustX: 1,
adjustY: 1
}
});
points = align.points;
var newOrient = orientMap[points[0]];
this.calendarInstance.setState({
orient: newOrient
});
React.findDOMNode(this.calendarInstance).focus();
}
this._lastOpen = this.state.open;
}
render() {
var props = this.props;
// var input = React.Children.only(props.children); bug 0.13.0
/*
children: Object
.0: (...)
get .0: function () {
set .0: function (value) {
_reactDidWarn: false
_reactFragment: Object
__proto__: Object
*/
var input = props.children;
if (!React.isValidElement(input)) {
var children = input;
React.Children.forEach(children, m => {
input = m;
});
}
var state = this.state;
var value = state.value;
var calendar = this._cacheCalendar;
if (state.open) {
var calendarInstance = this.calendarInstance;
var calendarProp = props.calendar;
this._cacheCalendar = calendar = React.cloneElement(calendarProp, {
ref: rcUtil.createChainedFunction(calendarProp.props.ref, this.saveCalendarRef),
value: value,
// focused: true,
orient: calendarInstance && calendarInstance.state.orient || getImmutableOrient(calendarProp.props.orient) || orientMap.tl,
onBlur: this.handleCalendarBlur,
onKeyDown: this.handleCalendarKeyDown,
onSelect: this.handleCalendarSelect,
onClear: this.handleCalendarClear
});
}
var inputValue = '';
if (value) {
inputValue = props.formatter.format(value);
}
input = React.cloneElement(input, {
ref: rcUtil.createChainedFunction(input.props.ref, this.saveInputRef),
readOnly: true,
onClick: this.handleInputClick,
value: inputValue,
onKeyDown: this.handleKeyDown
});
var classes = [props.prefixCls];
if (state.open) {
classes.push(props.prefixCls + '-open');
}
var trigger = props.trigger;
if (trigger) {
trigger = React.cloneElement(trigger, {
onClick: this.handleTriggerClick,
unselectable: true,
onMouseDown: prevent
});
}
return <span className={classes.join(' ')}>{[input, calendar, trigger]}</span>;
}
}
function prevent(e) {
e.preventDefault();
}
Picker.propTypes = {
onChange: React.PropTypes.func
};
Picker.defaultProps = {
prefixCls: 'rc-calendar-picker',
onChange() {
},
formatter: new DateTimeFormat('yyyy-MM-dd')
};
module.exports = Picker;
'use strict';
module.exports = function () {
var prefixCls = this.state.prefixCls;
var args = Array.prototype.slice.call(arguments, 0);
return args.map(s => {
return prefixCls + '-' + s;
}).join(' ');
};
'use strict';
var React = require('react');
var rcUtil = require('rc-util');
var KeyCode = rcUtil.KeyCode;
var TimePanel = require('./TimePanel');
var setHourOfDay = 'setHourOfDay';
var setMinutes = 'setMinutes';
var setSeconds = 'setSeconds';
function padding(number) {
if (number < 10) {
number = '0' + number;
}
return number;
}
function loop(value, min, max) {
if (value === min - 1) {
value = max;
} else if (value === max + 1) {
value = min;
}
return value;
}
function keyDownWrap(method, min, max) {
return function (e) {
var value = e.target.value;
var number = parseInt(value, 10);
var keyCode = e.keyCode;
var handled;
if (keyCode === KeyCode.DOWN) {
number++;
e.stopPropagation();
e.preventDefault();
handled = 1;
} else if (keyCode === KeyCode.UP) {
number--;
e.stopPropagation();
e.preventDefault();
handled = 1;
}
if (handled) {
number = loop(number, min, max);
var time = this.props.value.clone();
time[method](number);
this.props.onChange(time, e);
}
};
}
class Time extends React.Component {
constructor(props) {
super(props);
this.state = {
showHourPanel: 0,
showMinutePanel: 0,
showSecondPanel: 0
};
var events = [
'onHourKeyDown', 'onMinuteKeyDown', 'onSecondKeyDown', 'onHourClick', 'onMinuteClick', 'onSecondClick',
'onSelectPanel'
];
events.forEach(m => {
this[m] = this[m].bind(this);
});
}
onSelectPanel(value, setter) {
this.setState({
showHourPanel: 0,
showMinutePanel: 0,
showSecondPanel: 0
}, ()=> {
// ie9 has broken focus
React.findDOMNode(this.refs[setter]).focus();
});
this.props.onChange(value);
}
onHourClick() {
this.setState({
showHourPanel: 1,
showMinutePanel: 0,
showSecondPanel: 0
});
}
onMinuteClick() {
this.setState({
showHourPanel: 0,
showMinutePanel: 1,
showSecondPanel: 0
});
}
onSecondClick() {
this.setState({
showHourPanel: 0,
showMinutePanel: 0,
showSecondPanel: 1
});
}
shouldComponentUpdate() {
return rcUtil.PureRenderMixin.shouldComponentUpdate.apply(this, arguments);
}
render() {
var state = this.state;
var props = this.props;
var prefixClsFn = props.prefixClsFn;
var value = props.value;
var locale = props.locale;
var hour = value.getHourOfDay();
var minute = value.getMinutes();
var second = value.getSeconds();
var panel;
var commonProps = {
value: value,
onSelect: this.onSelectPanel,
rootPrefixCls: props.rootPrefixCls
};
if (state.showHourPanel) {
panel = <TimePanel rowCount={6} colCount={4} getter="getHourOfDay" setter={setHourOfDay}
title={locale.hourPanelTitle}
{...commonProps}/>;
} else if (state.showMinutePanel) {
panel = <TimePanel rowCount={6} colCount={10} getter="getMinutes" setter={setMinutes}
title={locale.minutePanelTitle}
{...commonProps}/>;
} else if (state.showSecondPanel) {
panel = <TimePanel rowCount={6} colCount={10} getter="getSeconds" setter={setSeconds}
title={locale.secondPanelTitle}
{...commonProps}/>;
}
return (<div>
<input className = {prefixClsFn('time-input')} title={locale.hourInput}
ref={setHourOfDay}
readOnly value={padding(hour)}
onClick={this.onHourClick}
onKeyDown={this.onHourKeyDown}/>
<span> : </span>
<input className = {prefixClsFn('time-input')} title={locale.minuteInput}
ref={setMinutes}
readOnly value={padding(minute)}
onClick={this.onMinuteClick}
onKeyDown = {this.onMinuteKeyDown}/>
<span> : </span>
<input className = {prefixClsFn('time-input')} title={locale.secondInput}
ref={setSeconds}
readOnly value={padding(second)}
onClick={this.onSecondClick}
onKeyDown = {this.onSecondKeyDown}/>
{panel}
</div>);
}
}
Time.prototype.onHourKeyDown = keyDownWrap('setHourOfDay', 0, 23);
Time.prototype.onMinuteKeyDown = keyDownWrap('setMinutes', 0, 59);
Time.prototype.onSecondKeyDown = keyDownWrap('setSeconds', 0, 59);
module.exports = Time;
'use strict';
var React = require('react');
var cx = require('rc-util').classSet;
function choose(hour, e) {
var next = this.state.value.clone();
var method = this.props.setter;
next[method](hour);
this.props.onSelect(next, method);
e.preventDefault();
}
class TimePanel extends React.Component {
constructor(props) {
super(props);
this.state = {
value: props.value,
prefixCls: props.rootPrefixCls + '-time-panel'
};
this.prefixClsFn = require('./prefixClsFn').bind(this);
}
render() {
var value = this.state.value;
var props = this.props;
var method = props.getter;
var currentHour = value[method]();
var data = [];
var prefixClsFn = this.prefixClsFn;
var ROW = props.rowCount;
var COL = props.colCount;
for (var i = 0; i < ROW; i++) {
data[i] = [];
for (var j = 0; j < COL; j++) {
data[i][j] = i * COL + j;
}
}
var hoursEls = data.map((row, index)=> {
var tds = row.map(d => {
var classNameMap = {};
classNameMap[prefixClsFn('cell')] = 1;
classNameMap[prefixClsFn('selected-cell')] = d === currentHour;
return (<td
key={d}
onClick={choose.bind(this, d)}
role="gridcell"
className = {cx(classNameMap)} >
<a
className={prefixClsFn('time')}>
{d}
</a>
</td>);
});
return (<tr key={index} role="row">{tds}</tr>);
});
return (
<div className={this.state.prefixCls}>
<div className = {prefixClsFn('header')}>
<div className = {prefixClsFn('title')}>
{props.title}
</div>
</div>
<div className = {prefixClsFn('body')}>
<table className = {prefixClsFn('table')} cellSpacing="0" role="grid">
<tbody className = {prefixClsFn('tbody')}>
{hoursEls}
</tbody>
</table>
</div>
</div>);
}
}
TimePanel.defaultProps = {
onSelect() {
}
};
module.exports = TimePanel;
'use strict';
var React = require('react');
var DateTimeFormat = require('gregorian-calendar-format');
var ROW = 3;
var COL = 4;
var cx = require('rc-util').classSet;
var DecadePanel = require('./DecadePanel');
function goYear(direction) {
var next = this.state.value.clone();
next.addYear(direction);
this.setState({value: next});
}
function chooseYear(year) {
var next = this.state.value.clone();
next.setYear(year);
this.props.onSelect(next);
}
class YearPanel extends React.Component {
constructor(props) {
super(props);
this.prefixClsFn = require('./prefixClsFn').bind(this);
this.state = {
value: props.value,
prefixCls: props.rootPrefixCls + '-year-panel'
};
this.nextDecade = goYear.bind(this, 10);
this.previousDecade = goYear.bind(this, -10);
['showDecadePanel', 'onDecadePanelSelect'].forEach(m => {
this[m] = this[m].bind(this);
});
}
showDecadePanel() {
this.setState({
showDecadePanel: 1
});
}
onDecadePanelSelect(current) {
this.setState({
value: current,
showDecadePanel: 0
});
}
getYears() {
var value = this.state.value;
var currentYear = value.getYear();
var startYear = parseInt(currentYear / 10, 10) * 10;
var preYear = startYear - 1;
var current = value.clone();
var locale = this.props.locale;
var yearFormat = locale.yearFormat;
var dateFormatter = new DateTimeFormat(yearFormat);
var years = [];
var index = 0;
for (var i = 0; i < ROW; i++) {
years[i] = [];
for (var j = 0; j < COL; j++) {
current.setYear(preYear + index);
years[i][j] = {
content: preYear + index,
title: dateFormatter.format(current)
};
index++;
}
}
return years;
}
render() {
var props = this.props;
var value = this.state.value;
var locale = props.locale;
var years = this.getYears();
var currentYear = value.getYear();
var startYear = parseInt(currentYear / 10, 10) * 10;
var endYear = startYear + 9;
var prefixClsFn = this.prefixClsFn;
var yeasEls = years.map((row, index) => {
var tds = row.map(y => {
var classNameMap = {};
classNameMap[prefixClsFn('cell')] = 1;
classNameMap[prefixClsFn('selected-cell')] = y.content === currentYear;
classNameMap[prefixClsFn('last-decade-cell')] = y.content < startYear;
classNameMap[prefixClsFn('next-decade-cell')] = y.content > endYear;
return (
<td role="gridcell"
title={y.title}
key={y.content}
onClick={chooseYear.bind(this, y.content)}
className = {cx(classNameMap)}
>
<a
className={prefixClsFn('year')}>
{y.content}
</a>
</td>);
});
return (<tr key={index} role="row">{tds}</tr>);
});
var decadePanel;
if (this.state.showDecadePanel) {
decadePanel = <DecadePanel locale={locale} value={value} rootPrefixCls={props.rootPrefixCls} onSelect={this.onDecadePanelSelect}/>;
}
return (
<div className={this.state.prefixCls}>
<div>
<div className = {prefixClsFn('header')}>
<a className = {prefixClsFn('prev-decade-btn')}
role="button"
onClick={this.previousDecade}
title={locale.previousDecade}>
«
</a>
<a className = {prefixClsFn('decade-select')}
role="button"
onClick={this.showDecadePanel}
title={locale.decadeSelect}>
<span className = {prefixClsFn('decade-select-content')}>
{startYear}-{endYear}
</span>
<span className = {prefixClsFn('decade-select-arrow')}>x</span>
</a>
<a className = {prefixClsFn('next-decade-btn')}
role="button"
onClick={this.nextDecade}
title={locale.nextDecade}>
»
</a>
</div>
<div className = {prefixClsFn('body')}>
<table className = {prefixClsFn('table')} cellSpacing="0" role="grid">
<tbody className = {prefixClsFn('tbody')}>
{yeasEls}
</tbody>
</table>
</div>
</div>
{decadePanel}
</div>);
}
}
YearPanel.defaultProps = {
onSelect() {
}
};
module.exports = YearPanel;
var keyCode = require('rc-util').KeyCode;
var expect = require('expect.js');
var Calendar = require('../index');
var React = require('react/addons');
var TestUtils = React.addons.TestUtils;
var Simulate = TestUtils.Simulate;
var async = require('async');
describe('Calendar', function () {
var calendar;
var container = document.createElement('div');
document.body.appendChild(container);
beforeEach(function (done) {
React.render(<Calendar showToday={true} showWeekNumber={true} showTime={true}/>, container, function () {
calendar = this;
done();
});
});
afterEach(function () {
React.unmountComponentAtNode(container);
});
describe('keyboard works', function () {
it('left works', function (done) {
var original = calendar.state.value;
var expected = original.clone();
expected.addDayOfMonth(-1);
Simulate.keyDown(React.findDOMNode(calendar), {
keyCode: keyCode.LEFT
});
setTimeout(function () {
expect(calendar.state.value.getDayOfMonth()).to.be(expected.getDayOfMonth());
done();
}, 10);
});
it('right works', function (done) {
var original = calendar.state.value;
var expected = original.clone();
expected.addDayOfMonth(1);
Simulate.keyDown(React.findDOMNode(calendar), {
keyCode: keyCode.RIGHT
});
setTimeout(function () {
expect(calendar.state.value.getDayOfMonth()).to.be(expected.getDayOfMonth());
done();
}, 10);
});
it('up works', function (done) {
var original = calendar.state.value;
var expected = original.clone();
expected.addDayOfMonth(-7);
Simulate.keyDown(React.findDOMNode(calendar), {
keyCode: keyCode.UP
});
setTimeout(function () {
expect(calendar.state.value.getDayOfMonth()).to.be(expected.getDayOfMonth());
done();
}, 10);
});
it('down works', function (done) {
var original = calendar.state.value;
var expected = original.clone();
expected.addDayOfMonth(7);
Simulate.keyDown(React.findDOMNode(calendar), {
keyCode: keyCode.DOWN
});
setTimeout(function () {
expect(calendar.state.value.getDayOfMonth()).to.be(expected.getDayOfMonth());
done();
}, 10);
});
it('pageDown works', function (done) {
var original = calendar.state.value;
var expected = original.clone();
expected.addMonth(1);
Simulate.keyDown(React.findDOMNode(calendar), {
keyCode: keyCode.PAGE_DOWN
});
setTimeout(function () {
expect(calendar.state.value.getMonth()).to.be(expected.getMonth());
done();
}, 10);
});
it('pageUp works', function (done) {
var original = calendar.state.value;
var expected = original.clone();
expected.addMonth(-1);
Simulate.keyDown(React.findDOMNode(calendar), {
keyCode: keyCode.PAGE_UP
});
setTimeout(function () {
expect(calendar.state.value.getMonth()).to.be(expected.getMonth());
done();
}, 10);
});
it('ctrl left works', function (done) {
var original = calendar.state.value;
var expected = original.clone();
expected.addYear(-1);
Simulate.keyDown(React.findDOMNode(calendar), {
keyCode: keyCode.LEFT,
ctrlKey: 1
});
setTimeout(function () {
expect(calendar.state.value.getYear()).to.be(expected.getYear());
done();
}, 10);
});
it('ctrl right works', function (done) {
var original = calendar.state.value;
var expected = original.clone();
expected.addYear(1);
Simulate.keyDown(React.findDOMNode(calendar), {
keyCode: keyCode.RIGHT,
ctrlKey: 1
});
setTimeout(function () {
expect(calendar.state.value.getYear()).to.be(expected.getYear());
done();
}, 10);
});
});
it('next month works', function (done) {
var month = calendar.state.value.getMonth();
if (month === 11) {
month = -1;
}
Simulate.click(TestUtils.scryRenderedDOMComponentsWithClass(calendar, 'rc-calendar-next-month-btn')[0]);
setTimeout(function () {
expect(calendar.state.value.getMonth()).to.be(month + 1);
done();
}, 10);
});
it('previous month works', function (done) {
var month = calendar.state.value.getMonth();
if (month === 0) {
month = 12;
}
Simulate.click(TestUtils.scryRenderedDOMComponentsWithClass(calendar, 'rc-calendar-prev-month-btn')[0]);
setTimeout(function () {
expect(calendar.state.value.getMonth()).to.be(month - 1);
done();
}, 10);
});
it('next year works', function (done) {
var year = calendar.state.value.getYear();
Simulate.click(TestUtils.scryRenderedDOMComponentsWithClass(calendar, 'rc-calendar-next-year-btn')[0]);
setTimeout(function () {
expect(calendar.state.value.getYear()).to.be(year + 1);
done();
}, 10);
});
it('previous year works', function (done) {
var year = calendar.state.value.getYear();
Simulate.click(TestUtils.scryRenderedDOMComponentsWithClass(calendar, 'rc-calendar-prev-year-btn')[0]);
setTimeout(function () {
expect(calendar.state.value.getYear()).to.be(year - 1);
done();
}, 10);
});
it('render works', function () {
expect(TestUtils.scryRenderedDOMComponentsWithClass(calendar, 'rc-calendar-cell').length).to.above(0);
});
it('onSelect works', function (done) {
var day;
function onSelect(d) {
expect(d.getDayOfMonth()).to.be(parseInt(day.props.children), 10);
done();
}
calendar = React.render(<Calendar showToday={true}
onSelect={onSelect}
showWeekNumber={true} showTime={true}/>, container);
day = TestUtils.scryRenderedDOMComponentsWithClass(calendar, 'rc-calendar-date')[5];
Simulate.click(day);
});
it('month panel shows', function (done) {
expect(TestUtils.scryRenderedDOMComponentsWithClass(calendar, 'rc-calendar-month-panel').length).to.be(0);
Simulate.click(TestUtils.findRenderedDOMComponentWithClass(calendar, 'rc-calendar-month-select'));
async.series([function (next) {
expect(TestUtils.scryRenderedDOMComponentsWithClass(calendar, 'rc-calendar-month-panel').length).to.be(1);
expect(TestUtils.scryRenderedDOMComponentsWithClass(calendar, 'rc-calendar-month-panel-month').length).to.be(12);
var m = TestUtils.scryRenderedDOMComponentsWithClass(calendar, 'rc-calendar-month-panel-month')[9];
Simulate.click(m);
setTimeout(next, 10);
}, function (next) {
expect(calendar.state.value.getMonth()).to.be(9);
next();
}], done);
});
it('year panel works', function (done) {
var text;
async.series([function (done) {
Simulate.click(TestUtils.findRenderedDOMComponentWithClass(calendar, 'rc-calendar-month-select'));
setTimeout(done, 10);
}, function (done) {
Simulate.click(TestUtils.findRenderedDOMComponentWithClass(calendar, 'rc-calendar-month-panel-year-select'));
setTimeout(done, 10);
}, function (done) {
expect(TestUtils.scryRenderedDOMComponentsWithClass(calendar, 'rc-calendar-year-panel').length).to.be(1);
expect(TestUtils.scryRenderedDOMComponentsWithClass(calendar, 'rc-calendar-year-panel-year').length).to.be(12);
var year = TestUtils.scryRenderedDOMComponentsWithClass(calendar, 'rc-calendar-year-panel-year')[9];
text = year.props.children;
Simulate.click(year);
setTimeout(done, 10);
}, function (done) {
var m = TestUtils.scryRenderedDOMComponentsWithClass(calendar, 'rc-calendar-month-panel-month')[9];
Simulate.click(m);
setTimeout(done, 10);
}, function (done) {
expect(calendar.state.value.getYear()).to.be(text);
done();
}], done);
});
it('decade panel works', function (done) {
async.series([function (done) {
Simulate.click(TestUtils.findRenderedDOMComponentWithClass(calendar, 'rc-calendar-month-select'));
setTimeout(done, 10);
}, function (done) {
Simulate.click(TestUtils.findRenderedDOMComponentWithClass(calendar, 'rc-calendar-month-panel-year-select'));
setTimeout(done, 10);
}, function (done) {
Simulate.click(TestUtils.findRenderedDOMComponentWithClass(calendar, 'rc-calendar-year-panel-decade-select'));
setTimeout(done, 10);
}, function (done) {
expect(TestUtils.scryRenderedDOMComponentsWithClass(calendar, 'rc-calendar-decade-panel').length).to.be(1);
expect(TestUtils.scryRenderedDOMComponentsWithClass(calendar, 'rc-calendar-decade-panel-decade').length).to.be(12);
done();
}], done);
});
});
var keyCode = require('rc-util').KeyCode;
var expect = require('expect.js');
var Calendar = require('../index');
var React = require('react/addons');
var TestUtils = React.addons.TestUtils;
var Simulate = TestUtils.Simulate;
var async = require('async');
describe('Time', function () {
var calendar;
var container = document.createElement('div');
document.body.appendChild(container);
beforeEach(function (done) {
React.render(<Calendar showToday={true} showWeekNumber={true} showTime={true}/>, container, function () {
calendar = this;
done();
});
});
afterEach(function () {
React.unmountComponentAtNode(container);
});
describe('keyboard', function () {
it('hour pane works for up', function (done) {
var hour = calendar.state.value.getHourOfDay();
if (hour === 0) {
hour = 24;
}
Simulate.keyDown(TestUtils.scryRenderedDOMComponentsWithClass(calendar, 'rc-calendar-time-input')[0], {
keyCode: keyCode.UP
});
setTimeout(function () {
expect(calendar.state.value.getHourOfDay()).to.be(hour - 1);
done();
}, 10);
});
it('hour pane works for down', function (done) {
var hour = calendar.state.value.getHourOfDay();
if (hour === 23) {
hour = -1;
}
Simulate.keyDown(TestUtils.scryRenderedDOMComponentsWithClass(calendar, 'rc-calendar-time-input')[0], {
keyCode: keyCode.DOWN
});
setTimeout(function () {
expect(calendar.state.value.getHourOfDay()).to.be(hour + 1);
done();
}, 10);
});
it('minute pane works for up', function (done) {
var minute = calendar.state.value.getMinutes();
if (minute === 0) {
minute = 60;
}
Simulate.keyDown(TestUtils.scryRenderedDOMComponentsWithClass(calendar, 'rc-calendar-time-input')[1], {
keyCode: keyCode.UP
});
setTimeout(function () {
expect(calendar.state.value.getMinutes()).to.be(minute - 1);
done();
}, 10);
});
it('minute pane works for down', function (done) {
var minute = calendar.state.value.getMinutes();
if (minute === 59) {
minute = -1;
}
Simulate.keyDown(TestUtils.scryRenderedDOMComponentsWithClass(calendar, 'rc-calendar-time-input')[1], {
keyCode: keyCode.DOWN
});
setTimeout(function () {
expect(calendar.state.value.getMinutes()).to.be(minute + 1);
done();
}, 10);
});
it('second pane works for up', function (done) {
var second = calendar.state.value.getSeconds();
if (second === 0) {
second = 59;
}
Simulate.keyDown(TestUtils.scryRenderedDOMComponentsWithClass(calendar, 'rc-calendar-time-input')[2], {
keyCode: keyCode.UP
});
setTimeout(function () {
expect(calendar.state.value.getSeconds()).to.be(second - 1);
done();
}, 10);
});
it('second pane works for down', function (done) {
var second = calendar.state.value.getSeconds();
if (second === 59) {
second = -1;
}
Simulate.keyDown(TestUtils.scryRenderedDOMComponentsWithClass(calendar, 'rc-calendar-time-input')[2], {
keyCode: keyCode.DOWN
});
setTimeout(function () {
expect(calendar.state.value.getSeconds()).to.be(second + 1);
done();
}, 10);
});
});
it('hour pane shows', function (done) {
Simulate.click(TestUtils.scryRenderedDOMComponentsWithClass(calendar, 'rc-calendar-time-input')[0]);
async.series([function (done) {
expect(TestUtils.scryRenderedDOMComponentsWithClass(calendar, 'rc-calendar-time-panel-time').length).to.be(24);
Simulate.click(TestUtils.scryRenderedDOMComponentsWithClass(calendar, 'rc-calendar-time-panel-time')[2]);
setTimeout(done, 10);
}, function (done) {
expect(calendar.state.value.getHourOfDay()).to.be(2);
done();
}], done);
});
it('minute pane shows', function (done) {
Simulate.click(TestUtils.scryRenderedDOMComponentsWithClass(calendar, 'rc-calendar-time-input')[1]);
setTimeout(function () {
expect(TestUtils.scryRenderedDOMComponentsWithClass(calendar, 'rc-calendar-time-panel-time').length).to.be(60);
done();
}, 10);
});
it('second pane shows', function (done) {
Simulate.click(TestUtils.scryRenderedDOMComponentsWithClass(calendar, 'rc-calendar-time-input')[2]);
setTimeout(function () {
expect(TestUtils.scryRenderedDOMComponentsWithClass(calendar, 'rc-calendar-time-panel-time').length).to.be(60);
done();
}, 10);
});
});
+1
-2

@@ -1,2 +0,1 @@

/** @jsx React.DOM */
require('rc-calendar/assets/index.css');

@@ -9,3 +8,3 @@ var React = require('react');

var GregorianCalendar = require('gregorian-calendar');
var CalendarLocale = require('../lib/locale/zh-cn');
var CalendarLocale = require('rc-calendar/src/locale/zh-cn');

@@ -12,0 +11,0 @@

@@ -1,2 +0,2 @@

/** @jsx React.DOM */
require('rc-calendar/assets/index.css');

@@ -10,3 +10,3 @@

var zhCn = require('gregorian-calendar/lib/locale/zh-cn');
var CalendarLocale = require('../lib/locale/zh-cn');
var CalendarLocale = require('rc-calendar/src/locale/zh-cn');

@@ -13,0 +13,0 @@ var value = new GregorianCalendar(zhCn);

@@ -1,2 +0,2 @@

/** @jsx React.DOM */
require('bootstrap/dist/css/bootstrap.css');

@@ -10,3 +10,3 @@ require('rc-calendar/assets/bootstrap.css');

var GregorianCalendar = require('gregorian-calendar');
var CalendarLocale = require('../lib/locale/zh-cn');
var CalendarLocale = require('rc-calendar/src/locale/zh-cn');

@@ -13,0 +13,0 @@ var Test = React.createClass({

@@ -1,2 +0,2 @@

/** @jsx React.DOM */
require('rc-calendar/assets/bootstrap.css');

@@ -3,0 +3,0 @@ var Calendar = require('rc-calendar');

@@ -1,2 +0,2 @@

/** @jsx React.DOM */
require('bootstrap/dist/css/bootstrap.css');

@@ -10,3 +10,3 @@ require('rc-calendar/assets/bootstrap.css');

var GregorianCalendar = require('gregorian-calendar');
var CalendarLocale = require('../lib/locale/zh-cn');
var CalendarLocale = require('rc-calendar/src/locale/zh-cn');

@@ -13,0 +13,0 @@ var Test = React.createClass({

@@ -1,2 +0,2 @@

/** @jsx React.DOM */
require('rc-calendar/assets/bootstrap.css');

@@ -3,0 +3,0 @@

@@ -1,2 +0,2 @@

/** @jsx React.DOM */
require('rc-calendar/assets/classic.css');

@@ -3,0 +3,0 @@ var Calendar = require('rc-calendar');

# History
----
## 3.5.0 / 2015-05-26
`new` publish transformed es5 code to npm
## 3.4.0 / 2015-05-19

@@ -5,0 +9,0 @@

@@ -1,2 +0,1 @@

module.exports = require('./lib/Calendar');
module.exports.Picker = require('./lib/Picker');
module.exports = require('./src/');

@@ -1,7 +0,4 @@

/**
* i18n resources for date-picker
* @ignore
* @author yiminghe@gmail.com
*/
module.exports = ({
'use strict';
module.exports = {
today: 'Today',

@@ -29,3 +26,3 @@ clear: 'Clear',

nextCentury: 'Next century',
format: require('gregorian-calendar-format/lib/locale/en-us')
});
format: require('gregorian-calendar-format/lib/locale/en-us')
};

@@ -1,8 +0,4 @@

/**
* i18n resources for date-picker
* @ignore
* @author yiminghe@gmail.com
*/
'use strict';
module.exports = ({
module.exports = {
today: '今天',

@@ -21,6 +17,5 @@ clear: '清除',

secondPanelTitle: '选择秒',
/*jshint quotmark: false*/
yearFormat: "yyyy'年'",
monthYearFormat: "yyyy'年'M'月'",
dateFormat: "yyyy'年'M'月'd'日'",
yearFormat: 'yyyy\'年\'',
monthYearFormat: 'yyyy\'年\'M\'月\'',
dateFormat: 'yyyy\'年\'M\'月\'d\'日\'',
previousYear: '上一年 (Control键加左方向键)',

@@ -33,2 +28,2 @@ nextYear: '下一年 (Control键加右方向键)',

format: require('gregorian-calendar-format/lib/locale/zh-cn')
});
};

@@ -0,7 +1,9 @@

'use strict';
module.exports = function () {
var prefixCls = this.state.prefixCls;
var args = Array.prototype.slice.call(arguments, 0);
return args.map(s => {
return args.map(function (s) {
return prefixCls + '-' + s;
}).join(' ');
};
};
{
"name": "rc-calendar",
"version": "3.4.2",
"version": "3.5.0",
"description": "calendar ui component for react",

@@ -14,2 +14,3 @@ "keywords": [

],
"main": "lib/index",
"homepage": "http://github.com/react-component/calendar",

@@ -30,2 +31,3 @@ "author": "yiminghe@gmail.com",

"build": "rc-tools run build",
"precommit": "rc-tools run precommit",
"less": "rc-tools run less",

@@ -46,5 +48,5 @@ "gh-pages": "rc-tools run gh-pages",

"precommit-hook": "^1.0.7",
"rc-server": "^2.0.0",
"rc-server": "3.x",
"rc-style": "1.0.x",
"rc-tools": "2.x",
"rc-tools": "3.x",
"react": "^0.13.0"

@@ -64,4 +66,3 @@ },

"precommit": [
"lint",
"less"
"precommit"
],

@@ -68,0 +69,0 @@ "dependencies": {

{
"requireCurlyBraces": ["if", "else", "for", "while", "do", "try", "catch"],
"requireSpaceAfterKeywords": ["if", "else", "for", "while", "do", "switch", "return", "try", "catch"],
"requireSpacesInFunctionExpression": {
"beforeOpeningCurlyBrace": true
},
"disallowSpacesInsideArrayBrackets": true,
"disallowSpacesInsideObjectBrackets": true,
"disallowSpacesInsideParentheses": true,
"disallowQuotedKeysInObjects": "allButReserved",
"disallowSpaceAfterObjectKeys": true,
"requireSpaceBeforeBinaryOperators": ["-", "/", "*", "=", "==", "===", "!=", "!==", ">", ">=", "<", "<=" ],
"requireSpacesInConditionalExpression": {
"afterTest": true,
"beforeConsequent": true,
"afterConsequent": true,
"beforeAlternate": true
},
"requireSpaceAfterBinaryOperators": ["/", "*", "=", "==", "===", "!=", "!==", ">", ">=", "<", "<="],
"disallowKeywords": [ "with" ],
"disallowSpaceAfterPrefixUnaryOperators": [ "!" , "++", "--", "+", "-", "~"],
"disallowSpaceBeforePostfixUnaryOperators": ["++", "--", ","],
"disallowMultipleLineBreaks": true,
"disallowKeywordsOnNewLine": ["else"],
"safeContextKeyword": "self",
"excludeFiles": ["lib/**/parser.js"]
}
{
"camelcase": true,
"curly": true,
"eqeqeq": true,
"freeze": true,
"indent": 4,
"latedef": "nofunc",
"quotmark": "false",
"nonew": true,
"newcap": false,
"immed": true,
"noarg": true,
"eqnull": true,
"trailing": true,
"undef": true,
"unused": true,
"browser": true,
"node": true,
"esnext": true,
"globals": {
"describe": false,
"expect": false,
"beforeEach": false,
"afterEach": false,
"modulex": false,
"it": false
}
}
var React = require('react');
var DATE_ROW_COUNT = 6;
var DATE_COL_COUNT = 7;
var DateTimeFormat = require('gregorian-calendar-format');
var GregorianCalendar = require('gregorian-calendar');
var rcUtil = require('rc-util');
var KeyCode = rcUtil.KeyCode;
var MonthPanel = require('./MonthPanel');
var Time = require('./Time');
function noop() {
}
function getIdFromDate(d) {
return 'rc-calendar-' + d.getYear() +
'-' + d.getMonth() + '-' +
d.getDayOfMonth();
}
function goStartMonth() {
var next = this.state.value.clone();
next.setDayOfMonth(1);
this.setState({value: next});
}
function goEndMonth() {
var next = this.state.value.clone();
next.setDayOfMonth(next.getActualMaximum(GregorianCalendar.MONTH));
this.setState({value: next});
}
function goMonth(direction) {
var next = this.state.value.clone();
next.addMonth(direction);
this.setState({value: next});
}
function goYear(direction) {
var next = this.state.value.clone();
next.addYear(direction);
this.setState({value: next});
}
function goWeek(direction) {
var next = this.state.value.clone();
next.addWeekOfYear(direction);
this.setState({value: next});
}
function goDay(direction) {
var next = this.state.value.clone();
next.addDayOfMonth(direction);
this.setState({value: next});
}
function isSameDay(one, two) {
return one.getYear() === two.getYear() &&
one.getMonth() === two.getMonth() &&
one.getDayOfMonth() === two.getDayOfMonth();
}
function beforeCurrentMonthYear(current, today) {
if (current.getYear() < today.getYear()) {
return 1;
}
return current.getYear() === today.getYear() &&
current.getMonth() < today.getMonth();
}
function afterCurrentMonthYear(current, today) {
if (current.getYear() > today.getYear()) {
return 1;
}
return current.getYear() === today.getYear() &&
current.getMonth() > today.getMonth();
}
function onFocus() {
if (this._blurTimer) {
clearTimeout(this._blurTimer);
this._blurTimer = null;
} else {
this.props.onFocus();
}
}
function onBlur() {
if (this._blurTimer) {
clearTimeout(this._blurTimer);
}
this._blurTimer = setTimeout(()=> {
this.props.onBlur();
}, 100);
}
function chooseToday() {
var today = this.state.value.clone();
today.setTime(Date.now());
this.handleSelect(today);
}
function handleDayClick(current) {
this.handleSelect(current);
}
function handleSelect(current, keyDownEvent) {
var props = this.props;
this.setState({
value: current
});
if (!keyDownEvent) {
props.onSelect(current);
}
}
function clear() {
this.props.onClear();
}
function onMonthPanelSelect(current) {
this.setState({
value: current,
showMonthPanel: 0
});
}
function handleKeyDown(e) {
var keyCode = e.keyCode;
// mac
var ctrlKey = e.ctrlKey || e.metaKey;
switch (keyCode) {
case KeyCode.DOWN:
goWeek.call(this, 1);
e.preventDefault();
return true;
case KeyCode.UP:
goWeek.call(this, -1);
e.preventDefault();
return true;
case KeyCode.LEFT:
if (ctrlKey) {
this.previousYear();
} else {
goDay.call(this, -1);
}
e.preventDefault();
return true;
case KeyCode.RIGHT:
if (ctrlKey) {
this.nextYear();
} else {
goDay.call(this, 1);
}
e.preventDefault();
return true;
case KeyCode.HOME:
goStartMonth.call(this);
e.preventDefault();
return true;
case KeyCode.END:
goEndMonth.call(this);
e.preventDefault();
return true;
case KeyCode.PAGE_DOWN:
this.nextMonth();
e.preventDefault();
return true;
case KeyCode.PAGE_UP:
this.previousMonth();
e.preventDefault();
return true;
case KeyCode.ENTER:
this.props.onSelect(this.state.value);
e.preventDefault();
return true;
}
this.props.onKeyDown(e);
}
function showMonthPanel() {
this.setState({
showMonthPanel: 1
});
}
class Calendar extends React.Component {
constructor(props) {
super(props);
var value = props.value || props.defaultValue;
if (!value) {
value = new GregorianCalendar();
value.setTime(Date.now());
}
this.dateFormatter = new DateTimeFormat(props.locale.dateFormat);
this.state = {
orient: props.orient,
prefixCls: props.prefixCls || 'rc-calendar',
value: value
};
// bind methods
this.onBlur = onBlur.bind(this);
this.onFocus = onFocus.bind(this);
this.prefixClsFn = require('./prefixClsFn').bind(this);
this.nextMonth = goMonth.bind(this, 1);
this.previousMonth = goMonth.bind(this, -1);
this.nextYear = goYear.bind(this, 1);
this.previousYear = goYear.bind(this, -1);
this.chooseToday = chooseToday.bind(this);
this.clear = clear.bind(this);
this.handleSelect = handleSelect.bind(this);
this.onMonthPanelSelect = onMonthPanelSelect.bind(this);
this.handleKeyDown = handleKeyDown.bind(this);
this.showMonthPanel = showMonthPanel.bind(this);
}
shouldComponentUpdate() {
return rcUtil.PureRenderMixin.shouldComponentUpdate.apply(this, arguments);
}
componentWillReceiveProps(nextProps) {
var value = nextProps.value;
if (value !== undefined) {
if (!value) {
value = this.state.value.clone();
value.setTime(Date.now());
}
this.setState({
value: value
});
}
if (nextProps.orient) {
this.setState({
orient: nextProps.orient
});
}
if (nextProps.locale !== this.props.locale) {
this.dateFormatter = new DateTimeFormat(nextProps.locale.dateFormat);
}
}
renderDates() {
var props = this.props;
var i, j, current;
var dateTable = [];
var showWeekNumber = props.showWeekNumber;
var value = this.state.value;
var today = value.clone();
var prefixClsFn = this.prefixClsFn;
var cellClass = prefixClsFn('cell');
var weekNumberCellClass = prefixClsFn('week-number-cell');
var dateClass = prefixClsFn('date');
var dateRender = props.dateRender;
var disabledDate = props.disabledDate;
var dateFormatter = this.dateFormatter;
var todayClass = prefixClsFn('today');
var selectedClass = prefixClsFn('selected-day');
var lastMonthDayClass = prefixClsFn('last-month-cell');
var nextMonthDayClass = prefixClsFn('next-month-btn-day');
var disabledClass = prefixClsFn('disabled-cell');
today.setTime(Date.now());
var month1 = value.clone();
month1.set(value.getYear(), value.getMonth(), 1);
var day = month1.getDayOfWeek();
var lastMonthDiffDay = (day + 7 - value.getFirstDayOfWeek()) % 7;
// calculate last month
var lastMonth1 = month1.clone();
lastMonth1.addDayOfMonth(0 - lastMonthDiffDay);
var passed = 0;
for (i = 0; i < DATE_ROW_COUNT; i++) {
for (j = 0; j < DATE_COL_COUNT; j++) {
current = lastMonth1;
if (passed) {
current = current.clone();
current.addDayOfMonth(passed);
}
dateTable.push(current);
passed++;
}
}
var tableHtml = [];
passed = 0;
for (i = 0; i < DATE_ROW_COUNT; i++) {
var weekNumberCell;
var dateCells = [];
if (showWeekNumber) {
weekNumberCell = (<td key={dateTable[passed].getWeekOfYear()} role="gridcell" className = {weekNumberCellClass}>{dateTable[passed].getWeekOfYear()}</td>);
}
for (j = 0; j < DATE_COL_COUNT; j++) {
current = dateTable[passed];
var cls = cellClass;
var disabled = false;
var selected = false;
if (isSameDay(current, today)) {
cls += ' ' + todayClass;
}
if (isSameDay(current, value)) {
cls += ' ' + selectedClass;
selected = true;
}
if (beforeCurrentMonthYear(current, value)) {
cls += ' ' + lastMonthDayClass;
}
if (afterCurrentMonthYear(current, value)) {
cls += ' ' + nextMonthDayClass;
}
if (disabledDate && disabledDate(current, value)) {
cls += ' ' + disabledClass;
disabled = true;
}
var dateHtml;
if (!(dateRender && (dateHtml = dateRender(current, value)))) {
dateHtml = (
<span
key={getIdFromDate(current)}
className = {dateClass}
aria-selected={selected}
aria-disabled={disabled}>
{current.getDayOfMonth()}
</span>);
}
dateCells.push(
<td key={passed} onClick={disabled ? noop : handleDayClick.bind(this, current)} role="gridcell" title={dateFormatter.format(current)} className = {cls}>
{dateHtml}
</td>);
passed++;
}
tableHtml.push(
<tr
key={i}
role="row">
{weekNumberCell}
{dateCells}
</tr>);
}
this.dateTable = dateTable;
return tableHtml;
}
getTodayTime() {
var value = this.state.value;
var today = value.clone();
today.setTime(Date.now());
return this.dateFormatter.format(today);
}
getMonthYear() {
var locale = this.props.locale;
var value = this.state.value;
return new DateTimeFormat(locale.monthYearFormat).format(value);
}
render() {
// console.log('re render');
var showWeekNumberEl;
var props = this.props;
var locale = props.locale;
var state = this.state;
var value = state.value;
var veryShortWeekdays = [];
var weekDays = [];
var firstDayOfWeek = value.getFirstDayOfWeek();
var prefixCls = state.prefixCls;
var prefixClsFn = this.prefixClsFn;
for (var i = 0; i < DATE_COL_COUNT; i++) {
var index = (firstDayOfWeek + i) % DATE_COL_COUNT;
veryShortWeekdays[i] = locale.format.veryShortWeekdays[index];
weekDays[i] = locale.format.weekdays[index];
}
if (props.showWeekNumber) {
showWeekNumberEl = (
<th role="columnheader" className = {prefixClsFn("column-header", "week-number-header")}>
<span className ={prefixClsFn("column-header-inner")}>x</span>
</th>);
}
var weekDaysEls = weekDays.map((value, xindex)=> {
return (
<th key={xindex} role="columnheader" title={value} className ={prefixClsFn("column-header")}>
<span className = {prefixClsFn("column-header-inner")}>
{veryShortWeekdays[xindex]}
</span>
</th>);
});
var footerEl;
if (props.showToday || props.showTime) {
var todayEl;
if (props.showToday) {
todayEl = (<a className = {prefixClsFn("today-btn")}
role="button"
onClick={this.chooseToday}
title={this.getTodayTime()}>{locale.today}</a>);
}
var clearEl;
if (props.showClear) {
clearEl = (<a className = {prefixClsFn("clear-btn")}
role="button"
onClick={this.clear}>{locale.clear}</a>);
}
var footerBtn;
if (todayEl || clearEl) {
footerBtn = <div className={prefixClsFn("footer-btn")}>{todayEl} {clearEl}</div>;
}
var timeEl;
if (props.showTime) {
timeEl = (<Time value={value} rootPrefixCls={prefixCls} prefixClsFn={prefixClsFn} locale={locale} onChange={this.handleSelect}/>);
}
footerEl = (
<div className = {prefixClsFn("footer")}>
{timeEl}
{footerBtn}
</div>);
}
var monthPanel;
if (state.showMonthPanel) {
monthPanel = <MonthPanel locale={locale} value={value} rootPrefixCls={state.prefixCls} onSelect={this.onMonthPanelSelect}/>;
}
var className = prefixCls;
if (props.className) {
className += ' ' + props.className;
}
var orient = state.orient;
if (orient) {
orient.forEach(o => {
className += ' ' + prefixClsFn('orient-' + o);
});
}
return (
<div className = {className} tabIndex="0" onFocus={this.onFocus} onBlur={this.onBlur} onKeyDown={this.handleKeyDown}>
<div style={{outline: 'none'}}>
<div className = {prefixClsFn("header")}>
<a className ={prefixClsFn("prev-year-btn")}
role="button"
onClick={this.previousYear}
title={locale.previousYear}>
«
</a>
<a className = {prefixClsFn("prev-month-btn")}
role="button"
onClick={this.previousMonth}
title={locale.previousMonth}>
</a>
<a className = {prefixClsFn("month-select")}
role="button"
onClick={this.showMonthPanel}
title={locale.monthSelect}>
<span className = {prefixClsFn("month-select-content")}>{this.getMonthYear()}</span>
<span className = {prefixClsFn("month-select-arrow")}>x</span>
</a>
<a className = {prefixClsFn("next-month-btn")}
onClick={this.nextMonth}
title={locale.nextMonth}>
</a>
<a className = {prefixClsFn("next-year-btn")}
onClick={this.nextYear}
title={locale.nextYear}>
»
</a>
</div>
<div className = {prefixClsFn("calendar-body")}>
<table className = {prefixClsFn("table")} cellSpacing="0" role="grid">
<thead>
<tr role="row">
{showWeekNumberEl}
{weekDaysEls}
</tr>
</thead>
<tbody className = {prefixClsFn("tbody")}>
{this.renderDates()}
</tbody>
</table>
</div>
{footerEl}
</div>
{monthPanel}
</div>);
}
}
Calendar.propTypes = {
value: React.PropTypes.object,
defaultValue: React.PropTypes.object,
className: React.PropTypes.string,
orient: React.PropTypes.arrayOf(React.PropTypes.oneOf(['left', 'top', 'right', 'bottom'])),
locale: React.PropTypes.object,
showWeekNumber: React.PropTypes.bool,
showToday: React.PropTypes.bool,
showTime: React.PropTypes.bool,
onSelect: React.PropTypes.func,
onBlur: React.PropTypes.func
};
Calendar.defaultProps = {
locale: require('./locale/en-us'),
onKeyDown: noop,
className: '',
showToday: true,
onSelect: noop,
onFocus: noop,
onBlur: noop,
onClear: noop
};
module.exports = Calendar;
var React = require('react');
var ROW = 4;
var COL = 3;
var cx = require('rc-util').classSet;
function goYear(direction) {
var next = this.state.value.clone();
next.addYear(direction);
this.setState({
value: next
});
}
function chooseDecade(year, e) {
var next = this.state.value.clone();
next.setYear(year);
this.props.onSelect(next);
e.preventDefault();
}
class DecadePanel extends React.Component {
constructor(props) {
super(props);
this.state = {
value: props.value,
prefixCls: props.rootPrefixCls + '-decade-panel'
};
// bind methods
this.prefixClsFn = require('./prefixClsFn').bind(this);
this.nextCentury = goYear.bind(this, 100);
this.previousCentury = goYear.bind(this, -100);
}
render() {
var value = this.state.value;
var locale = this.props.locale;
var currentYear = value.getYear();
var startYear = parseInt(currentYear / 100, 10) * 100;
var preYear = startYear - 10;
var endYear = startYear + 99;
var decades = [];
var index = 0;
var prefixClsFn = this.prefixClsFn;
for (var i = 0; i < ROW; i++) {
decades[i] = [];
for (var j = 0; j < COL; j++) {
decades[i][j] = {
startDecade: preYear + index * 10,
endDecade: preYear + index * 10 + 9
};
index++;
}
}
var decadesEls = decades.map((row, index) => {
var tds = row.map(d => {
var startDecade = d.startDecade;
var endDecade = d.endDecade;
var classNameMap = {};
classNameMap[prefixClsFn('cell')] = 1;
classNameMap[prefixClsFn('selected-cell')] = startDecade <= currentYear && currentYear <= endDecade;
classNameMap[prefixClsFn('last-century-cell')] = startDecade < startYear;
classNameMap[prefixClsFn('next-century-cell')] = endDecade > endYear;
return (<td
key={startDecade}
onClick={chooseDecade.bind(this, startDecade)}
role="gridcell"
className = {cx(classNameMap)}
>
<a
className={prefixClsFn('decade')}>
{startDecade} - {endDecade}
</a>
</td>);
});
return (<tr key={index} role="row">{tds}</tr>);
});
return (
<div className={this.state.prefixCls}>
<div className = {prefixClsFn('header')}>
<a className = {prefixClsFn('prev-century-btn')}
role="button"
onClick={this.previousCentury}
title={locale.previousCentury}>
«
</a>
<div className = {prefixClsFn('century')}>
{startYear}-{endYear}
</div>
<a className = {prefixClsFn('next-century-btn')}
role="button"
onClick={this.nextCentury}
title={locale.nextCentury}>
»
</a>
</div>
<div className = {prefixClsFn('body')}>
<table className = {prefixClsFn('table')} cellSpacing="0" role="grid">
<tbody className = {prefixClsFn('tbody')}>
{decadesEls}
</tbody>
</table>
</div>
</div>);
}
}
DecadePanel.defaultProps = {
onSelect() {
}
};
module.exports = DecadePanel;
var React = require('react');
var DateTimeFormat = require('gregorian-calendar-format');
var ROW = 3;
var COL = 4;
var cx = require('rc-util').classSet;
var YearPanel = require('./YearPanel');
function goYear(direction) {
var next = this.state.value.clone();
next.addYear(direction);
this.setState({
value: next
});
}
function showYearPanel() {
this.setState({
showYearPanel: 1
});
}
function chooseMonth(month) {
var next = this.state.value.clone();
next.setMonth(month);
this.props.onSelect(next);
}
function onYearPanelSelect(current) {
this.setState({
value: current,
showYearPanel: 0
});
}
class MonthPanel extends React.Component {
constructor(props) {
super(props);
this.state = {
value: this.props.value,
prefixCls: this.props.rootPrefixCls + '-month-panel'
};
// bind methods
this.nextYear = goYear.bind(this, 1);
this.previousYear = goYear.bind(this, -1);
this.showYearPanel = showYearPanel.bind(this);
this.onYearPanelSelect = onYearPanelSelect.bind(this);
this.prefixClsFn = require('./prefixClsFn').bind(this);
}
getMonths() {
var props = this.props;
var value = this.state.value;
var current = value.clone();
var locale = props.locale;
var monthYearFormat = locale.monthYearFormat;
var dateFormatter = new DateTimeFormat(monthYearFormat);
var months = [];
var shortMonths = locale.format.shortMonths;
var index = 0;
for (var i = 0; i < ROW; i++) {
months[i] = [];
for (var j = 0; j < COL; j++) {
current.setMonth(index);
months[i][j] = {
value: index,
content: shortMonths[index],
title: dateFormatter.format(current)
};
index++;
}
}
return months;
}
render() {
var props = this.props;
var value = this.state.value;
var locale = props.locale;
var months = this.getMonths();
var year = value.getYear();
var currentMonth = value.getMonth();
var prefixClsFn = this.prefixClsFn;
var monthsEls = months.map((month, index)=> {
var tds = month.map(m => {
var classNameMap = {};
classNameMap[prefixClsFn('cell')] = 1;
classNameMap[prefixClsFn('selected-cell')] = m.value === currentMonth;
return (
<td role="gridcell"
key={m.value}
onClick={chooseMonth.bind(this, m.value)}
title={m.title}
className = {cx(classNameMap)}>
<a
className = {prefixClsFn('month')}>
{m.content}
</a>
</td>);
});
return (<tr key={index} role="row">{tds}</tr>);
});
var yearPanel;
if (this.state.showYearPanel) {
yearPanel = <YearPanel locale={locale} value={value} rootPrefixCls={props.rootPrefixCls} onSelect={this.onYearPanelSelect}/>;
}
return (
<div className= {this.state.prefixCls}>
<div>
<div className = {prefixClsFn('header')}>
<a className = {prefixClsFn('prev-year-btn')}
role="button"
onClick={this.previousYear}
title={locale.previousYear}>
«
</a>
<a className = {prefixClsFn('year-select')}
role="button"
onClick={this.showYearPanel}
title={locale.yearSelect}>
<span className = {prefixClsFn('year-select-content')}>{year}</span>
<span className = {prefixClsFn('year-select-arrow')}>x</span>
</a>
<a className = {prefixClsFn('next-year-btn')}
role="button"
onClick={this.nextYear}
title={locale.nextYear}>
»
</a>
</div>
<div className = {prefixClsFn('body')}>
<table className = {prefixClsFn('table')} cellSpacing="0" role="grid">
<tbody className = {prefixClsFn('tbody')}>
{monthsEls}
</tbody>
</table>
</div>
</div>
{yearPanel}
</div>);
}
}
MonthPanel.defaultProps = {
onSelect() {
}
};
module.exports = MonthPanel;
var React = require('react');
var DateTimeFormat = require('gregorian-calendar-format');
var rcUtil = require('rc-util');
var KeyCode = require('rc-util').KeyCode;
var domAlign = require('dom-align');
var orientMap = {
tl: ['top', 'left'],
tr: ['top', 'right'],
bl: ['bottom', 'left'],
br: ['bottom', 'right']
};
function getImmutableOrient(orient) {
if (orient) {
for (var i in orientMap) {
var original = orientMap[i];
if (original[0] === orient[0] && original[1] === orient[1]) {
return original;
}
}
}
}
function refFn(field, component) {
this[field] = component;
}
/**
* DatePicker = wrap input using Calendar
*/
class Picker extends React.Component {
constructor(props) {
super(props);
this.state = {
open: props.open,
value: props.value || props.defaultValue
};
// bind methods
[
'handleInputClick', 'handleCalendarBlur', 'handleTriggerClick',
'handleCalendarClear', 'handleCalendarKeyDown',
'handleKeyDown', 'handleCalendarSelect'
].forEach(m => {
this[m] = this[m].bind(this);
});
this.saveCalendarRef = refFn.bind(this, 'calendarInstance');
this.saveInputRef = refFn.bind(this, 'inputInstance');
}
componentWillReceiveProps(nextProps) {
if (nextProps.value) {
this.setState({
value: nextProps.value
});
}
}
open(callback) {
this.setState({
open: true
}, callback);
}
close(callback) {
this.setState({
open: false
}, callback);
}
handleInputClick() {
this.toggle();
}
handleTriggerClick() {
this.toggle();
}
toggle(callback) {
this.setState({
open: !this.state.open
}, callback);
}
handleKeyDown(e) {
// down
if (e.keyCode === KeyCode.DOWN) {
e.preventDefault();
this.open();
}
}
handleCalendarKeyDown(e) {
if (e.keyCode === KeyCode.ESC) {
e.stopPropagation();
this.close(() => {
React.findDOMNode(this.inputInstance).focus();
});
}
}
handleCalendarSelect(value) {
this.props.calendar.props.onSelect(value);
var currentValue = this.state.value;
if (this.props.calendar.props.showTime) {
this.setState({
value: value
});
} else {
this.setState({
value: value,
open: false
}, () => {
React.findDOMNode(this.inputInstance).focus();
});
}
if (!currentValue || currentValue.getTime() !== value.getTime()) {
this.props.onChange(value);
}
}
handleCalendarBlur() {
// if invisible, will not trigger blur
this.setState({
open: false
});
}
handleCalendarClear() {
this.props.calendar.props.onClear();
this.setState({
open: false,
value: null
}, ()=> {
React.findDOMNode(this.inputInstance).focus();
});
if (this.state.value !== null) {
this.props.onChange(null);
}
}
componentDidMount() {
this.componentDidUpdate();
}
componentDidUpdate() {
if (this.state.open && !this._lastOpen) {
var orient = this._cacheCalendar.props.orient;
var points = ['tl', 'bl'];
var offset = [0, 5];
if (orient.indexOf('top') !== -1 && orient.indexOf('left') !== -1) {
points = ['tl', 'bl'];
} else if (orient.indexOf('top') !== -1 && orient.indexOf('right') !== -1) {
points = ['tr', 'br'];
} else if (orient.indexOf('bottom') !== -1 && orient.indexOf('left') !== -1) {
points = ['bl', 'tl'];
offset = [0, -5];
} else if (orient.indexOf('bottom') !== -1 && orient.indexOf('right') !== -1) {
points = ['br', 'tr'];
offset = [0, -5];
}
var align = domAlign(React.findDOMNode(this.calendarInstance), React.findDOMNode(this.inputInstance), {
points: points,
offset: offset,
overflow: {
adjustX: 1,
adjustY: 1
}
});
points = align.points;
var newOrient = orientMap[points[0]];
this.calendarInstance.setState({
orient: newOrient
});
React.findDOMNode(this.calendarInstance).focus();
}
this._lastOpen = this.state.open;
}
render() {
var props = this.props;
// var input = React.Children.only(props.children); bug 0.13.0
/*
children: Object
.0: (...)
get .0: function () {
set .0: function (value) {
_reactDidWarn: false
_reactFragment: Object
__proto__: Object
*/
var input = props.children;
if (!React.isValidElement(input)) {
var children = input;
React.Children.forEach(children, m => {
input = m;
});
}
var state = this.state;
var value = state.value;
var calendar = this._cacheCalendar;
if (state.open) {
var calendarInstance = this.calendarInstance;
var calendarProp = props.calendar;
this._cacheCalendar = calendar = React.cloneElement(calendarProp, {
ref: rcUtil.createChainedFunction(calendarProp.props.ref, this.saveCalendarRef),
value: value,
// focused: true,
orient: calendarInstance && calendarInstance.state.orient || getImmutableOrient(calendarProp.props.orient) || orientMap.tl,
onBlur: this.handleCalendarBlur,
onKeyDown: this.handleCalendarKeyDown,
onSelect: this.handleCalendarSelect,
onClear: this.handleCalendarClear
});
}
var inputValue = '';
if (value) {
inputValue = props.formatter.format(value);
}
input = React.cloneElement(input, {
ref: rcUtil.createChainedFunction(input.props.ref, this.saveInputRef),
readOnly: true,
onClick: this.handleInputClick,
value: inputValue,
onKeyDown: this.handleKeyDown
});
var classes = [props.prefixCls];
if (state.open) {
classes.push(props.prefixCls + '-open');
}
var trigger = props.trigger;
if (trigger) {
trigger = React.cloneElement(trigger, {
onClick: this.handleTriggerClick,
unselectable: true,
onMouseDown: prevent
});
}
return <span className={classes.join(' ')}>{[input, calendar, trigger]}</span>;
}
}
function prevent(e) {
e.preventDefault();
}
Picker.propTypes = {
onChange: React.PropTypes.func
};
Picker.defaultProps = {
prefixCls: 'rc-calendar-picker',
onChange() {
},
formatter: new DateTimeFormat('yyyy-MM-dd')
};
module.exports = Picker;
var React = require('react');
var rcUtil = require('rc-util');
var KeyCode = rcUtil.KeyCode;
var TimePanel = require('./TimePanel');
var setHourOfDay = 'setHourOfDay';
var setMinutes = 'setMinutes';
var setSeconds = 'setSeconds';
function padding(number) {
if (number < 10) {
number = '0' + number;
}
return number;
}
function loop(value, min, max) {
if (value === min - 1) {
value = max;
} else if (value === max + 1) {
value = min;
}
return value;
}
function keyDownWrap(method, min, max) {
return function (e) {
var value = e.target.value;
var number = parseInt(value, 10);
var keyCode = e.keyCode;
var handled;
if (keyCode === KeyCode.DOWN) {
number++;
e.stopPropagation();
e.preventDefault();
handled = 1;
} else if (keyCode === KeyCode.UP) {
number--;
e.stopPropagation();
e.preventDefault();
handled = 1;
}
if (handled) {
number = loop(number, min, max);
var time = this.props.value.clone();
time[method](number);
this.props.onChange(time, e);
}
};
}
class Time extends React.Component {
constructor(props) {
super(props);
this.state = {
showHourPanel: 0,
showMinutePanel: 0,
showSecondPanel: 0
};
[
'onHourKeyDown', 'onMinuteKeyDown', 'onSecondKeyDown', 'onHourClick', 'onMinuteClick', 'onSecondClick',
'onSelectPanel'
].forEach(m => {
this[m] = this[m].bind(this);
});
}
onSelectPanel(value, setter) {
this.setState({
showHourPanel: 0,
showMinutePanel: 0,
showSecondPanel: 0
}, ()=> {
// ie9 has broken focus
React.findDOMNode(this.refs[setter]).focus();
});
this.props.onChange(value);
}
onHourClick() {
this.setState({
showHourPanel: 1,
showMinutePanel: 0,
showSecondPanel: 0
});
}
onMinuteClick() {
this.setState({
showHourPanel: 0,
showMinutePanel: 1,
showSecondPanel: 0
});
}
onSecondClick() {
this.setState({
showHourPanel: 0,
showMinutePanel: 0,
showSecondPanel: 1
});
}
shouldComponentUpdate() {
return rcUtil.PureRenderMixin.shouldComponentUpdate.apply(this, arguments);
}
render() {
var state = this.state;
var props = this.props;
var prefixClsFn = props.prefixClsFn;
var value = props.value;
var locale = props.locale;
var hour = value.getHourOfDay();
var minute = value.getMinutes();
var second = value.getSeconds();
var panel;
var commonProps = {
value: value,
onSelect: this.onSelectPanel,
rootPrefixCls: props.rootPrefixCls
};
if (state.showHourPanel) {
panel = <TimePanel rowCount={6} colCount={4} getter="getHourOfDay" setter={setHourOfDay}
title={locale.hourPanelTitle}
{...commonProps}/>;
} else if (state.showMinutePanel) {
panel = <TimePanel rowCount={6} colCount={10} getter="getMinutes" setter={setMinutes}
title={locale.minutePanelTitle}
{...commonProps}/>;
} else if (state.showSecondPanel) {
panel = <TimePanel rowCount={6} colCount={10} getter="getSeconds" setter={setSeconds}
title={locale.secondPanelTitle}
{...commonProps}/>;
}
return (<div>
<input className = {prefixClsFn("time-input")} title={locale.hourInput}
ref={setHourOfDay}
readOnly value={padding(hour)}
onClick={this.onHourClick}
onKeyDown={this.onHourKeyDown}/>
<span> : </span>
<input className = {prefixClsFn("time-input")} title={locale.minuteInput}
ref={setMinutes}
readOnly value={padding(minute)}
onClick={this.onMinuteClick}
onKeyDown = {this.onMinuteKeyDown}/>
<span> : </span>
<input className = {prefixClsFn("time-input")} title={locale.secondInput}
ref={setSeconds}
readOnly value={padding(second)}
onClick={this.onSecondClick}
onKeyDown = {this.onSecondKeyDown}/>
{panel}
</div>);
}
}
Time.prototype.onHourKeyDown = keyDownWrap('setHourOfDay', 0, 23);
Time.prototype.onMinuteKeyDown = keyDownWrap('setMinutes', 0, 59);
Time.prototype.onSecondKeyDown = keyDownWrap('setSeconds', 0, 59);
module.exports = Time;
var React = require('react');
var cx = require('rc-util').classSet;
function choose(hour, e) {
var next = this.state.value.clone();
var method = this.props.setter;
next[method](hour);
this.props.onSelect(next,method);
e.preventDefault();
}
class TimePanel extends React.Component {
constructor(props) {
super(props);
this.state = {
value: props.value,
prefixCls: props.rootPrefixCls + '-time-panel'
};
this.prefixClsFn = require('./prefixClsFn').bind(this);
}
render() {
var value = this.state.value;
var props = this.props;
var method = props.getter;
var currentHour = value[method]();
var data = [];
var prefixClsFn = this.prefixClsFn;
var ROW = props.rowCount;
var COL = props.colCount;
for (var i = 0; i < ROW; i++) {
data[i] = [];
for (var j = 0; j < COL; j++) {
data[i][j] = i * COL + j;
}
}
var hoursEls = data.map((row, index)=> {
var tds = row.map(d => {
var classNameMap = {};
classNameMap[prefixClsFn('cell')] = 1;
classNameMap[prefixClsFn('selected-cell')] = d === currentHour;
return (<td
key={d}
onClick={choose.bind(this, d)}
role="gridcell"
className = {cx(classNameMap)} >
<a
className={prefixClsFn('time')}>
{d}
</a>
</td>);
});
return (<tr key={index} role="row">{tds}</tr>);
});
return (
<div className={this.state.prefixCls}>
<div className = {prefixClsFn('header')}>
<div className = {prefixClsFn('title')}>
{props.title}
</div>
</div>
<div className = {prefixClsFn('body')}>
<table className = {prefixClsFn('table')} cellSpacing="0" role="grid">
<tbody className = {prefixClsFn('tbody')}>
{hoursEls}
</tbody>
</table>
</div>
</div>);
}
}
TimePanel.defaultProps = {
onSelect() {
}
};
module.exports = TimePanel;
var React = require('react');
var DateTimeFormat = require('gregorian-calendar-format');
var ROW = 3;
var COL = 4;
var cx = require('rc-util').classSet;
var DecadePanel = require('./DecadePanel');
function goYear(direction) {
var next = this.state.value.clone();
next.addYear(direction);
this.setState({value: next});
}
function chooseYear(year) {
var next = this.state.value.clone();
next.setYear(year);
this.props.onSelect(next);
}
class YearPanel extends React.Component {
constructor(props) {
super(props);
this.prefixClsFn = require('./prefixClsFn').bind(this);
this.state = {
value: props.value,
prefixCls: props.rootPrefixCls + '-year-panel'
};
this.nextDecade = goYear.bind(this, 10);
this.previousDecade = goYear.bind(this, -10);
['showDecadePanel', 'onDecadePanelSelect'].forEach(m => {
this[m] = this[m].bind(this);
});
}
showDecadePanel() {
this.setState({
showDecadePanel: 1
});
}
onDecadePanelSelect(current) {
this.setState({
value: current,
showDecadePanel: 0
});
}
getYears() {
var value = this.state.value;
var currentYear = value.getYear();
var startYear = parseInt(currentYear / 10, 10) * 10;
var preYear = startYear - 1;
var current = value.clone();
var locale = this.props.locale;
var yearFormat = locale.yearFormat;
var dateFormatter = new DateTimeFormat(yearFormat);
var years = [];
var index = 0;
for (var i = 0; i < ROW; i++) {
years[i] = [];
for (var j = 0; j < COL; j++) {
current.setYear(preYear + index);
years[i][j] = {
content: preYear + index,
title: dateFormatter.format(current)
};
index++;
}
}
return years;
}
render() {
var props = this.props;
var value = this.state.value;
var locale = props.locale;
var years = this.getYears();
var currentYear = value.getYear();
var startYear = parseInt(currentYear / 10, 10) * 10;
var endYear = startYear + 9;
var prefixClsFn = this.prefixClsFn;
var yeasEls = years.map((row, index) => {
var tds = row.map(y => {
var classNameMap = {};
classNameMap[prefixClsFn('cell')] = 1;
classNameMap[prefixClsFn('selected-cell')] = y.content === currentYear;
classNameMap[prefixClsFn('last-decade-cell')] = y.content < startYear;
classNameMap[prefixClsFn('next-decade-cell')] = y.content > endYear;
return (
<td role="gridcell"
title={y.title}
key={y.content}
onClick={chooseYear.bind(this, y.content)}
className = {cx(classNameMap)}
>
<a
className={prefixClsFn('year')}>
{y.content}
</a>
</td>);
});
return (<tr key={index} role="row">{tds}</tr>);
});
var decadePanel;
if (this.state.showDecadePanel) {
decadePanel = <DecadePanel locale={locale} value={value} rootPrefixCls={props.rootPrefixCls} onSelect={this.onDecadePanelSelect}/>;
}
return (
<div className={this.state.prefixCls}>
<div>
<div className = {prefixClsFn('header')}>
<a className = {prefixClsFn('prev-decade-btn')}
role="button"
onClick={this.previousDecade}
title={locale.previousDecade}>
«
</a>
<a className = {prefixClsFn('decade-select')}
role="button"
onClick={this.showDecadePanel}
title={locale.decadeSelect}>
<span className = {prefixClsFn('decade-select-content')}>
{startYear}-{endYear}
</span>
<span className = {prefixClsFn('decade-select-arrow')}>x</span>
</a>
<a className = {prefixClsFn('next-decade-btn')}
role="button"
onClick={this.nextDecade}
title={locale.nextDecade}>
»
</a>
</div>
<div className = {prefixClsFn('body')}>
<table className = {prefixClsFn('table')} cellSpacing="0" role="grid">
<tbody className = {prefixClsFn('tbody')}>
{yeasEls}
</tbody>
</table>
</div>
</div>
{decadePanel}
</div>);
}
}
YearPanel.defaultProps = {
onSelect() {
}
};
module.exports = YearPanel;
/** @jsx React.DOM */
var keyCode = require('rc-util').KeyCode;
var expect = require('expect.js');
var Calendar = require('../index');
var React = require('react/addons');
var TestUtils = React.addons.TestUtils;
var Simulate = TestUtils.Simulate;
var async = require('async');
describe('Calendar', function () {
var calendar;
var container = document.createElement('div');
document.body.appendChild(container);
beforeEach(function (done) {
React.render(<Calendar showToday={true} showWeekNumber={true} showTime={true}/>, container, function () {
calendar = this;
done();
});
});
afterEach(function () {
React.unmountComponentAtNode(container);
});
describe('keyboard works', function () {
it('left works', function (done) {
var original = calendar.state.value;
var expected = original.clone();
expected.addDayOfMonth(-1);
Simulate.keyDown(React.findDOMNode(calendar), {
keyCode: keyCode.LEFT
});
setTimeout(function () {
expect(calendar.state.value.getDayOfMonth()).to.be(expected.getDayOfMonth());
done();
}, 10);
});
it('right works', function (done) {
var original = calendar.state.value;
var expected = original.clone();
expected.addDayOfMonth(1);
Simulate.keyDown(React.findDOMNode(calendar), {
keyCode: keyCode.RIGHT
});
setTimeout(function () {
expect(calendar.state.value.getDayOfMonth()).to.be(expected.getDayOfMonth());
done();
}, 10);
});
it('up works', function (done) {
var original = calendar.state.value;
var expected = original.clone();
expected.addDayOfMonth(-7);
Simulate.keyDown(React.findDOMNode(calendar), {
keyCode: keyCode.UP
});
setTimeout(function () {
expect(calendar.state.value.getDayOfMonth()).to.be(expected.getDayOfMonth());
done();
}, 10);
});
it('down works', function (done) {
var original = calendar.state.value;
var expected = original.clone();
expected.addDayOfMonth(7);
Simulate.keyDown(React.findDOMNode(calendar), {
keyCode: keyCode.DOWN
});
setTimeout(function () {
expect(calendar.state.value.getDayOfMonth()).to.be(expected.getDayOfMonth());
done();
}, 10);
});
it('pageDown works', function (done) {
var original = calendar.state.value;
var expected = original.clone();
expected.addMonth(1);
Simulate.keyDown(React.findDOMNode(calendar), {
keyCode: keyCode.PAGE_DOWN
});
setTimeout(function () {
expect(calendar.state.value.getMonth()).to.be(expected.getMonth());
done();
}, 10);
});
it('pageUp works', function (done) {
var original = calendar.state.value;
var expected = original.clone();
expected.addMonth(-1);
Simulate.keyDown(React.findDOMNode(calendar), {
keyCode: keyCode.PAGE_UP
});
setTimeout(function () {
expect(calendar.state.value.getMonth()).to.be(expected.getMonth());
done();
}, 10);
});
it('ctrl left works', function (done) {
var original = calendar.state.value;
var expected = original.clone();
expected.addYear(-1);
Simulate.keyDown(React.findDOMNode(calendar), {
keyCode: keyCode.LEFT,
ctrlKey: 1
});
setTimeout(function () {
expect(calendar.state.value.getYear()).to.be(expected.getYear());
done();
}, 10);
});
it('ctrl right works', function (done) {
var original = calendar.state.value;
var expected = original.clone();
expected.addYear(1);
Simulate.keyDown(React.findDOMNode(calendar), {
keyCode: keyCode.RIGHT,
ctrlKey: 1
});
setTimeout(function () {
expect(calendar.state.value.getYear()).to.be(expected.getYear());
done();
}, 10);
});
});
it('next month works', function (done) {
var month = calendar.state.value.getMonth();
if (month === 11) {
month = -1;
}
Simulate.click(TestUtils.scryRenderedDOMComponentsWithClass(calendar, 'rc-calendar-next-month-btn')[0]);
setTimeout(function () {
expect(calendar.state.value.getMonth()).to.be(month + 1);
done();
}, 10);
});
it('previous month works', function (done) {
var month = calendar.state.value.getMonth();
if (month === 0) {
month = 12;
}
Simulate.click(TestUtils.scryRenderedDOMComponentsWithClass(calendar, 'rc-calendar-prev-month-btn')[0]);
setTimeout(function () {
expect(calendar.state.value.getMonth()).to.be(month - 1);
done();
}, 10);
});
it('next year works', function (done) {
var year = calendar.state.value.getYear();
Simulate.click(TestUtils.scryRenderedDOMComponentsWithClass(calendar, 'rc-calendar-next-year-btn')[0]);
setTimeout(function () {
expect(calendar.state.value.getYear()).to.be(year + 1);
done();
}, 10);
});
it('previous year works', function (done) {
var year = calendar.state.value.getYear();
Simulate.click(TestUtils.scryRenderedDOMComponentsWithClass(calendar, 'rc-calendar-prev-year-btn')[0]);
setTimeout(function () {
expect(calendar.state.value.getYear()).to.be(year - 1);
done();
}, 10);
});
it('render works', function () {
expect(TestUtils.scryRenderedDOMComponentsWithClass(calendar, 'rc-calendar-cell').length).to.above(0);
});
it('onSelect works', function (done) {
var day;
function onSelect(d) {
expect(d.getDayOfMonth()).to.be(parseInt(day.props.children), 10);
done();
}
calendar = React.render(<Calendar showToday={true}
onSelect={onSelect}
showWeekNumber={true} showTime={true}/>, container);
day = TestUtils.scryRenderedDOMComponentsWithClass(calendar, 'rc-calendar-date')[5];
Simulate.click(day);
});
it('month panel shows', function (done) {
expect(TestUtils.scryRenderedDOMComponentsWithClass(calendar, 'rc-calendar-month-panel').length).to.be(0);
Simulate.click(TestUtils.findRenderedDOMComponentWithClass(calendar, 'rc-calendar-month-select'));
async.series([function (next) {
expect(TestUtils.scryRenderedDOMComponentsWithClass(calendar, 'rc-calendar-month-panel').length).to.be(1);
expect(TestUtils.scryRenderedDOMComponentsWithClass(calendar, 'rc-calendar-month-panel-month').length).to.be(12);
var m = TestUtils.scryRenderedDOMComponentsWithClass(calendar, 'rc-calendar-month-panel-month')[9];
Simulate.click(m);
setTimeout(next, 10);
}, function (next) {
expect(calendar.state.value.getMonth()).to.be(9);
next();
}], done);
});
it('year panel works', function (done) {
var text;
async.series([function (done) {
Simulate.click(TestUtils.findRenderedDOMComponentWithClass(calendar, 'rc-calendar-month-select'));
setTimeout(done, 10);
}, function (done) {
Simulate.click(TestUtils.findRenderedDOMComponentWithClass(calendar, 'rc-calendar-month-panel-year-select'));
setTimeout(done, 10);
}, function (done) {
expect(TestUtils.scryRenderedDOMComponentsWithClass(calendar, 'rc-calendar-year-panel').length).to.be(1);
expect(TestUtils.scryRenderedDOMComponentsWithClass(calendar, 'rc-calendar-year-panel-year').length).to.be(12);
var year = TestUtils.scryRenderedDOMComponentsWithClass(calendar, 'rc-calendar-year-panel-year')[9];
text = year.props.children;
Simulate.click(year);
setTimeout(done, 10);
}, function (done) {
var m = TestUtils.scryRenderedDOMComponentsWithClass(calendar, 'rc-calendar-month-panel-month')[9];
Simulate.click(m);
setTimeout(done, 10);
}, function (done) {
expect(calendar.state.value.getYear()).to.be(text);
done();
}], done);
});
it('decade panel works', function (done) {
async.series([function (done) {
Simulate.click(TestUtils.findRenderedDOMComponentWithClass(calendar, 'rc-calendar-month-select'));
setTimeout(done, 10);
}, function (done) {
Simulate.click(TestUtils.findRenderedDOMComponentWithClass(calendar, 'rc-calendar-month-panel-year-select'));
setTimeout(done, 10);
}, function (done) {
Simulate.click(TestUtils.findRenderedDOMComponentWithClass(calendar, 'rc-calendar-year-panel-decade-select'));
setTimeout(done, 10);
}, function (done) {
expect(TestUtils.scryRenderedDOMComponentsWithClass(calendar, 'rc-calendar-decade-panel').length).to.be(1);
expect(TestUtils.scryRenderedDOMComponentsWithClass(calendar, 'rc-calendar-decade-panel-decade').length).to.be(12);
done();
}], done);
});
});
/** @jsx React.DOM */
var keyCode = require('rc-util').KeyCode;
var expect = require('expect.js');
var Calendar = require('../index');
var React = require('react/addons');
var TestUtils = React.addons.TestUtils;
var Simulate = TestUtils.Simulate;
var async = require('async');
describe('Time', function () {
var calendar;
var container = document.createElement('div');
document.body.appendChild(container);
beforeEach(function (done) {
React.render(<Calendar showToday={true} showWeekNumber={true} showTime={true}/>, container, function () {
calendar = this;
done();
});
});
afterEach(function () {
React.unmountComponentAtNode(container);
});
describe('keyboard', function () {
it('hour pane works for up', function (done) {
var hour = calendar.state.value.getHourOfDay();
if (hour === 0) {
hour = 24;
}
Simulate.keyDown(TestUtils.scryRenderedDOMComponentsWithClass(calendar, 'rc-calendar-time-input')[0], {
keyCode: keyCode.UP
});
setTimeout(function () {
expect(calendar.state.value.getHourOfDay()).to.be(hour - 1);
done();
}, 10);
});
it('hour pane works for down', function (done) {
var hour = calendar.state.value.getHourOfDay();
if (hour === 23) {
hour = -1;
}
Simulate.keyDown(TestUtils.scryRenderedDOMComponentsWithClass(calendar, 'rc-calendar-time-input')[0], {
keyCode: keyCode.DOWN
});
setTimeout(function () {
expect(calendar.state.value.getHourOfDay()).to.be(hour + 1);
done();
}, 10);
});
it('minute pane works for up', function (done) {
var minute = calendar.state.value.getMinutes();
if (minute === 0) {
minute = 60;
}
Simulate.keyDown(TestUtils.scryRenderedDOMComponentsWithClass(calendar, 'rc-calendar-time-input')[1], {
keyCode: keyCode.UP
});
setTimeout(function () {
expect(calendar.state.value.getMinutes()).to.be(minute - 1);
done();
}, 10);
});
it('minute pane works for down', function (done) {
var minute = calendar.state.value.getMinutes();
if (minute === 59) {
minute = -1;
}
Simulate.keyDown(TestUtils.scryRenderedDOMComponentsWithClass(calendar, 'rc-calendar-time-input')[1], {
keyCode: keyCode.DOWN
});
setTimeout(function () {
expect(calendar.state.value.getMinutes()).to.be(minute + 1);
done();
}, 10);
});
it('second pane works for up', function (done) {
var second = calendar.state.value.getSeconds();
if (second === 0) {
second = 59;
}
Simulate.keyDown(TestUtils.scryRenderedDOMComponentsWithClass(calendar, 'rc-calendar-time-input')[2], {
keyCode: keyCode.UP
});
setTimeout(function () {
expect(calendar.state.value.getSeconds()).to.be(second - 1);
done();
}, 10);
});
it('second pane works for down', function (done) {
var second = calendar.state.value.getSeconds();
if (second === 59) {
second = -1;
}
Simulate.keyDown(TestUtils.scryRenderedDOMComponentsWithClass(calendar, 'rc-calendar-time-input')[2], {
keyCode: keyCode.DOWN
});
setTimeout(function () {
expect(calendar.state.value.getSeconds()).to.be(second + 1);
done();
}, 10);
});
});
it('hour pane shows', function (done) {
Simulate.click(TestUtils.scryRenderedDOMComponentsWithClass(calendar, 'rc-calendar-time-input')[0]);
async.series([function (done) {
expect(TestUtils.scryRenderedDOMComponentsWithClass(calendar, 'rc-calendar-time-panel-time').length).to.be(24);
Simulate.click(TestUtils.scryRenderedDOMComponentsWithClass(calendar, 'rc-calendar-time-panel-time')[2]);
setTimeout(done, 10);
}, function (done) {
expect(calendar.state.value.getHourOfDay()).to.be(2);
done();
}], done);
});
it('minute pane shows', function (done) {
Simulate.click(TestUtils.scryRenderedDOMComponentsWithClass(calendar, 'rc-calendar-time-input')[1]);
setTimeout(function () {
expect(TestUtils.scryRenderedDOMComponentsWithClass(calendar, 'rc-calendar-time-panel-time').length).to.be(60);
done();
}, 10);
});
it('second pane shows', function (done) {
Simulate.click(TestUtils.scryRenderedDOMComponentsWithClass(calendar, 'rc-calendar-time-input')[2]);
setTimeout(function () {
expect(TestUtils.scryRenderedDOMComponentsWithClass(calendar, 'rc-calendar-time-panel-time').length).to.be(60);
done();
}, 10);
});
});