1 |
|
2 |
|
3 |
|
4 |
|
5 | import MonthCalendar from "./rc-calendar/MonthCalendar";
|
6 | import { KeyCode } from 'tinper-bee-core';
|
7 | import React, { Component } from "react";
|
8 | import ReactDOM from 'react-dom';
|
9 | import Picker from "./rc-calendar/Picker";
|
10 | import FormControl from "bee-form-control";
|
11 | import Icon from "bee-icon";
|
12 | import InputGroup from 'bee-input-group';
|
13 | import classnames from 'classnames';
|
14 | import zhCN from "./locale/zh_CN";
|
15 | import omit from 'omit.js';
|
16 | import moment from "moment";
|
17 | import { formatDate } from './rc-calendar/util';
|
18 |
|
19 | class MonthPicker extends Component {
|
20 | constructor(props, context) {
|
21 | super(props, context);
|
22 |
|
23 | this.state = {
|
24 | type: "month",
|
25 | value: props.value || props.defaultValue,
|
26 | open: false,
|
27 | showClose: false
|
28 | };
|
29 | }
|
30 |
|
31 | componentDidMount(){
|
32 | let value = this.props.value || this.props.defaultValue;
|
33 | let format = this.props.format;
|
34 | if(value){
|
35 | if(typeof value == 'string'){
|
36 | if(moment(value, format).isValid()){
|
37 | value = moment(value, format);
|
38 | }else{
|
39 | console.error('value is not in the correct format');
|
40 | value = ''
|
41 | }
|
42 | }else if(value.format&&value.isValid()){
|
43 | value = value;
|
44 | }else{
|
45 | console.error('value is not in the correct format');
|
46 | value = ''
|
47 | }
|
48 | }
|
49 | this.setState({
|
50 | value
|
51 | })
|
52 | }
|
53 |
|
54 | componentWillReceiveProps(nextProps){
|
55 | if('value' in nextProps){
|
56 | let value = nextProps.value;
|
57 | if(value){
|
58 | if(value.format&&value.isValid()){
|
59 |
|
60 | }else{
|
61 | value = moment(value, this.props.format)
|
62 | }
|
63 | }else{
|
64 | value='';
|
65 | }
|
66 | this.setState({
|
67 | value
|
68 | })
|
69 | }
|
70 | }
|
71 | handleCalendarChange = (value) => {
|
72 | this.setState({
|
73 | value: value && Object.assign(value, {_type:'month'}) || value
|
74 | });
|
75 | }
|
76 | onChange = (value) => {
|
77 | let { onChange,onClear,onSelect,format } = this.props;
|
78 |
|
79 | this.setState({
|
80 | value: value && Object.assign(value, {_type:'month'}) || value
|
81 | });
|
82 | onChange&&onChange(value,value?formatDate(value,format):'');
|
83 | };
|
84 | inputFocus=()=>{
|
85 | const self = this;
|
86 | const { format } = self.props;
|
87 | let input = document.querySelector('.rc-calendar-input');
|
88 | if(input){
|
89 | if(input.value){
|
90 | input.select()
|
91 | }else{
|
92 | input.focus()
|
93 | }
|
94 | input.onkeydown=(e)=>{
|
95 | if(e.keyCode == KeyCode.DELETE){
|
96 | input.value = '';
|
97 | self.props.onChange&&self.props.onChange('','');
|
98 | }else if(e.keyCode == KeyCode.ESC){
|
99 | self.setState({
|
100 | open:false
|
101 | });
|
102 | let v = self.state.value;
|
103 | self.props.onOpenChange&&self.props.onOpenChange(false,v, (v && formatDate(v,self.props.format)) || '');
|
104 | ReactDOM.findDOMNode(self.outInput).focus();
|
105 | }else if(e.keyCode == KeyCode.ENTER){
|
106 | let parsed = moment(input.value, format, true);
|
107 | if(parsed.isValid()){
|
108 | self.setState({
|
109 | open:false
|
110 | });
|
111 | let v = self.state.value;
|
112 | self.props.onOpenChange&&self.props.onOpenChange(false,v, (v && formatDate(v,format)) || '');
|
113 | ReactDOM.findDOMNode(self.outInput).focus();
|
114 | }
|
115 | }
|
116 | }
|
117 | }
|
118 | }
|
119 | onOpenChange = open => {
|
120 | const props = this.props;
|
121 | const self = this;
|
122 | this.setState({
|
123 | open
|
124 | },function(){
|
125 | if(open){
|
126 | setTimeout(() => {
|
127 | self.inputFocus()
|
128 | }, 0);
|
129 | }
|
130 | });
|
131 | const value = self.state.value;
|
132 | props.onOpenChange && props.onOpenChange(open,value, (value && formatDate(value,self.props.format)) || '');
|
133 | if(open){
|
134 | setTimeout(()=>{
|
135 | self.inputFocus()
|
136 | },200);
|
137 | }
|
138 | };
|
139 |
|
140 | onTypeChange = type => {
|
141 | this.setState({
|
142 | type
|
143 | });
|
144 | };
|
145 | onMouseLeave = (e) => {
|
146 | this.setState({
|
147 | showClose: false
|
148 | })
|
149 | }
|
150 | onMouseEnter = (e) => {
|
151 | this.setState({
|
152 | showClose: true
|
153 | })
|
154 | }
|
155 | clear = (e) => {
|
156 | e.stopPropagation();
|
157 | this.setState({
|
158 | value: ''
|
159 | })
|
160 | this.props.onChange && this.props.onChange('', '');
|
161 | }
|
162 |
|
163 | render() {
|
164 | let state = this.state;
|
165 | let props = this.props;
|
166 | const { showClose,value, ...others } = props;
|
167 | const monthCalendar = <MonthCalendar {...props}
|
168 | value = {state.value}
|
169 | onChange={this.handleCalendarChange}
|
170 | />;
|
171 | let classes = classnames(props.className, "datepicker-container");
|
172 | return (
|
173 | <div className={classes}
|
174 | {...omit(others, [
|
175 | 'closeIcon',
|
176 | 'renderIcon',
|
177 | 'format',
|
178 | 'showDateInput',
|
179 | 'showMonthInput',
|
180 | 'locale',
|
181 | 'placeholder',
|
182 | 'onClear',
|
183 | 'renderFooter',
|
184 | 'renderError',
|
185 | 'disabledDate',
|
186 | 'disabledTime',
|
187 | ])}
|
188 | >
|
189 | <Picker
|
190 | {...props}
|
191 | onOpenChange={this.onOpenChange}
|
192 | animation={'animation' in props ? props.animation : "slide-up"}
|
193 | calendar={monthCalendar}
|
194 | open={this.state.open}
|
195 | value={state.value}
|
196 | onChange={this.onChange}
|
197 | dropdownClassName={props.dropdownClassName}
|
198 | selectedValue={state.value}
|
199 | renderError={props.renderError}
|
200 | >
|
201 | {({ value }) => {
|
202 | let propsValStr;
|
203 | if(value&&value.format&&value.isValid()){
|
204 | value = (typeof value != 'string') ? formatDate(value,props.format) : value;
|
205 | propsValStr = (typeof props.value != 'string') ? formatDate(props.value,props.format) : props.value;
|
206 | // 为了避免在输入框内输入月份的过程中显示invalid date
|
207 | if (value != propsValStr && propsValStr.length != 0){
|
208 | value = props.value;
|
209 | }
|
210 | }else {
|
211 | value = props.value;
|
212 | }
|
213 | return (
|
214 | <InputGroup simple className="datepicker-input-group"
|
215 | onMouseEnter={this.onMouseEnter}
|
216 | onMouseLeave={this.onMouseLeave}
|
217 | >
|
218 | <FormControl
|
219 | ref = { ref => this.outInput = ref }
|
220 | placeholder={this.props.placeholder}
|
221 | className={this.props.className}
|
222 | value={value}
|
223 | disabled={props.disabled}
|
224 | />
|
225 | {
|
226 | showClose&&this.state.value&&this.state.showClose&&(!props.disabled)?(
|
227 | <InputGroup.Button shape="border"
|
228 | onClick={this.clear}>
|
229 | { props.closeIcon() }
|
230 | </InputGroup.Button>
|
231 | ):<InputGroup.Button shape="border">
|
232 | { props.renderIcon() }
|
233 | </InputGroup.Button>
|
234 | }
|
235 | </InputGroup>
|
236 | );
|
237 | }}
|
238 | </Picker>
|
239 | </div>
|
240 | );
|
241 | }
|
242 | }
|
243 |
|
244 |
|
245 | MonthPicker.defaultProps = {
|
246 | closeIcon:()=><Icon type="uf-close-c"/>,
|
247 | renderIcon: () => <Icon type="uf-calendar" />,
|
248 | format:'YYYY-MM',
|
249 | renderError:()=>{},
|
250 | showDateInput:true,
|
251 | showMonthInput:true,
|
252 | locale:zhCN,
|
253 | showClose:true,
|
254 | autoTriggerChange:true,
|
255 | validatorFunc:()=>{
|
256 | return true;
|
257 | }
|
258 | }
|
259 |
|
260 | export default MonthPicker;
|