Просмотр исходного кода

fix: fix some bugs & complete basic input function

yhhu 5 лет назад
Родитель
Сommit
cf84d5d974

+ 4 - 4
src/components/calendar/Header.js

@@ -14,14 +14,14 @@ const Header = () => (
         onNextYear,
       }) => (
         <div className={Styles.wrapper}>
-          <i className={Styles.prevYear} role="presentation" title="上一年" onClick={() => onPrevYear()} />
-          <i className={Styles.prevMonth} role="presentation" title="上一月" onClick={() => onPrevMonth()} />
+          <i className={Styles.prevYear} role="presentation" title="上一年" onClick={e => onPrevYear(e)} />
+          <i className={Styles.prevMonth} role="presentation" title="上一月" onClick={e => onPrevMonth(e)} />
           <div className={Styles.text}>
             <span className={Styles.link}>{`${year}年`}</span>
             <span className={Styles.link}>{`${month}月`}</span>
           </div>
-          <i className={Styles.nextMonth} role="presentation" title="下一月" onClick={() => onNextMonth()} />
-          <i className={Styles.nextYear} role="presentation" title="下一年" onClick={() => onNextYear()} />
+          <i className={Styles.nextMonth} role="presentation" title="下一月" onClick={e => onNextMonth(e)} />
+          <i className={Styles.nextYear} role="presentation" title="下一年" onClick={e => onNextYear(e)} />
         </div>
       )
     }

+ 1 - 1
src/components/calendar/Index.js

@@ -31,7 +31,7 @@ const Index = () => (
                 })}
                 title={day.full}
                 key={day.full}
-                onClick={() => onSelectDay(day)}
+                onClick={e => onSelectDay(day, e)}
                 role="presentation"
               >
                 { day.day }

+ 2 - 2
src/components/footer/Footer.js

