Created
June 30, 2015 20:07
-
-
Save richard-to/74443e2f6f10159516f6 to your computer and use it in GitHub Desktop.
Random code
This file contains 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
var CalendarViewType = { | |
CALENDAR: 1, | |
MONTH: 2, | |
YEAR: 3 | |
}; | |
var DAYS_IN_WEEK = 7; | |
var MONTHS_IN_YEAR = 12; | |
var MONTHS = [ | |
'January', 'February', 'March', 'April', 'May', | |
'June', 'July', 'August', 'September', 'October', | |
'November', 'December' | |
]; | |
var MONTHS_ABBREVIATED = [ | |
'Jan', 'Feb', 'Mar', 'Apr', 'May', | |
'Jun', 'Jul', 'Aug', 'Sep', 'Oct', | |
'Nov', 'Dec' | |
]; | |
var DAYS_OF_WEEK = ['Su', 'Mo', 'Tu', 'We', 'Th', 'Fr', 'Sa']; | |
var getFirstOfMonthDate = function(dt) { | |
var dtStart = new Date(dt.getTime()); | |
dtStart.setDate(1); | |
return dtStart; | |
}; | |
var getLastOfMonthDate = function(dt) { | |
var dtEnd = new Date(dt.getTime()); | |
dtEnd.setDate(1); | |
dtEnd.setMonth(dtEnd.getMonth() + 1); | |
dtEnd.setDate(dtEnd.getDate() - 1); | |
return dtEnd; | |
}; | |
var getEndOfLastMonthDate = function(dt) { | |
var dtLast = getFirstOfMonthDate(dt); | |
dtLast.setDate(dtLast.getDate() - 1); | |
return dtLast; | |
} | |
var generateCalendar = function(dt) { | |
var dtStart = getFirstOfMonthDate(dt); | |
var dtEnd = getLastOfMonthDate(dt); | |
var dtEndLastMonth = getEndOfLastMonthDate(dt); | |
var calendar = [ | |
_.range( | |
dtEndLastMonth.getDate() + 1 - dtStart.getDay(), | |
dtEndLastMonth.getDate() + 1 | |
).concat( | |
_.range(1, DAYS_IN_WEEK - dtStart.getDay() + 1) | |
) | |
]; | |
var dayCount = calendar[0][DAYS_IN_WEEK - 1] + 1; | |
while (dayCount <= dtEnd.getDate() - DAYS_IN_WEEK) { | |
var endDay = dayCount + DAYS_IN_WEEK; | |
calendar.push(_.range(dayCount, endDay)); | |
dayCount = endDay; | |
} | |
calendar.push( | |
_.range( | |
dayCount, dtEnd.getDate() + 1 | |
).concat( | |
_.range(1, DAYS_IN_WEEK - dtEnd.getDay()) | |
) | |
); | |
return calendar; | |
}; | |
var CalendarHeader = React.createClass({ | |
render: function() { | |
return ( | |
<div> | |
<button onClick={this.handleClickPrev}>Prev</button> | |
<span onClick={this.handleClickHeader}>{this.props.title}</span> | |
<button onClick={this.handleClickNext}>Next</button> | |
</div> | |
); | |
}, | |
handleClickPrev: function() { | |
if (this.props.onClickPrev) { | |
this.props.onClickPrev(); | |
} | |
}, | |
handleClickNext: function() { | |
if (this.props.onClickNext) { | |
this.props.onClickNext(); | |
} | |
}, | |
handleClickHeader: function() { | |
if (this.props.onClickHeader) { | |
this.props.onClickHeader(); | |
} | |
} | |
}); | |
var YearGrid = React.createClass({ | |
COLS_PER_ROW: 5, | |
render: function() { | |
var yearGrid = _.range( | |
this.props.startYear, this.props.startYear + this.props.range, this.COLS_PER_ROW | |
).map(function(startYear) { | |
return <tr key={"year-row-" + startYear}>{this.renderRow(startYear, startYear + this.COLS_PER_ROW)}</tr>; | |
}.bind(this)); | |
}, | |
renderRow: function(startYear, endYear) { | |
return _.range(startYear, endYear).map(function(year) { | |
return ( | |
<td | |
onClick={this.handleClickYearWrapper(year)} | |
key={"year-" + year}>{year}</td> | |
) | |
}.bind(this)); | |
}, | |
handleClickYearWrapper: function(year) { | |
return function() { | |
this.handleClickYear(year) | |
}.bind(this); | |
}, | |
handleClickYear: function(year) { | |
if (this.props.onClickYear) { | |
this.props.onClickYear(year); | |
} | |
} | |
}); | |
var YearView = React.createClass({ | |
YEAR_RANGE: 20, | |
getInitialState: function() { | |
return { | |
selectedDate: this.props.selectedDate, | |
viewingMonth: this.props.viewingMonth, | |
startYear: this.props.viewingYear - (this.props.viewingYear % this.YEAR_RANGE) | |
}; | |
}, | |
render: function() { | |
return ( | |
<div className="month-view"> | |
<CalendarHeader | |
title={this.state.viewingYear} | |
onClickPrev={this.handleClickPrev} | |
onClickNext={this.handleClickNext} | |
/> | |
<YearGrid | |
onClickYear={this.handleClickYear} | |
startYear={this.state.startYear} | |
yearRange={this.YEAR_RANGE} /> | |
</div> | |
); | |
}, | |
handleClickPrev: function() { | |
this.setState({ viewingYear: this.state.viewingYear - this.YEAR_RANGE }); | |
}, | |
handleClickNext: function() { | |
this.setState({ viewingYear: this.state.viewingYear + this.YEAR_RANGE }); | |
}, | |
handleClickYear: function(year) { | |
if (this.props.onClickYear) { | |
this.props.onClickYear(month, year); | |
} | |
} | |
}); | |
var MonthGrid = React.createClass({ | |
COLS_PER_ROW: 3, | |
render: function() { | |
var monthGrid = _.range(0, MONTHS.length, this.COLS_PER_ROW).map(function(startCol) { | |
return <tr key={"month-row-" + startCol}>{this.renderRow(startCol, startCol + this.COLS_PER_ROW)}</tr>; | |
}.bind(this)); | |
return <table><tbody>{monthGrid}</tbody></table>; | |
}, | |
renderRow: function(startCol, endCol) { | |
return _.range(startCol, endCol).map(function(monthIndex) { | |
return ( | |
<td | |
onClick={this.handleClickMonthWrapper(monthIndex)} | |
key={"month-" + monthIndex}>{MONTHS_ABBREVIATED[monthIndex]}</td> | |
) | |
}.bind(this)); | |
}, | |
handleClickMonthWrapper: function(monthIndex) { | |
return function() { | |
this.handleClickMonth(monthIndex) | |
}.bind(this); | |
}, | |
handleClickMonth: function(monthIndex) { | |
if (this.props.onClickMonth) { | |
this.props.onClickMonth(monthIndex); | |
} | |
} | |
}); | |
var MonthView = React.createClass({ | |
getInitialState: function() { | |
return { | |
selectedDate: this.props.selectedDate, | |
viewingMonth: this.props.viewingMonth, | |
viewingYear: this.props.viewingYear | |
}; | |
}, | |
render: function() { | |
return ( | |
<div className="month-view"> | |
<CalendarHeader | |
title={this.state.viewingYear} | |
onClickPrev={this.handleClickPrev} | |
onClickNext={this.handleClickNext} | |
onClickHeader={this.handleClickHeader} | |
/> | |
<MonthGrid | |
onClickMonth={this.handleClickMonth} | |
month={this.state.viewingMonth} | |
year={this.state.viewingYear} /> | |
</div> | |
); | |
}, | |
handleClickPrev: function() { | |
this.setState({viewingYear: this.state.viewingYear - 1}); | |
}, | |
handleClickNext: function() { | |
this.setState({viewingYear: this.state.viewingYear + 1}); | |
}, | |
handleClickHeader: function() { | |
if (this.props.onClickHeader) { | |
this.props.onClickHeader(this.state.viewingMonth, this.state.viewingYear); | |
} | |
}, | |
handleClickMonth: function(month) { | |
if (this.props.onClickMonth) { | |
this.props.onClickMonth(month, this.state.viewingYear); | |
} | |
} | |
}); | |
var DayOfWeekRow = React.createClass({ | |
render: function() { | |
var daysRow = DAYS_OF_WEEK.map(function(day) { | |
return <th key={day}>{day}</th>; | |
}); | |
return <tr>{daysRow}</tr>; | |
} | |
}); | |
var CalendarGrid = React.createClass({ | |
render: function() { | |
var dt = new Date(this.props.year, this.props.month, 1); | |
var calendar = generateCalendar(dt); | |
var calendarRows = calendar.map(function(row, index) { | |
return <tr key={"c-row-" + index}>{this.renderRow(row, index)}</tr>; | |
}.bind(this)); | |
return <table><thead><DayOfWeekRow /></thead><tbody>{calendarRows}</tbody></table>; | |
}, | |
renderRow: function(row, rowIndex) { | |
return row.map(function(day) { | |
return <td key={"c-row-" + rowIndex + "-day-" + day}>{day}</td>; | |
}); | |
} | |
}); | |
var CalendarView = React.createClass({ | |
getInitialState: function() { | |
return { | |
selectedDate: this.props.selectedDate, | |
viewingMonth: this.props.viewingMonth, | |
viewingYear: this.props.viewingYear | |
}; | |
}, | |
render: function() { | |
return ( | |
<div className="calendar-view"> | |
<CalendarHeader | |
title={MONTHS[this.state.viewingMonth] + " " + this.state.viewingYear} | |
onClickPrev={this.handleClickPrev} | |
onClickNext={this.handleClickNext} | |
onClickHeader={this.handleClickHeader} | |
/> | |
<CalendarGrid month={this.state.viewingMonth} year={this.state.viewingYear} /> | |
</div> | |
); | |
}, | |
handleClickPrev: function() { | |
var updatedMonth = this.state.viewingMonth - 1; | |
var updatedYear = this.state.viewingYear; | |
if (updatedMonth === -1) { | |
updatedMonth = MONTHS_IN_YEAR - 1; | |
updatedYear -= 1; | |
} | |
this.setState({viewingMonth: updatedMonth, viewingYear: updatedYear}); | |
}, | |
handleClickNext: function() { | |
var updatedMonth = this.state.viewingMonth + 1; | |
var updatedYear = this.state.viewingYear; | |
if (updatedMonth === MONTHS_IN_YEAR) { | |
updatedMonth %= MONTHS_IN_YEAR; | |
updatedYear += 1; | |
} | |
this.setState({viewingMonth: updatedMonth, viewingYear: updatedYear}); | |
}, | |
handleClickHeader: function() { | |
if (this.props.onClickHeader) { | |
this.props.onClickHeader(this.state.viewingMonth, this.state.viewingYear); | |
} | |
} | |
}); | |
var CalendarWidget = React.createClass({ | |
getInitialState: function() { | |
var today = new Date(); | |
return { | |
selectedDate: today, | |
viewingMonth: today.getMonth(), | |
viewingYear: today.getFullYear(), | |
view: CalendarViewType.CALENDAR | |
}; | |
}, | |
render: function() { | |
var calendarView = null; | |
if (this.state.view === CalendarViewType.CALENDAR) { | |
calendarView = ( | |
<CalendarView | |
selectedDate={this.state.selectedDate} | |
viewingMonth={this.state.viewingMonth} | |
viewingYear={this.state.viewingYear} | |
onClickHeader={this.showMonthView} /> | |
); | |
} else if (this.state.view === CalendarViewType.MONTH) { | |
calendarView = ( | |
<MonthView | |
selectedDate={this.state.selectedDate} | |
viewingMonth={this.state.viewingMonth} | |
viewingYear={this.state.viewingYear} | |
onClickHeader={this.showYearView} | |
onClickMonth={this.showCalendarView} /> | |
); | |
} else if (this.state.view === CalendarViewType.YEAR) { | |
calendarView = ( | |
<YearView | |
selectedDate={this.state.selectedDate} | |
viewingMonth={this.state.viewingMonth} | |
viewingYear={this.state.viewingYear} | |
onClickYear={this.showMonthView} /> | |
); | |
} | |
return <div className="calendar-widget">{calendarView}</div> | |
}, | |
updateDate: function(day, month, year) { | |
}, | |
showCalendarView: function(month, year) { | |
this.setState({view: CalendarViewType.CALENDAR, viewingMonth: month, viewingYear: year}); | |
}, | |
showMonthView: function(month, year) { | |
this.setState({view: CalendarViewType.MONTH, viewingMonth: month, viewingYear: year}); | |
}, | |
showYearView: function(month, year) { | |
this.setState({view: CalendarViewType.YEAR, viewingMonth: month, viewingYear: year}); | |
} | |
}); | |
React.render( | |
<CalendarWidget />, | |
document.getElementById('calendar') | |
); |
This file contains 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
<!doctype html> | |
<html> | |
<head> | |
<meta charset="utf-8"> | |
<meta http-equiv="X-UA-Compatible" content="IE=edge"> | |
<title>Calendar Widget</title> | |
<meta name="description" content=""> | |
<meta name="viewport" content="width=device-width, initial-scale=1"> | |
</head> | |
<body> | |
<div id="calendar"></div> | |
<script src="http://cdnjs.cloudflare.com/ajax/libs/lodash.js/2.4.1/lodash.min.js"></script> | |
<script src="http://fb.me/react-with-addons-0.12.2.js"></script> | |
<script src="http://fb.me/JSXTransformer-0.12.2.js"></script> | |
<script type="text/jsx" src="/calendar.js"></script> | |
</body> | |
</html> |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment