Created
December 26, 2016 10:43
-
-
Save arnabdas/34083b2c78cd17b988ed96a009ce0ad1 to your computer and use it in GitHub Desktop.
A very simple datepicker with ReactJS
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
// Variables | |
$default-font-color: rgb(119, 119, 119); | |
$rem-cal-background: rgba(232, 232, 232, 1); | |
.rem-cal { | |
position: relative; | |
.rem-cal-wrapper { | |
position: relative; | |
display: none; | |
z-index: 10; | |
&.open { | |
display: inline-block; | |
} | |
.rem-cal-triangle-up { | |
position: absolute; | |
left: -.9em; | |
width: 0; | |
height: 0; | |
left: 2.5em; | |
top: -15px; | |
border-left: .9em solid transparent; | |
border-right: .9em solid transparent; | |
border-bottom: .9em solid $rem-cal-background; | |
} | |
.rem-cal-content { | |
position: absolute; | |
min-height: 120px; | |
min-width: 250px; | |
left: 0.5em; | |
top: -3px; | |
padding: 3px; | |
border-radius: 4px; | |
background: $rem-cal-background; | |
.rem-cal-header { | |
height: 2em; | |
.rem-cal-header-nav { | |
margin: .5em .2em; | |
cursor: pointer; | |
color: lighten($default-font-color, 30%); | |
&:hover { | |
color: lighten($default-font-color, 20%); | |
} | |
} | |
.rem-cal-header-info { | |
font-size: 1.4em; | |
top: 1px; | |
} | |
} | |
.rem-cal-month { | |
background: lighten($rem-cal-background, 80%); | |
.rem-cal-cell { | |
cursor: pointer; | |
width: 2.5em; | |
padding: .1em; | |
font-size: .9em; | |
text-align: center; | |
display: inline-block; | |
&:hover { | |
color: darken($default-font-color, 20%); | |
} | |
} | |
} | |
} | |
} | |
} |
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
/// <reference path="../../../typings/index.d.ts" /> | |
import * as React from 'react'; | |
import * as ReactDOM from 'react-dom'; | |
export interface DatepickerProps { format?: string, onChange?: () => {}, selectedDate?: string }; | |
export interface DatepickerState { | |
isOpen?: boolean, | |
dateToShow?: string, | |
showingMonth?: number, | |
showingYear?: number, | |
selectedDate?: Date, | |
monthArray?: Array<string> | |
}; | |
export class Datepicker extends React.Component<DatepickerProps, DatepickerState> { | |
_mounted: boolean; | |
constructor() { | |
super(); | |
} | |
componentWillMount() { | |
let selectedDate = new Date(); | |
if (this.props.selectedDate) { | |
selectedDate = new Date(this.props.selectedDate); | |
} | |
this.setState({ | |
isOpen: false, | |
selectedDate: selectedDate, | |
dateToShow: `${selectedDate.getDate()}/${selectedDate.getMonth()+1}/${selectedDate.getFullYear()}` | |
}); | |
this.setMonthArray(selectedDate.getFullYear(), selectedDate.getMonth()); | |
} | |
navigateMonth(isFwd: boolean) { | |
let currentYear = this.state.showingYear; | |
let currentMonth = this.state.showingMonth; | |
currentMonth = isFwd ? currentMonth + 1 : currentMonth - 1; | |
if (currentMonth > 11) { | |
currentMonth = 0; | |
currentYear += 1; | |
} | |
else if (currentMonth < 0) { | |
currentMonth = 11; | |
currentYear -= 1; | |
} | |
this.setMonthArray(currentYear, currentMonth); | |
} | |
setMonthArray(year: number, month: number) { | |
let firstDay = (new Date(year, month)).getDay(); | |
let daysInMonthExtended = (new Date(year, month, 0)).getDate() + firstDay; | |
let monthArray = ['Su', 'Mo', 'Tu', 'We', 'Th', 'Fr', 'Sa']; | |
for (var i = 0; i <= daysInMonthExtended; i++) { | |
if (i < firstDay) { | |
monthArray.push(''); | |
} | |
else { | |
monthArray.push((i - firstDay + 1).toString()); | |
} | |
} | |
this.setState({ | |
monthArray: monthArray, | |
showingMonth: month, | |
showingYear: year | |
}); | |
} | |
showCalendar() { | |
if (this.state.isOpen) { | |
return; | |
} | |
let showingMonth = this.state.selectedDate.getMonth(); | |
let showingYear = this.state.selectedDate.getFullYear(); | |
this.setMonthArray(showingYear, showingMonth); | |
this.setState({ | |
isOpen: true, | |
showingMonth: showingMonth, | |
showingYear: showingYear | |
}); | |
} | |
setSelectedDate(d: string) { | |
let selectedDay = Number(d); | |
if (isNaN(selectedDay)) { | |
return; | |
} | |
let selectedDate = new Date(this.state.showingYear, this.state.showingMonth, selectedDay); | |
this.setState({ | |
isOpen: false, | |
selectedDate: selectedDate, | |
dateToShow: `${selectedDate.getDate()}/${selectedDate.getMonth() + 1}/${selectedDate.getFullYear()}` | |
}); | |
} | |
render() { | |
return ( | |
<div className="rem-cal"> | |
<input type="text" className="form-control" placeholder={this.props.format} onFocus={() => { this.showCalendar() } } value={this.state.dateToShow} /> | |
<div className={this.state.isOpen ? 'rem-cal-wrapper open' : 'rem-cal-wrapper'}> | |
<div className="rem-cal-triangle-up" /> | |
<div className="rem-cal-content" > | |
<div className="rem-cal-header text-center" > | |
<span className="rem-cal-header-nav glyphicon glyphicon-triangle-left pull-left" onClick={() => { this.navigateMonth(false) } } /> | |
<span className="rem-cal-header-info">{ | |
['January', 'February', 'March', 'April', 'May', 'June', | |
'July', 'August', 'September', 'October', 'November', 'December'][this.state.showingMonth] }, {this.state.showingYear }</span> | |
<span className="rem-cal-header-nav glyphicon glyphicon-triangle-right pull-right" onClick={() => { this.navigateMonth(true) } } /> | |
</div> | |
<div className="rem-cal-month"> | |
{this.state.monthArray.map(function (d) { | |
return ( | |
<span className="rem-cal-cell" onClick={() => { this.setSelectedDate(d) } }>{d}</span> | |
); | |
}.bind(this)) } | |
</div> | |
</div> | |
</div> | |
</div> | |
); | |
} | |
} |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment