react-advance-jalaali-datepicker2
Version:
Jalaali React Date Picker developed with love by Alireza Kasaaian
305 lines (286 loc) • 10.5 kB
JavaScript
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;