Skip to content

Instantly share code, notes, and snippets.

@richard-to
Created June 30, 2015 20:07
Show Gist options
  • Save richard-to/74443e2f6f10159516f6 to your computer and use it in GitHub Desktop.
Save richard-to/74443e2f6f10159516f6 to your computer and use it in GitHub Desktop.
Random code
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')
);
<!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