JSFiddle - React, Tailwind, and code Playground
by tonyleeper
HTML
<div class="calendar">
<button class="today" data-bind="text: resources['Today'],
click: gotoToday"></button>
<div class="month">
<button class="previous" data-bind="click: gotoPreviousMonth"><</button>
<span data-bind="text: resources['Month.' + month()]"></span>
<button class="next" data-bind="click: gotoNextMonth">></button>
</div>
<div class="year">
<button class="previous" data-bind="click: gotoPreviousYear"><</button>
<span data-bind="text: year()"></span>
<button class="next" data-bind="click: gotoNextYear">></button>
</div>
<div class="weekdays">
<div class="row">
<div class="cell">MON</div>
<div class="cell">TUE</div>
<div class="cell">WED</div>
<div class="cell">THU</div>
<div class="cell">FRI</div>
<div class="cell">SAT</div>
<div class="cell">SUN</div>
</div>
</div>
<div class="dates" data-bind="foreach: weeks">
<div class="row" data-bind="foreach: dates">
<div class="cell" data-bind="text: $data.date === 1 ? resources['Month.' + $data.month] + ' ' + $data.date : $data.date, css: { 'current-month': $data.month === $root.month(), 'today': $data.date === $root.today().getDate() && $data.month === $root.today().getMonth() && $root.today().getFullYear() === $root.year() }"></div>
</div>
</div>
</div>
CSS
html, body {
width: 95%;
height: 95%;
margin: 0;
padding: 0;
}
.calendar {
text-align: center;
cursor: default;
-webkit-user-select: none;
height: 100%;
width: 100%;
min-height: 100px;
min-width: 100px;
}
.year, .month {
display: inline-block;
}
.year span, .month span {
display: inline-block;
width: 100px;
}
.weekdays {
display: table;
table-layout: fixed;
width: 100%;
border-top: 1px solid lightgray;
border-left: 1px solid lightgray;
}
.dates {
display: table;
table-layout: fixed;
width: 100%;
height: 100%;
border-left: 1px solid lightgray;
}
.row {
display: table-row;
}
.cell {
white-space: nowrap;
height: 16%;
display: table-cell;
overflow: hidden;
border-right: 1px solid lightgray;
border-bottom: 1px solid lightgray;
}
.dates .cell {
outline: 0;
text-align: right;
color: lightgray;
}
.dates .cell.current-month {
color: black;
}
.dates .cell.today {
background-color: lightblue;
}
.weekdays .cell {
height: 20px;
text-align: center;
}
/*.cell:active, .cell.focus {
background-color: darkblue;
color: white;
}*/
JavaScript
/**
calendar view concept
*/
var CalendarViewModel = function () {
var self = this;
self.today = ko.observable(new Date());
self.date = ko.observable(self.today().getDate());
self.month = ko.observable(self.today().getMonth());
self.year = ko.observable(self.today().getFullYear());
self.getFirstDayOfMonth = function () {
var firstOfMonth = new Date(self.year(), self.month(), 1);
var jsDay = firstOfMonth.getDay();
return jsDay === 0 ? 6 : jsDay - 1; // convert from sun (0) - sat (6) to mon (0) - sun (6)
};
self.getNumberOfDaysInMonth = function (month) {
var lastOfMonth = new Date(2013, month + 1, 0);
return lastOfMonth.getDate();
};
self.weekCount = function () {
return Math.ceil((self.getFirstDayOfMonth() + self.getNumberOfDaysInMonth(self.month())) / 7);
};
self.weeks = ko.computed(function () {
var weeks = [];
var firstWeek = {
dates: []
};
// fill in the correct dates for this month
var date = 1;
var month = self.month();
var firstDayOfMonth = self.getFirstDayOfMonth();
var previousMonth = self.month() === 0 ? 11 : self.month() - 1;
var daysInPreviousMonth = self.getNumberOfDaysInMonth(previousMonth);
firstWeek.dates[firstDayOfMonth] = {
date: date++,
month: month
};
for (var i = firstDayOfMonth - 1; i >= 0; i--) {
firstWeek.dates[i] = {
date: daysInPreviousMonth--,
month: previousMonth
};
}
for (var i = firstDayOfMonth + 1; i < 7; i++) {
firstWeek.dates[i] = {
date: date++,
month: month
};
}
// add the first week
weeks.push(firstWeek);
// add the remaining weeks
var daysInMonth =...