UNPKG

react-advance-jalaali-datepicker2

Version:

Jalaali React Date Picker developed with love by Alireza Kasaaian

305 lines (286 loc) 10.5 kB
import React from "react"; import ReactDOM from "react-dom"; import moment from "moment-jalaali"; import Days from "./Partials/Days"; import Months from "./Partials/Months"; import Styles from "./Partials/Styles"; import Input from "./Partials/Input"; import Background from "./Partials/Background"; import Years from "./Partials/Years"; const canUseDOM = !!( typeof window !== "undefined" && window.document && window.document.createElement ); moment.loadPersian([]); class JDatePicker extends React.Component { constructor(props) { super(props); this.daysInMonth = this.daysInMonth.bind(this); let preSelected = ""; if (this.props.preSelected) preSelected = this.props.preSelected; this.state = { openPicker: false, eventTarget: {}, selectedYear: parseInt(moment().format("jYYYY")), currentMonth: parseInt(moment().format("jMM")), selectedMonthFirstDay: moment( moment().format("jYYYY") + "/" + moment().format("jMM") + "/01", "jYYYY/jMM/jDD" ).weekday(), selectedDay: preSelected.length > 1 ? moment(preSelected, this.props.format).format("jYYYYjMMjDD") : "", inputValue: preSelected }; this.state.daysCount = this.daysInMonth( moment().format("jMM"), moment().format("jYYYY") ); } componentDidMount() { let {selectedMonthFirstDay} = this.state; if (canUseDOM && !document.getElementById("jdstyle")) { let css = Styles(selectedMonthFirstDay), head = document.head || document.getElementsByTagName("head")[0], style = document.createElement("style"); style.type = "text/css"; style.id = "jdstyle"; if (style.styleSheet) { style.styleSheet.cssText = css; } else { style.appendChild(document.createTextNode(css)); } head.appendChild(style); /*const script = document.createElement("script"); script.src="./static/fontAwesome.js"; script.async=true; document.body.appendChild(script);*/ } } componentDidUpdate(preProps) { const {preSelected, format} = this.props; if ( this.props.controllValue && preProps.preSelected !== preSelected && preSelected !== this.state.selectedDay ) this.setState({ selectedDay: preSelected.length > 1 ? moment(preSelected, this.props.format).format("jYYYYjMMjDD") : "", inputValue: preSelected }); } componentWillMount() { document.addEventListener('mousedown', this.handleClose, false); } componentWillUnmount() { document.removeEventListener('mousedown', this.handleClose, false); } handleClose = async (e) => { let datepickerWrapper = document.getElementById("datepickerWrapper"); if (!datepickerWrapper) return; if (!datepickerWrapper.contains(e.target) && e.target.id !== 'dp') { this.setState({openPicker: false}); await this.removePicker(); } }; daysInMonth(month, selectedYear) { if (month > 0 && month < 7) return 31; else if (month > 6 && month < 12) return 30; else if (month == 12 && moment.jIsLeapYear(selectedYear)) return 30; else if (month == 12 && !moment.jIsLeapYear(selectedYear)) return 29; } daysClicked(day, momentDay) { this.removePicker(); this.setState({openPicker: false}); let {onChange, format} = this.props; if (!format) format = "jYYYY-jMM-jDD"; if (this.state.selectedDay != momentDay) { this.setState({ selectedDay: momentDay, inputValue: moment( momentDay + " 23:59:59", "jYYYYjMMjDD HH:mm:ss" ).format(format) }); } let formatted; if (!!format) formatted = moment( momentDay + " 23:59:59", "jYYYYjMMjDD HH:mm:ss" ).format(format); if (onChange) this.props.onChange( moment(momentDay + " 23:59:59", "jYYYYjMMjDD HH:mm:ss").unix(), formatted ); } monthsClicked(month) { let {selectedYear} = this.state; let year = selectedYear; let thisMonth = month; this.setState({daysCount: 0}); this.removePicker(); if (month == 0) { this.setState({ currentMonth: 12, daysCount: this.daysInMonth(12, selectedYear - 1), selectedYear: selectedYear - 1 }); thisMonth = 12; year = selectedYear - 1; } else if (month == 13) { this.setState({ currentMonth: 1, daysCount: this.daysInMonth(1, selectedYear + 1), selectedYear: selectedYear + 1 }); thisMonth = 1; year = selectedYear + 1; } else this.setState({ currentMonth: month, daysCount: this.daysInMonth(month, selectedYear) }); this.firstDayOfMonth(thisMonth, year); } firstDayOfMonth(mo, ye) { let month = mo.toString(); let year = ye.toString(); if (month.length == 1) month = "0" + month; this.setState({ selectedMonthFirstDay: moment( year + "/" + month + "/01", "jYYYY/jMM/jDD" ).weekday() }); } yearSelected(year) { this.setState({selectedYear: year}); this.firstDayOfMonth(this.state.currentMonth, year); this.removePicker(); } renderDialogForm = () => { const { eventTarget, daysCount, selectedDay, currentMonth, selectedYear, selectedMonthFirstDay, openPicker, } = this.state; const { disableFromUnix, monthTitleEnable, } = this.props; console.log("openPicker in state has " + openPicker + "value"); let boundingClientRect = eventTarget.getBoundingClientRect(); const jDatePickerWrapper = document.createElement("div"); jDatePickerWrapper.style.position = "absolute"; jDatePickerWrapper.style.top = (boundingClientRect.top + eventTarget.clientHeight) + "px"; jDatePickerWrapper.style.left = (boundingClientRect.left + eventTarget.clientWidth - 300) + "px"; jDatePickerWrapper.style.width = "300px"; jDatePickerWrapper.style.zIndex = "9999"; jDatePickerWrapper.id = "datepickerWrapper"; const jDatePicker = document.createElement("div"); jDatePicker.className = "JDatePicker"; jDatePickerWrapper.append(jDatePicker); ReactDOM.render( <div> <div className="JDheader"> <Years changeEvent={returnedYear => this.yearSelected(returnedYear)} year={selectedYear} /> <Months monthTitleEnable={monthTitleEnable} clickEvent={returnedMonth => this.monthsClicked(returnedMonth)} month={currentMonth}/> </div> <div className="days-titles"> <div>ش</div> <div>ی</div> <div>د</div> <div>س</div> <div>چ</div> <div>پ</div> <div>ج</div> </div> <Days disableFromUnix={disableFromUnix} selectedYear={selectedYear} selectedDay={selectedDay} currentMonth={currentMonth} daysCount={daysCount} firstDay={selectedMonthFirstDay} clickEvent={(day, momentDay) => this.daysClicked(day, momentDay)} /> </div>, jDatePicker ); document.body.append(jDatePickerWrapper); }; removePicker = () => { setTimeout(() => { document.getElementById("datepickerWrapper") && document.getElementById("datepickerWrapper").remove(); }, 10); }; render() { let { openPicker, inputValue } = this.state; let { id, placeholder, containerClass, inputTextAlign, inputComponent, cancelOnBackgroundClick } = this.props; let inputAlign = !!inputTextAlign && typeof inputTextAlign != "undefined" ? inputTextAlign : "right"; return ( <div style={{textAlign: "initial"}} className={containerClass} ref={node => this.node = node}> <Input type="text" id={id} placeholder={placeholder} dir="ltr" style={{textAlign: inputAlign}} readOnly value={inputValue} onClick={(event) => { console.log("clicked in input text field"); this.setState({ openPicker: !openPicker, eventTarget: event.target, }); }} component={inputComponent} /> {cancelOnBackgroundClick && openPicker && ( <Background onClick={() => { console.log("remove datepicker wrapper"); this.removePicker(); this.setState({openPicker: false}); }} /> )} { openPicker && this.renderDialogForm() } </div> ); } } export default JDatePicker;