///
import * as React from 'react';
import view from '../picker/view';
import {
createYearArray,
createMinutesAndSecondsArray,
createHoursArray,
createMonthArray,
getDaysInMonth,
getDefaultValue,
valueFormat,
getTodayDate
} from '../util/date';
// import { setTranslate } from '../util/transform';
import PickerCore from '../picker/core';
const prefix = 'tsp-component-Picker';
function formatLabel(selected: TspComponentPickerValues[]): string {
let label = '';
for (let i = 0; i < selected.length; i++) {
const value = selected[i].value;
if (i < 2) {
label += value + '-';
} else if (i === 3) {
label += ' ' + value;
} else if (i === 4) {
label += ':' + value;
} else {
label += value;
}
}
return label;
}
class DatePicker extends React.Component {
constructor(props: TspComponentDatePickerProps, state: any) {
super(props, state);
this.onPanStart = this.onPanStart.bind(this);
this.onPan = this.onPan.bind(this);
this.onPanEnd = this.onPanEnd.bind(this);
this.onOk = this.onOk.bind(this);
this.onCancel = this.onCancel.bind(this);
this.onOpen = this.onOpen.bind(this);
this.onTransitionEnd = this.onTransitionEnd.bind(this);
}
public static defaultProps: TspComponentDatePickerProps = {
id: '',
cascade: false,
defaultValue: getDefaultValue(),
startDate: getTodayDate(),
endDate: getTodayDate(),
enableStartDate: false,
enableEndDate: false,
mode: 'yyMMddHHmm',
//defaultLabel: formatLabel(getDefaultValue()),
formatLabel
};
/**
* PickerCore实例
*/
private core: PickerCore;
/**
* 触发transitionEnd的timeout返回对象
*/
private transitionEndTimeout: number;
public shouldComponentUpdate(nextProps: TspComponentDatePickerProps): boolean {
return this.props.updateId !== nextProps.updateId;
}
public componentDidMount(): void {
const value = this.props.defaultValue.slice(0, 5).map((item) => item.value).join('');
const startDate = this.props.startDate.join('');
const endDate = this.props.endDate.join('');
if (value < startDate && this.props.enableStartDate) {
console.error('value设定值不能小于startDate的设定值');
return;
}
if (value > endDate && this.props.enableEndDate) {
console.error('value设定值不能超过endDate的设定值');
return;
}
this.core = new PickerCore({
id: this.props.id,
cascade: false,
defaultValue: this.props.defaultValue,
onOk: this.props.onOk,
defaultLabel: this.props.defaultLabel,
data: [],
sliderElem: this.refs.slider as HTMLElement,
containerElem: this.refs.container['elem'] as HTMLElement,
labelElem: this.refs.label as HTMLElement,
formatLabel: this.props.formatLabel
});
this.core.data = this.setMode();
this.core.init();
// this.onTransitionEnd();
this.core.sliderElem.addEventListener('webkitTransitionEnd', this.onTransitionEnd);
}
public componentWillReceiveProps(nextProps: TspComponentDatePickerProps): void {
// this.core.componentWillReceiveProps(this.props, nextProps);
}
public componentDidUpdate(prevProps: TspComponentDatePickerProps): void {
this.core.data = this.setMode();
this.core.componentWillReceiveProps(prevProps, this.props);
}
/**
* 开始拖动
*/
public onPanStart(evt: TspComponentSliderEvt): void {
evt.preventDefault();
this.core.panStart(evt);
}
/**
* 拖动中
*/
public onPan(evt: TspComponentSliderEvt): void {
evt.preventDefault();
this.core.pan(evt);
}
/**
* 拖动结束后
*/
public onPanEnd(evt: TspComponentSliderEvt): void {
evt.preventDefault();
this.core.panEnd(evt);
if (this.core.isPanEnd && this.core.touchElementCol !== undefined) {
this.transitionEndTimeout = setTimeout(() => {
if (!this.core.isTransitionEnd) {
this.onTransitionEnd();
}
}, 300);
}
}
/**
* 监听translate完成事件
*/
public onTransitionEnd(): void {
this.core.transitionEnd(this.transitionEndTimeout);
this.reset();
}
/**
* 重置
*/
public reset(): void {
switch (this.props.mode) {
case 'yyMMdd':
case 'yyMMddHH':
case 'yyMMddHHmm':
if (this.props.enableStartDate || this.props.enableEndDate) {
if (this.core.touchElementCol === 0 || this.core.touchElementCol === 1) {
const year = parseInt(this.core.data[0][this.core.getValueIndex(0, this.core.selected)].value.toString());
const month = parseInt(this.core.data[1][this.core.getValueIndex(1, this.core.selected)].value.toString()) - 1;
const day = parseInt(this.core.data[2][this.core.getValueIndex(2, this.core.selected)].value.toString());
if (this.core.touchElementCol === 0) {
this.replaceMonth(year);
} else if (this.core.touchElementCol === 1) {
this.replaceDays(year, month, day);
}
}
} else {
this.renderDays();
}
break;
default: break;
}
}
/**
* 确定
*/
public onOk(): void {
this.core.ok();
}
/**
* 取消
*/
public onCancel(): void {
this.core.cancel();
}
/**
* 打开
*/
public onOpen(): void {
if (!this.props.disabled) {
this.reset();
this.core['value'] = this.core.selected;
this.core.open();
}
}
/** 设置日期模式 */
// tslint:disable-next-line:max-line-length
// tslint:disable-next-line:array-type
public setMode(yearIndex: number = this.props.defaultValue[0].index, monthIndex: number = this.props.defaultValue[1].index): { value: string | number, label: number | string }[][] {
const mode = this.props.mode;
const startYear = parseInt(this.props.startDate[0].toString());
const endYear = parseInt(this.props.endDate[0].toString());
const startMonth = parseInt(this.props.startDate[1].toString());
const endMonth = parseInt(this.props.endDate[1].toString());
const startDay = parseInt(this.props.startDate[2].toString());
const endDay = parseInt(this.props.endDate[2].toString());
let year = yearIndex !== undefined ? startYear + yearIndex : this.props.defaultValue[0].value;
let month = monthIndex !== undefined ? monthIndex : parseInt(this.props.defaultValue[1].value.toString()) - 1;
let [yy, MM, dd, HH, mm] = [undefined, undefined, undefined, undefined, undefined];
if (mode.indexOf('yy') >= 0) {
const startDate = parseInt(this.props.startDate[0]);
const endDate = parseInt(this.props.endDate[0]);
yy = createYearArray(startDate, endDate, 'array').map((value) => valueFormat(value, 'object', '年'));
}
year = parseInt(year.toString());
month = parseInt(month.toString());
if (mode.indexOf('MM') >= 0) {
MM = createMonthArray('array').map((value) => valueFormat(value + 1, 'object', '月'));
if (this.props.enableStartDate && year === startYear) {
if (this.props.startDate.length >= 2) {
MM = MM.slice(startMonth - 1);
} else {
console.error('startDate设置错误,startDate数组长度不足2维');
}
}
if (this.props.enableEndDate && year === endYear) {
if (this.props.endDate.length >= 2) {
MM = MM.slice(0, endMonth - startMonth + 1);
} else {
console.error('endDate设置错误,endDate数组长度不足2维');
}
}
}
if (mode.indexOf('dd') >= 0) {
dd = getDaysInMonth(year, month, 'array').map((value) => valueFormat(value, 'object', '日'));
if (this.props.enableStartDate && year === startYear && month === startMonth - 1) {
if (this.props.startDate.length >= 3) {
dd = dd.slice(startDay - 1);
} else {
console.error('startDate设置错误,startDate数组长度不等于3维');
}
}
if (this.props.enableEndDate && year === endYear && month === endMonth - 1) {
if (this.props.endDate.length >= 3) {
dd = dd.slice(0, endDay);
} else {
console.error('endDate设置错误,endDate数组长度不足3维');
}
}
}
if (mode.indexOf('HH') >= 0) {
HH = createHoursArray('array').map((value) => valueFormat(value, 'object', '时'));
}
if (mode.indexOf('mm') >= 0) {
mm = createMinutesAndSecondsArray('array').map((value) => valueFormat(value, 'object', '分'));
}
switch (mode) {
case 'yy': return [yy];
case 'yyMM': return [yy, MM];
case 'yyMMdd': return [yy, MM, dd];
case 'yyMMddHH': return [yy, MM, dd, HH];
case 'yyMMddHHmm': return [yy, MM, dd, HH, mm];
case 'HHmm': return [HH, mm];
default: break;
}
}
/**
* 渲染天数
*/
public renderDays(): void {
const data = this.core.data;
const year = parseInt(data[0][this.core.getValueIndex(0, this.core.selected)].value.toString());
const month = parseInt(data[1][this.core.getValueIndex(1, this.core.selected)].value.toString()) - 1;
const days = getDaysInMonth(year, month, 'array').map((value) => valueFormat(value, 'object', '日'));
const oldLength = data[2].length;
const newLength = days.length;
const parent = this.core.sliderElem.children[2];
const fragment = document.createDocumentFragment();
const length = oldLength > newLength ? oldLength : newLength;
const flag = oldLength > newLength ? 1 : 2;
if (oldLength === newLength) {
return;
}
parent.innerHTML = null;
for (let i = 0; i < length; i++) {
const tempElem = document.createElement('div');
tempElem.classList.add(`${prefix}-body-col-item`);
tempElem.innerText = valueFormat(i + 1, 'string', '日');
fragment.appendChild(tempElem);
}
parent.appendChild(fragment);
this.core.data[2] = days;
const selected = this.core.getValueIndex(2, this.core.selected);
this.core.pickerTranslateInitial(2, this.core.data[2][selected] ? selected : 0);
}
public replaceMonth(year: number): void {
const { startDate, endDate, enableStartDate, enableEndDate } = this.props;
const startYear = parseInt(startDate[0].toString());
const endYear = parseInt(endDate[0].toString());
const enableStartYear = year === startYear && enableStartDate;
const enableEndYear = year === endYear && enableEndDate;
const startMonth = parseInt(startDate[1].toString());
const endMonth = parseInt(endDate[1].toString());
const selectedMonth = parseInt(this.core.selected[1].value.toString());
let [month, day] = [undefined, undefined];
if (enableStartYear || enableEndYear) {
if (enableStartYear) {
month = selectedMonth < startMonth ? startMonth : selectedMonth;
} else {
month = selectedMonth > endMonth ? endMonth : selectedMonth;
}
this.core.data = this.setMode(this.core.selected[0].index, month - 1);
this.core.renderCol(this.core.data[1], 1, 'replace');
if (!enableStartYear) {
this.core.selected[1].index = undefined;
this.core.selected[1].value = valueFormat(month, 'string', '月');
}
this.core.pickerTranslateInitial(1, this.core.getValueIndex(1, this.core.selected));
const dayValueIndex = this.core.getValueIndex(2, this.core.selected);
const dayIndex = this.core.data[2].length > dayValueIndex ? dayValueIndex : 0;
day = parseInt(this.core.data[2][dayIndex].value.toString());
this.replaceDays(year, month - 1, day);
} else {
this.renderDays();
this.core.data = this.setMode(this.core.selected[0].index, selectedMonth - 1);
this.core.renderCol(this.core.data[1], 1, 'replace');
this.core.pickerTranslateInitial(1, this.core.getValueIndex(1, this.core.selected));
}
}
public replaceDays(year: number, month: number, day: number): void {
const { startDate, endDate, enableStartDate, enableEndDate } = this.props;
const startYear = parseInt(startDate[0].toString());
const endYear = parseInt(endDate[0].toString());
const startMonth = parseInt(startDate[1].toString()) - 1;
const endMonth = parseInt(endDate[1].toString()) - 1;
const startMatch = year === startYear && month === startMonth && enableStartDate;
const endMatch = year === endYear && month === endMonth && enableEndDate;
if (startMatch || endMatch) {
this.core.data = this.setMode(this.core.selected[0].index, month);
this.core.renderCol(this.core.data[2], 2, 'replace');
this.core.selected[2].index = undefined;
this.core.selected[2].value = valueFormat(day, 'string', '月');
this.core.pickerTranslateInitial(2, this.core.getValueIndex(2, this.core.selected));
} else {
this.renderDays();
}
}
public render(): JSX.Element {
return view(this);
}
}
export default DatePicker;