1 |
|
2 |
|
3 |
|
4 | import React, { Component } from "react";
|
5 | import RangeCalendar from "./rc-calendar/RangeCalendar";
|
6 | import TimePickerPanel from "rc-time-picker/lib/Panel";
|
7 | import FormControl from "bee-form-control";
|
8 | import Picker from "./rc-calendar/Picker";
|
9 | import InputGroup from 'bee-input-group';
|
10 | import Icon from "bee-icon";
|
11 | import classNames from 'classnames';
|
12 | import { KeyCode } from 'tinper-bee-core';
|
13 | import { formatDate } from './rc-calendar/util';
|
14 | import zhCN from "./locale/zh_CN";
|
15 | import omit from 'omit.js';
|
16 |
|
17 | import moment from "moment";
|
18 | import "moment/locale/zh-cn";
|
19 |
|
20 |
|
21 |
|
22 |
|
23 |
|
24 |
|
25 |
|
26 |
|
27 |
|
28 |
|
29 |
|
30 |
|
31 |
|
32 | const fullFormat = "YYYY-MM-DD";
|
33 |
|
34 | const cn = typeof window !== 'undefined' ? location.search.indexOf("cn") !== -1 : true;
|
35 |
|
36 | const now = moment();
|
37 |
|
38 |
|
39 |
|
40 | function isValidRange(v) {
|
41 | return v && v[0] && v[1];
|
42 | }
|
43 |
|
44 | if (cn) {
|
45 | now.locale("zh-cn").utcOffset(8);
|
46 | } else {
|
47 | now.locale("en-gb").utcOffset(0);
|
48 | }
|
49 |
|
50 |
|
51 | class RangePicker extends Component {
|
52 | constructor(props, context) {
|
53 | super(props, context);
|
54 | this.state = {
|
55 | hoverValue: [],
|
56 | value: this.initValue(props),
|
57 | open: props.open||false
|
58 | };
|
59 | }
|
60 | initValue=(props)=>{
|
61 | let valueProp = props.value || props.defaultValue||[];
|
62 | let values = [];
|
63 | for(let i = 0;i<2;i++){
|
64 | let value = valueProp[i]||'';
|
65 | if(value){
|
66 | if(typeof value == 'string'){
|
67 | if(moment(value).isValid()){
|
68 | values.push(moment(value));
|
69 | }else{
|
70 | console.error('value is not in the correct format');
|
71 | values.push('');
|
72 | }
|
73 | }else if(value.format&&value.isValid()){
|
74 | values.push(value);
|
75 | }else{
|
76 | console.error('value is not in the correct format');
|
77 | values = []
|
78 | }
|
79 | }else{
|
80 | values.push('')
|
81 | }
|
82 | }
|
83 | return values;
|
84 | }
|
85 | componentWillReceiveProps(nextProps){
|
86 | if ("value" in nextProps) {
|
87 | this.setState({
|
88 | value: this.initValue(nextProps)
|
89 | });
|
90 | }
|
91 | if ("open" in nextProps) {
|
92 | this.setState({
|
93 | open: nextProps.open
|
94 | });
|
95 | }
|
96 | this.setState({
|
97 | renderIcon: nextProps.renderIcon
|
98 | });
|
99 | }
|
100 |
|
101 | clearHoverValue = () => this.setState({ hoverValue: [] });
|
102 |
|
103 | onChange = (value) => {
|
104 | const props = this.props;
|
105 | let formatStr = props.format || 'YYYY-MM-DD';
|
106 | if(value.length < 2){ return }
|
107 | this.setState({
|
108 | value:value
|
109 | });
|
110 |
|
111 |
|
112 | if(props.onChange&&isValidRange(value)||value.length==0){
|
113 | if(value.length>0){
|
114 | props.onChange(value,`["${formatDate(value[0],formatStr)}" , "${formatDate(value[1],formatStr)}"]`, [`${formatDate(value[0],formatStr)}` , `${formatDate(value[1],formatStr)}`]);
|
115 | }
|
116 | else {
|
117 | props.onChange(null)
|
118 | }
|
119 |
|
120 | }else{
|
121 | props.onPanelChange&&props.onPanelChange(value);
|
122 | }
|
123 | }
|
124 |
|
125 | onHoverChange = (hoverValue) => {
|
126 | this.setState({ hoverValue });
|
127 | this.props.onHoverChange&&this.props.onHoverChange(hoverValue)
|
128 | }
|
129 |
|
130 | remove = (e) => {
|
131 | this.setState({ value:''});
|
132 | }
|
133 | handleCalendarChange = (value) => {
|
134 |
|
135 | }
|
136 | onMouseLeave = (e) => {
|
137 | this.setState({
|
138 | showClose: false
|
139 | })
|
140 | }
|
141 | onMouseEnter = (e) => {
|
142 | if(!this.valueIsEmpty(this.state.value)){
|
143 | this.setState({
|
144 | showClose: true
|
145 | })
|
146 | }
|
147 | }
|
148 |
|
149 | valueIsEmpty=(value)=>{
|
150 | if(value){
|
151 | if(value.length==0){
|
152 | return true;
|
153 | }else{
|
154 | let flag = true;
|
155 | if(value[0]||value[1])flag=false;
|
156 | return flag;
|
157 | }
|
158 | }else{
|
159 | return true
|
160 | }
|
161 |
|
162 | }
|
163 | clear = (e) => {
|
164 | e&&e.stopPropagation&&e.stopPropagation();
|
165 | this.setState({
|
166 | value: []
|
167 | })
|
168 | this.props.onChange && this.props.onChange([], []);
|
169 | this.props.onFormControlClear&&this.props.onFormControlClear();
|
170 | }
|
171 | onOpenChange = open => {
|
172 | const props = this.props;
|
173 | const self = this;
|
174 |
|
175 |
|
176 |
|
177 |
|
178 | if (open === false) {
|
179 | this.clearHoverValue();
|
180 | }
|
181 |
|
182 | this.setState({
|
183 | open
|
184 | },function(){
|
185 | if(open){
|
186 | setTimeout(() => {
|
187 | self.inputFocus()
|
188 | }, 0);
|
189 | }
|
190 | });
|
191 | props.onOpenChange && props.onOpenChange(open);
|
192 | if(open){
|
193 | setTimeout(()=>{
|
194 | self.inputFocus()
|
195 | },200);
|
196 | }
|
197 | };
|
198 |
|
199 | outInputFocus = (e)=>{
|
200 | if(this.props.hasOwnProperty('open'))e.stopPropagation();
|
201 | this.props.outInputFocus&&this.props.outInputFocus(e);
|
202 | }
|
203 |
|
204 | inputFocus=()=>{
|
205 | let inputs = document.querySelectorAll('.rc-calendar-input');
|
206 | if(!inputs){ return }
|
207 | if(inputs[0].value){
|
208 | inputs[0].select()
|
209 | }else{
|
210 | inputs[0].focus()
|
211 | }
|
212 | inputs[0].onkeydown=this.keydownLeft;
|
213 | inputs[1].onkeydown=this.keydownRight;
|
214 | }
|
215 |
|
216 | keydownLeft=(e)=>{
|
217 | let inputs = document.querySelectorAll('.rc-calendar-input');
|
218 | if(e.keyCode == KeyCode.ESC){
|
219 | this.setState({
|
220 | open:false
|
221 | });
|
222 | this.props.onOpenChange(false,v, (v && this.getValue(v)) || '');
|
223 | }
|
224 | if(e.keyCode == KeyCode.RIGHT||e.keyCode == KeyCode.LEFT){
|
225 | inputs[1].focus()
|
226 | }
|
227 | }
|
228 | keydownRight=(e)=>{
|
229 | let inputs = document.querySelectorAll('.rc-calendar-input');
|
230 | if(e.keyCode == KeyCode.ESC){
|
231 | this.setState({
|
232 | open:false
|
233 | });
|
234 | this.props.onOpenChange(false,v, (v && this.getValue(v)) || '');
|
235 | }
|
236 | if(e.keyCode == KeyCode.LEFT||e.keyCode == KeyCode.RIGHT){
|
237 | inputs[0].focus()
|
238 | }
|
239 | }
|
240 |
|
241 | onStartInputBlur=(e)=>{
|
242 | let inputs = document.querySelectorAll('.rc-calendar-input');
|
243 | let startValue,endValue;
|
244 | if(inputs) {
|
245 | startValue = inputs[0].value ? inputs[0].value : '';
|
246 | endValue = inputs[1].value ? inputs[1].value : '';
|
247 | }
|
248 | this.props.onStartInputBlur && this.props.onStartInputBlur(e, startValue, `["${startValue}" , "${endValue}"]`);
|
249 | }
|
250 | onEndInputBlur=(e)=>{
|
251 | let inputs = document.querySelectorAll('.rc-calendar-input');
|
252 | let startValue,endValue;
|
253 | if(inputs) {
|
254 | startValue = inputs[0].value ? inputs[0].value : '';
|
255 | endValue = inputs[1].value ? inputs[1].value : '';
|
256 | }
|
257 | this.props.onEndInputBlur && this.props.onEndInputBlur(e, endValue, `["${startValue}" , "${endValue}"]`);
|
258 | }
|
259 |
|
260 | stopPropagation = (e) => {
|
261 | e.stopPropagation();
|
262 | }
|
263 | onOk = (value) => {
|
264 | this.props.onOk && this.props.onOk(value);
|
265 | }
|
266 | render() {
|
267 | const props = this.props;
|
268 | const { showClose ,onChange, showHour,showMinute,showSecond,tabIndex,...others } = props;
|
269 | const {value,open} = this.state;
|
270 | let formatStr = props.format || 'YYYY-MM-DD';
|
271 | const timePickerElement = (
|
272 | <TimePickerPanel
|
273 | showHour={showHour} showMinute={showMinute} showSecond={showSecond}
|
274 | defaultValue={moment(moment().format("HH:mm:ss"), "HH:mm:ss")} />
|
275 | );
|
276 | const calendar = (
|
277 | <RangeCalendar
|
278 | hoverValue={this.state.hoverValue}
|
279 | onHoverChange={this.onHoverChange}
|
280 | showWeekNumber={false}
|
281 | format={formatStr}
|
282 | dateInputPlaceholder={props.dateInputPlaceholder||['start', 'end']}
|
283 | locale={props.locale || zhCN }
|
284 | onChange={this.onChange}
|
285 | disabledDate={props.disabledDate}
|
286 | showClear={ props.showClear }
|
287 | showOk={props.showOk}
|
288 | showToday={props.showToday}
|
289 | renderFooter={props.renderFooter}
|
290 | timePicker={props.showTime ? timePickerElement : null}
|
291 | renderError={props.renderError}
|
292 | onStartInputBlur={this.onStartInputBlur}
|
293 | onEndInputBlur={this.onEndInputBlur}
|
294 | onClear={this.clear}
|
295 | onOk={this.onOk}
|
296 | validatorFunc={props.validatorFunc}
|
297 | />
|
298 | );
|
299 | return (
|
300 | <div
|
301 | onClick={this.stopPropagation} onMouseOver={this.stopPropagation}
|
302 | {...omit(others, [
|
303 | 'closeIcon',
|
304 | 'renderIcon',
|
305 | 'showClear',
|
306 | 'showToday',
|
307 | 'locale',
|
308 | 'placeholder',
|
309 | 'showOk',
|
310 | 'dateInputPlaceholder',
|
311 | 'onPanelChange',
|
312 | 'onStartInputBlur',
|
313 | 'onEndInputBlur',
|
314 | 'renderFooter',
|
315 | 'showTime',
|
316 | 'disabledDate',
|
317 | 'disabledTime'
|
318 | ])}
|
319 | >
|
320 | <Picker
|
321 | {...props}
|
322 | value = {value}
|
323 | animation={'animation' in props ? props.animation : "slide-up"}
|
324 | calendar={calendar}
|
325 | disabled={props.disabled}
|
326 | dropdownClassName={props.dropdownClassName}
|
327 | onOpenChange={this.onOpenChange}
|
328 | open={open}
|
329 | >
|
330 | {
|
331 | ({}) => {
|
332 | return (
|
333 | <div className={classNames('calendar-picker','u-input-group','simple',props.className)}
|
334 | onMouseEnter={this.onMouseEnter}
|
335 | onMouseLeave={this.onMouseLeave}
|
336 | >
|
337 | <FormControl
|
338 | placeholder={this.props.placeholder?this.props.placeholder:'start ~ end'}
|
339 | value={isValidRange(value) && (this.props.inputShowValue&&this.props.inputShowValue[0]&&this.props.inputShowValue[1]?`${this.props.inputShowValue[0]} ~ ${this.props.inputShowValue[1]}`:`${formatDate(value[0],formatStr)} ~ ${formatDate(value[1],formatStr)}`) || ''}
|
340 | disabled={props.disabled}
|
341 | onFocus={(v,e)=>{this.outInputFocus(e)}}
|
342 | tabIndex={tabIndex}
|
343 | />
|
344 | {
|
345 | showClose&&(!this.valueIsEmpty(value))&&this.state.showClose&&(!props.disabled)?(
|
346 | <InputGroup.Button shape="border"
|
347 | onClick={this.clear}>
|
348 | { props.closeIcon() }
|
349 | </InputGroup.Button>
|
350 | ):<InputGroup.Button shape="border">
|
351 | { props.renderIcon() }
|
352 | </InputGroup.Button>
|
353 | }
|
354 | </div>
|
355 | );
|
356 | }
|
357 | }
|
358 | </Picker>
|
359 | </div>);
|
360 | }
|
361 | }
|
362 |
|
363 | RangePicker.defaultProps = {
|
364 | closeIcon:()=><Icon type="uf-close-c"/>,
|
365 | renderIcon: () => <Icon type="uf-calendar" />,
|
366 | locale:zhCN,
|
367 | showClear:true,
|
368 | showToday:true,
|
369 | showOk:true,
|
370 | showClose:true,
|
371 | showSecond:true,
|
372 | showHour:true,
|
373 | showMinute:true,
|
374 | validatorFunc:()=>{
|
375 | return true;
|
376 | }
|
377 | }
|
378 |
|
379 | export default RangePicker;
|