@@ -13,11 +13,11 @@ const Footer = () => (
           <div
             role="presentation"
             className={Styles.today}
-            onClick={() => onSelectToday(getDateFormatFromSepecificDate())}
+            onClick={e => onSelectToday(getDateFormatFromSepecificDate(), e)}
           >
             <span>今天</span>
           </div>
-          <div role="presentation" className={Styles.lang} onClick={() => onChangeModel(model)}>
+          <div role="presentation" className={Styles.lang} onClick={e => onChangeModel(model, e)}>
             <span>{ model === CHINESE_MODEL ? '中' : '西' }</span>
           </div>
         </div>

+ 61 - 39
src/components/index/DatePicker.js

@@ -3,12 +3,14 @@ import PropTypes from 'prop-types'
 import Styles from './picker.css'
 import {
   getDateFormatFromSepecificDate,
-  getCurrentYear, getCurrentMonth,
+  getCurrentYear,
+  getCurrentMonth,
   isDateValid,
-  // getCurrentDate,
 } from '../../utils'
 import Modal from '../modal/Modal'
-import { CHINESE_MODEL, WESTERN_MODEL, _ } from '../../const'
+import {
+  CHINESE_MODEL, WESTERN_MODEL, _, noop,
+} from '../../const'
 import { DateContext, initialData } from '../../context'
 import {
   setSelectedDays,
@@ -19,6 +21,7 @@ import {
   getNextYearAndMonth,
   isInCurrentMonth,
 } from '../../helper'
+import '../../utils/closest-polyfill'
 
 class DatePicker extends Component {
   constructor(props) {
@@ -33,6 +36,21 @@ class DatePicker extends Component {
     }
   }
 
+  componentDidMount() {
+    document.addEventListener('click', event => {
+      if (event.target.closest('.picker-wrapper')) {
+        return
+      }
+
+      const { value } = this.state
+      if (!isDateValid(value)) {
+        this.onSelectToday(getDateFormatFromSepecificDate())
+      } else {
+        this.onModalClose()
+      }
+    })
+  }
+
   onModalOpen = () => {
     this.setState({ showModal: true })
   }
@@ -43,13 +61,11 @@ class DatePicker extends Component {
 
   onInputChange = event => {
     const val = event.target.value
-    // console.log(val)
     this.setState({ value: val }, () => {
-      // console.log(isDateValid(val))
-      if (isDateValid(val)) {
-        // this.onSelectDay(val)
-      } else {
-        // this.onSelectToday(getCurrentDate())
+      if (!val || isDateValid(val)) {
+        const { days } = this.state
+        const afterSetDays = setSelectedDays(days, val)
+        this.setState({ days: afterSetDays })
       }
     })
   }
@@ -77,14 +93,41 @@ class DatePicker extends Component {
     })
   }
 
-  onSelectDay = day => {
-    const { days } = this.state
-    const afterSetDays = setSelectedDays(days, day.full)
-    this.setState({ value: day.full, days: afterSetDays }, () => {
-      this.onModalClose()
+  _onChangeYearOrMonth = (
+    changeYear,
+    changeMonth,
+    callback = noop,
+    format,
+  ) => {
+    const {
+      model, value, year, month,
+    } = this.state
+    const dayFormat = format || value
+    const days = getDaysAfterchangedYearOrMonth(changeYear, changeMonth, model)
+    const afterSetDays = setSelectedDays(days, dayFormat)
+    this.setState({
+      days: afterSetDays,
+      year: changeYear === _ ? year : changeYear,
+      month: changeMonth === _ ? month : changeMonth,
+      value: dayFormat,
+    }, () => {
+      callback()
     })
   }
 
+  onSelectDay = day => {
+    const { days, value } = this.state
+    if (!isInCurrentMonth(day.full, value)) {
+      const year = day.full.substring(0, 4)
+      const month = day.full.substring(5, 7)
+      /* eslint-disable no-underscore-dangle */
+      this._onChangeYearOrMonth(year, month, () => this.onModalClose(), day.full)
+    } else {
+      const afterSetDays = setSelectedDays(days, day.full)
+      this.setState({ value: day.full, days: afterSetDays }, () => this.onModalClose())
+    }
+  }
+
   onSelectToday = today => {
     const { days } = this.state
     let renderDays = days
@@ -94,31 +137,12 @@ class DatePicker extends Component {
     }
 
     const afterSetDays = setSelectedDays(renderDays, today)
-    this.setState({ value: today, days: afterSetDays }, () => {
-      this.onModalClose()
-    })
-  }
-
-  _onChangeYearOrMonth = (changeYear, changeMonth) => {
-    const {
-      model,
-      value,
-      year,
-      month,
-    } = this.state
-    const days = getDaysAfterchangedYearOrMonth(changeYear, changeMonth, model)
-    const afterSetDays = setSelectedDays(days, value)
-    this.setState({
-      days: afterSetDays,
-      year: changeYear === _ ? year : changeYear,
-      month: changeMonth === _ ? month : changeMonth,
-    })
+    this.setState({ value: today, days: afterSetDays }, () => this.onModalClose())
   }
 
   onPrevMonth = () => {
     const { year, month } = this.state
     const yearAndMonth = getPrevYearAndMonth(year, month)
-    /* eslint-disable no-underscore-dangle */
     this._onChangeYearOrMonth(yearAndMonth.year, yearAndMonth.month)
   }
 
@@ -143,7 +167,7 @@ class DatePicker extends Component {
     const { value, showModal } = this.state
 
     return (
-      <div className={Styles.wrapper}>
+      <div className={`picker-wrapper ${Styles.wrapper}`}>
         <div
           className={Styles.container}
           style={inline ? { display: 'inline-block' } : {}}
@@ -154,7 +178,7 @@ class DatePicker extends Component {
             className={Styles.input}
             value={value}
             onChange={e => this.onInputChange(e)}
-            onFocus={this.onModalOpen}
+            onFocus={e => this.onModalOpen(e)}
           />
           <i className={Styles.calendar} />
           <i
@@ -175,15 +199,13 @@ class DatePicker extends Component {
               onPrevYear: this.onPrevYear,
               onNextMonth: this.onNextMonth,
               onNextYear: this.onNextYear,
+              onInputChange: this.onInputChange,
             }
           }
         >
           <Modal
             isMounted={showModal}
             delayTime={200}
-            onInputChange={this.onInputChange}
-            onCloseModal={this.onModalClose}
-            {...this.state}
           />
         </DateContext.Provider>
       </div>

+ 17 - 18
src/components/input/Input.js

@@ -1,6 +1,6 @@
 import React from 'react'
-import PropTypes from 'prop-types'
 import Styles from './input.css'
+import { DateContext } from '../../context'
 
 class Input extends React.Component {
   constructor(props) {
@@ -13,26 +13,25 @@ class Input extends React.Component {
   }
 
   render() {
-    const { value, onInputChange } = this.props
-
     return (
-      <div className={Styles.wrapper}>
-        <input
-          ref={this.textInput}
-          className={Styles.input}
-          type="text"
-          placeholder="请选择日期"
-          value={value}
-          onChange={e => onInputChange(e)}
-        />
-      </div>
+      <DateContext.Consumer>
+        {
+          ({ value, onInputChange }) => (
+            <div className={Styles.wrapper}>
+              <input
+                ref={this.textInput}
+                className={Styles.input}
+                type="text"
+                placeholder="请选择日期"
+                value={value}
+                onChange={e => onInputChange(e)}
+              />
+            </div>
+          )
+        }
+      </DateContext.Consumer>
     )
   }
 }
 
-Input.propTypes = {
-  value: PropTypes.string.isRequired,
-  onInputChange: PropTypes.func.isRequired,
-}
-
 export default Input

+ 1 - 8
src/components/modal/Modal.js

@@ -10,8 +10,6 @@ import Footer from '../footer/Footer'
 
 const Modal = ({
   isMounted,
-  value,
-  onInputChange,
 }) => (
   <React.Fragment>
     <div className={classNames(Styles.container, {
@@ -19,10 +17,7 @@ const Modal = ({
       [Styles.out]: !isMounted,
     })}
     >
-      <Input
-        value={value}
-        onInputChange={onInputChange}
-      />
+      <Input />
       <div className={Styles.panel}>
         <div className={Styles.header}>
           <Header />
@@ -40,8 +35,6 @@ Modal.defaultProps = {
 
 Modal.propTypes = {
   isMounted: PropTypes.bool,
-  value: PropTypes.string.isRequired,
-  onInputChange: PropTypes.func.isRequired,
 }
 
 export default delayUnmounting(Modal)

+ 5 - 6
src/helper.js

@@ -61,8 +61,8 @@ export const getPrevYearAndMonth = (year, month) => {
 }
 
 export const getNextYearAndMonth = (year, month) => {
-  let nextYear = year
-  let nextMonth = month
+  let nextYear = +year
+  let nextMonth = +month
   if (+month === 12) {
     nextYear += 1
     nextMonth = 1
@@ -137,7 +137,6 @@ export const getDaysAfterchangedYearOrMonth = (year = getCurrentYear(),
   getDaysOfMonth(year, month, model)
 )
 
-export const isInCurrentMonth = date => {
-  const currentDate = getCurrentDate()
-  return date.substr(0, 7) === currentDate.substr(0, 7)
-}
+export const isInCurrentMonth = (date, current = getCurrentDate()) => (
+  date.substring(0, 7) === current.substring(0, 7)
+)

+ 32 - 0
src/utils/closest-polyfill.js

@@ -0,0 +1,32 @@
+/* eslint-disable */
+(function (ElementProto) {
+  if (typeof ElementProto.matches !== 'function') {
+    ElementProto.matches = ElementProto.msMatchesSelector || ElementProto.mozMatchesSelector || ElementProto.webkitMatchesSelector || function matches(selector) {
+      const element = this
+      let elements = (element.document || element.ownerDocument).querySelectorAll(selector)
+      let index = 0
+
+      while (elements[index] && elements[index] !== element) {
+        ++index
+      }
+
+      return Boolean(elements[index])
+    }
+  }
+
+  if (typeof ElementProto.closest !== 'function') {
+    ElementProto.closest = function closest(selector) {
+      let element = this
+
+      while (element && element.nodeType === 1) {
+        if (element.matches(selector)) {
+          return element
+        }
+
+        element = element.parentNode
+      }
+
+      return null
+    }
+  }
+}(window.Element.prototype))

+ 15 - 12
src/utils/date.js

@@ -50,11 +50,16 @@ export const formatMonthOrDay = dateStr => {
  * @param {String} date 日期
  */
 export const formatDate = date => {
-  const regexp = /^(\d{4})(\s*[/\-\\:]?\s*)?(\d{1,2})(\s*[/\-\\:]?\s*)?(\d{1,2})/
+  const regexp = /(^(\d{4})(\s*[/\-\\:]\s*)(\d{1,2})(\s*[/\-\\:]\s*)(\d{1,2})$)|(^(\d{4})(\d{1,2})(\d{1,2})$)/
   const strArr = trimStr(date).match(regexp)
-  const year = strArr[1]
-  let month = strArr[3]
-  let day = strArr[5]
+
+  if (!strArr) {
+    return { format: '' }
+  }
+
+  const year = strArr[2] || strArr[8]
+  let month = strArr[4] || strArr[9]
+  let day = strArr[6] || strArr[10]
 
   if (+month > 12) {
     warnning('month exceed max month number 12')
@@ -156,25 +161,23 @@ export const isCurrentDay = (year, month, day) => {
  * @param {String} date 日期
  */
 export const isDateValid = date => {
-  const regexp = /^(\d{4})(\s*[/\-\\:]?\s*)?(\d{1,2})(\s*[/\-\\:]?\s*)?(\d{1,2})$/
+  const regexp = /(^(\d{4})(\s*[/\-\\:]\s*)(\d{1,2})(\s*[/\-\\:]\s*)(\d{1,2})$)|(^(\d{4})(\d{1,2})(\d{1,2})$)/
   const strArr = trimStr(date).match(regexp)
-  const result = regexp.test(trimStr(date))
-
-  console.log(strArr)
-  console.log(result)
 
   if (!strArr) {
     return false
   }
 
-  const month = strArr[3]
-  const day = strArr[5]
+  const year = strArr[2] || strArr[8]
+  const month = strArr[4] || strArr[9]
+  const day = strArr[6] || strArr[10]
 
   if (+month > 12) {
     return false
   }
 
-  if (+day > 31) {
+  const countOfMonth = getDaysCountOfMonth(month, year)
+  if (+day > countOfMonth) {
     return false
   }