1 | import _toConsumableArray from 'babel-runtime/helpers/toConsumableArray';
|
2 | import _classCallCheck from 'babel-runtime/helpers/classCallCheck';
|
3 | import _createClass from 'babel-runtime/helpers/createClass';
|
4 | import _possibleConstructorReturn from 'babel-runtime/helpers/possibleConstructorReturn';
|
5 | import _inherits from 'babel-runtime/helpers/inherits';
|
6 | import * as React from 'react';
|
7 | import { Models } from './date/DataTypes';
|
8 | import { formatDate, shallowEqual } from './util';
|
9 | import defaultLocale from './locale/zh_CN';
|
10 |
|
11 | var DatePicker = function (_React$PureComponent) {
|
12 | _inherits(DatePicker, _React$PureComponent);
|
13 |
|
14 | function DatePicker(props) {
|
15 | _classCallCheck(this, DatePicker);
|
16 |
|
17 | var _this = _possibleConstructorReturn(this, (DatePicker.__proto__ || Object.getPrototypeOf(DatePicker)).call(this, props));
|
18 |
|
19 | _this.visibleMonth = [];
|
20 | _this.getDateWithoutTime = function (date) {
|
21 | if (!date) return 0;
|
22 | return +new Date(date.getFullYear(), date.getMonth(), date.getDate());
|
23 | };
|
24 | _this.genWeekData = function (firstDate) {
|
25 | var minDateTime = _this.getDateWithoutTime(_this.props.minDate);
|
26 | var maxDateTime = _this.getDateWithoutTime(_this.props.maxDate) || Number.POSITIVE_INFINITY;
|
27 | var weeks = [];
|
28 | var nextMonth = _this.getMonthDate(firstDate, 1).firstDate;
|
29 | var currentDay = firstDate;
|
30 | var currentWeek = [];
|
31 | weeks.push(currentWeek);
|
32 | var startWeekday = currentDay.getDay();
|
33 | if (startWeekday > 0) {
|
34 | for (var i = 0; i < startWeekday; i++) {
|
35 | currentWeek.push({});
|
36 | }
|
37 | }
|
38 | while (currentDay < nextMonth) {
|
39 | if (currentWeek.length === 7) {
|
40 | currentWeek = [];
|
41 | weeks.push(currentWeek);
|
42 | }
|
43 | var dayOfMonth = currentDay.getDate();
|
44 | var tick = +currentDay;
|
45 | currentWeek.push({
|
46 | tick: tick,
|
47 | dayOfMonth: dayOfMonth,
|
48 | selected: Models.SelectType.None,
|
49 | isFirstOfMonth: dayOfMonth === 1,
|
50 | isLastOfMonth: false,
|
51 | outOfDate: tick < minDateTime || tick > maxDateTime
|
52 | });
|
53 | currentDay = new Date(currentDay.getTime() + 3600 * 24 * 1000);
|
54 | }
|
55 | currentWeek[currentWeek.length - 1].isLastOfMonth = true;
|
56 | return weeks;
|
57 | };
|
58 | _this.selectDateRange = function (startDate, endDate) {
|
59 | var clear = arguments.length > 2 && arguments[2] !== undefined ? arguments[2] : false;
|
60 | var _this$props = _this.props,
|
61 | getDateExtra = _this$props.getDateExtra,
|
62 | type = _this$props.type,
|
63 | onSelectHasDisableDate = _this$props.onSelectHasDisableDate;
|
64 |
|
65 | if (type === 'one') {
|
66 | endDate = undefined;
|
67 | }
|
68 | var time1 = _this.getDateWithoutTime(startDate),
|
69 | time2 = _this.getDateWithoutTime(endDate);
|
70 | var startDateTick = !time2 || time1 < time2 ? time1 : time2;
|
71 | var endDateTick = time2 && time1 > time2 ? time1 : time2;
|
72 | var startMonthDate = _this.getMonthDate(new Date(startDateTick)).firstDate;
|
73 | var endMonthDate = endDateTick ? new Date(endDateTick) : _this.getMonthDate(new Date(startDateTick)).lastDate;
|
74 | var unuseable = [],
|
75 | needUpdate = false;
|
76 | _this.state.months.filter(function (m) {
|
77 | return m.firstDate >= startMonthDate && m.firstDate <= endMonthDate;
|
78 | }).forEach(function (m) {
|
79 | m.weeks.forEach(function (w) {
|
80 | return w.filter(function (d) {
|
81 | if (!endDateTick) {
|
82 | return d.tick && _this.inDate(startDateTick, d.tick);
|
83 | } else {
|
84 | return d.tick && d.tick >= startDateTick && d.tick <= endDateTick;
|
85 | }
|
86 | }).forEach(function (d) {
|
87 | var oldValue = d.selected;
|
88 | if (clear) {
|
89 | d.selected = Models.SelectType.None;
|
90 | } else {
|
91 | var info = getDateExtra && getDateExtra(new Date(d.tick)) || {};
|
92 | if (d.outOfDate || info.disable) {
|
93 | unuseable.push(d.tick);
|
94 | }
|
95 | if (_this.inDate(startDateTick, d.tick)) {
|
96 | if (type === 'one') {
|
97 | d.selected = Models.SelectType.Single;
|
98 | } else if (!endDateTick) {
|
99 | d.selected = Models.SelectType.Only;
|
100 | } else if (startDateTick !== endDateTick) {
|
101 | d.selected = Models.SelectType.Start;
|
102 | } else {
|
103 | d.selected = Models.SelectType.All;
|
104 | }
|
105 | } else if (_this.inDate(endDateTick, d.tick)) {
|
106 | d.selected = Models.SelectType.End;
|
107 | } else {
|
108 | d.selected = Models.SelectType.Middle;
|
109 | }
|
110 | }
|
111 | needUpdate = needUpdate || d.selected !== oldValue;
|
112 | });
|
113 | });
|
114 | if (needUpdate && m.componentRef) {
|
115 | m.componentRef.updateWeeks();
|
116 | m.componentRef.forceUpdate();
|
117 | }
|
118 | ;
|
119 | });
|
120 | if (unuseable.length > 0) {
|
121 | if (onSelectHasDisableDate) {
|
122 | onSelectHasDisableDate(unuseable.map(function (tick) {
|
123 | return new Date(tick);
|
124 | }));
|
125 | } else {
|
126 | console.warn('Unusable date. You can handle by onSelectHasDisableDate.', unuseable);
|
127 | }
|
128 | }
|
129 | };
|
130 | _this.computeVisible = function (clientHeight, scrollTop) {
|
131 | var needUpdate = false;
|
132 | var MAX_VIEW_PORT = clientHeight * 2;
|
133 | var MIN_VIEW_PORT = clientHeight;
|
134 |
|
135 | var filterFunc = function filterFunc(vm) {
|
136 | return vm.y && vm.height && vm.y + vm.height > scrollTop - MAX_VIEW_PORT && vm.y < scrollTop + clientHeight + MAX_VIEW_PORT;
|
137 | };
|
138 | if (_this.props.infiniteOpt && _this.visibleMonth.length > 12) {
|
139 | _this.visibleMonth = _this.visibleMonth.filter(filterFunc).sort(function (a, b) {
|
140 | return +a.firstDate - +b.firstDate;
|
141 | });
|
142 | }
|
143 |
|
144 | if (_this.visibleMonth.length > 0) {
|
145 | var last = _this.visibleMonth[_this.visibleMonth.length - 1];
|
146 | if (last.y !== undefined && last.height && last.y + last.height < scrollTop + clientHeight + MIN_VIEW_PORT) {
|
147 | var lastIndex = _this.state.months.indexOf(last);
|
148 | for (var i = 1; i <= 2; i++) {
|
149 | var index = lastIndex + i;
|
150 | if (index < _this.state.months.length && _this.visibleMonth.indexOf(_this.state.months[index]) < 0) {
|
151 | _this.visibleMonth.push(_this.state.months[index]);
|
152 | } else {
|
153 | _this.canLoadNext() && _this.genMonthData(undefined, 1);
|
154 | }
|
155 | }
|
156 | needUpdate = true;
|
157 | }
|
158 | var first = _this.visibleMonth[0];
|
159 | if (first.y !== undefined && first.height && first.y > scrollTop - MIN_VIEW_PORT) {
|
160 | var firstIndex = _this.state.months.indexOf(first);
|
161 | for (var _i = 1; _i <= 2; _i++) {
|
162 | var _index = firstIndex - _i;
|
163 | if (_index >= 0 && _this.visibleMonth.indexOf(_this.state.months[_index]) < 0) {
|
164 | _this.visibleMonth.unshift(_this.state.months[_index]);
|
165 | needUpdate = true;
|
166 | }
|
167 | }
|
168 | }
|
169 | } else if (_this.state.months.length > 0) {
|
170 | _this.visibleMonth = _this.state.months.filter(filterFunc);
|
171 | needUpdate = true;
|
172 | }
|
173 | return needUpdate;
|
174 | };
|
175 | _this.createOnScroll = function () {
|
176 | var timer = void 0;
|
177 | var clientHeight = 0,
|
178 | scrollTop = 0;
|
179 | return function (data) {
|
180 | var client = data.client,
|
181 | top = data.top;
|
182 |
|
183 | clientHeight = client;
|
184 | scrollTop = top;
|
185 | if (timer) {
|
186 | return;
|
187 | }
|
188 | timer = setTimeout(function () {
|
189 | timer = undefined;
|
190 | if (_this.computeVisible(clientHeight, scrollTop)) {
|
191 | _this.forceUpdate();
|
192 | }
|
193 | }, 64);
|
194 | };
|
195 | };
|
196 | _this.onCellClick = function (day) {
|
197 | if (!day.tick) return;
|
198 | _this.props.onCellClick && _this.props.onCellClick(new Date(day.tick));
|
199 | };
|
200 | _this.state = {
|
201 | months: []
|
202 | };
|
203 | return _this;
|
204 | }
|
205 |
|
206 | _createClass(DatePicker, [{
|
207 | key: 'shouldComponentUpdate',
|
208 | value: function shouldComponentUpdate(nextProps, nextState, nextContext) {
|
209 | return !shallowEqual(this.props, nextProps, ['startDate', 'endDate']) || !shallowEqual(this.state, nextState) || !shallowEqual(this.context, nextContext);
|
210 | }
|
211 | }, {
|
212 | key: 'componentWillReceiveProps',
|
213 | value: function componentWillReceiveProps(nextProps) {
|
214 | var oldValue = this.props;
|
215 | var newValue = nextProps;
|
216 | if (oldValue.startDate !== newValue.startDate || oldValue.endDate !== newValue.endDate) {
|
217 | if (oldValue.startDate) {
|
218 | this.selectDateRange(oldValue.startDate, oldValue.endDate, true);
|
219 | }
|
220 | if (newValue.startDate) {
|
221 | this.selectDateRange(newValue.startDate, newValue.endDate);
|
222 | }
|
223 | }
|
224 | }
|
225 | }, {
|
226 | key: 'componentWillMount',
|
227 | value: function componentWillMount() {
|
228 | var _props = this.props,
|
229 | _props$initalMonths = _props.initalMonths,
|
230 | initalMonths = _props$initalMonths === undefined ? 6 : _props$initalMonths,
|
231 | defaultDate = _props.defaultDate;
|
232 |
|
233 | for (var i = 0; i < initalMonths; i++) {
|
234 | this.canLoadNext() && this.genMonthData(defaultDate, i);
|
235 | }
|
236 | this.visibleMonth = [].concat(_toConsumableArray(this.state.months));
|
237 | }
|
238 | }, {
|
239 | key: 'getMonthDate',
|
240 | value: function getMonthDate() {
|
241 | var date = arguments.length > 0 && arguments[0] !== undefined ? arguments[0] : new Date();
|
242 | var addMonth = arguments.length > 1 && arguments[1] !== undefined ? arguments[1] : 0;
|
243 |
|
244 | var y = date.getFullYear(),
|
245 | m = date.getMonth();
|
246 | return {
|
247 | firstDate: new Date(y, m + addMonth, 1),
|
248 | lastDate: new Date(y, m + 1 + addMonth, 0)
|
249 | };
|
250 | }
|
251 | }, {
|
252 | key: 'canLoadPrev',
|
253 | value: function canLoadPrev() {
|
254 | var minDate = this.props.minDate;
|
255 |
|
256 | return !minDate || this.state.months.length <= 0 || +this.getMonthDate(minDate).firstDate < +this.state.months[0].firstDate;
|
257 | }
|
258 | }, {
|
259 | key: 'canLoadNext',
|
260 | value: function canLoadNext() {
|
261 | var maxDate = this.props.maxDate;
|
262 |
|
263 | return !maxDate || this.state.months.length <= 0 || +this.getMonthDate(maxDate).firstDate > +this.state.months[this.state.months.length - 1].firstDate;
|
264 | }
|
265 | }, {
|
266 | key: 'genMonthData',
|
267 | value: function genMonthData(date) {
|
268 | var addMonth = arguments.length > 1 && arguments[1] !== undefined ? arguments[1] : 0;
|
269 |
|
270 | if (!date) {
|
271 | date = addMonth >= 0 ? this.state.months[this.state.months.length - 1].firstDate : this.state.months[0].firstDate;
|
272 | }
|
273 | if (!date) {
|
274 | date = new Date();
|
275 | }
|
276 | var locale = this.props.locale;
|
277 |
|
278 | var _getMonthDate = this.getMonthDate(date, addMonth),
|
279 | firstDate = _getMonthDate.firstDate,
|
280 | lastDate = _getMonthDate.lastDate;
|
281 |
|
282 | var weeks = this.genWeekData(firstDate);
|
283 | var title = formatDate(firstDate, locale ? locale.monthTitle : 'yyyy/MM', this.props.locale);
|
284 | var data = {
|
285 | title: title,
|
286 | firstDate: firstDate,
|
287 | lastDate: lastDate,
|
288 | weeks: weeks
|
289 | };
|
290 | data.component = this.genMonthComponent(data);
|
291 | if (addMonth >= 0) {
|
292 | this.state.months.push(data);
|
293 | } else {
|
294 | this.state.months.unshift(data);
|
295 | }
|
296 | var _props2 = this.props,
|
297 | startDate = _props2.startDate,
|
298 | endDate = _props2.endDate;
|
299 |
|
300 | if (startDate) {
|
301 | this.selectDateRange(startDate, endDate);
|
302 | }
|
303 | return data;
|
304 | }
|
305 | }, {
|
306 | key: 'inDate',
|
307 | value: function inDate(date, tick) {
|
308 | return date <= tick && tick < date + 24 * 3600000;
|
309 | }
|
310 | }]);
|
311 |
|
312 | return DatePicker;
|
313 | }(React.PureComponent);
|
314 |
|
315 | export default DatePicker;
|
316 |
|
317 | DatePicker.defaultProps = {
|
318 | prefixCls: 'rmc-calendar',
|
319 | infinite: true,
|
320 | infiniteOpt: false,
|
321 | defaultDate: new Date(),
|
322 | initalMonths: 6,
|
323 | locale: defaultLocale
|
324 | }; |
\ | No newline at end of file |