<!DOCTYPE html>
<html lang="ja">
<head>
<meta charset="utf-8">
<title>calendar.js</title>
<style type="text/css">
.calendar {
font-family:"Verdana", sans-serif;
}
.calendar__pager {
position:relative;
margin-bottom:8px;
}
.calendar__pager__current-month,
.calendar__pager__arrow {
display:block;
padding:3px;
}
.calendar__pager__current-month {
text-align:center;
}
.calendar__pager__arrow {
position:absolute;
background:#eee;
font-weight:bold;
top:0px;
border-radius:4px;
cursor:pointer;
}
.calendar__pager__arrow:hover{ color:#f0f; }
.calendar__pager__next-month{ right:4px; }
.calendar__pager__next-month::before{ content:'→'; }
.calendar__pager__prev-month{ left:4px; }
.calendar__pager__prev-month::before{ content:'←'; }
.calendar__date-cell {
border:1px solid #ddd;
text-align:right;
-moz-border-radius:3px;
border-radius:3px;
}
.calendar__date-cell.AVAILABLE {
cursor:pointer;
padding:2px;
/* default values may be overriden */
background:#eee;
color: #333;
}
.calendar__date-cell.AVAILABLE:hover { color:#f0f; }
.calendar__date-cell.SUNDAY { background:#fdd; }
.calendar__date-cell.SATURDAY { background:#def; }
.calendar__dow-header {
font-weight:normal;
font-size:90%;
}
.calendar__dow-header.SUNDAY { color:red; }
.calendar__dow-header.SATURDAY { color:blue; }
</style>
</head>
<body>
<div id="calendar-holder1"></div>
<input id="picked-date" type="text" readonly>
<hr />
<div id="calendar-holder2"></div>
<script>
(function(){
function make_pager(date){
var y = date.getFullYear();
var m = date.getMonth();
var next = document.createElement('div');
next.dataset.calendarMonth = JSON.stringify(new Date(y, m+1));
next.classList.add('calendar__pager__arrow');
next.classList.add('calendar__pager__next-month');
var prev = document.createElement('div');
prev.dataset.calendarMonth = JSON.stringify(new Date(y, m-1));
prev.classList.add('calendar__pager__arrow');
prev.classList.add('calendar__pager__prev-month');
var current = document.createElement('span');
current.classList.add('calendar__pager__current-month');
current.appendChild(document.createTextNode(y + '/' + (m+1)));
var caption = document.createElement('caption');
caption.classList.add('calendar__pager');
caption.appendChild(prev);
caption.appendChild(current);
caption.appendChild(next);
return caption;
}
function make_tr_day_of_the_week(days){
var tr = document.createElement('tr');
days.forEach(function(day,i){
var th = document.createElement('th');
th.appendChild(document.createTextNode(day));
th.classList.add('calendar__dow-header');
if (i === 0) th.classList.add('SUNDAY');
if (i === 6) th.classList.add('SATURDAY');
tr.appendChild(th);
});
return tr;
}
var tr_day_of_the_week = make_tr_day_of_the_week(['日', '月', '火', '水', '木', '金', '土']);
var blank_cell = (function(){
var td = document.createElement('td');
td.classList.add('calendar__date-cell');
td.classList.add('UNAVAILABLE');
return td;
})();
function date_cell(date){
var td = document.createElement('td');
td.appendChild(document.createTextNode(date.getDate()));
td.classList.add('calendar__date-cell');
td.classList.add('AVAILABLE');
var dow = date.getDay();
if (dow === 0) td.classList.add('SUNDAY');
if (dow === 6) td.classList.add('SATURDAY');
td.dataset.calendarDate = JSON.stringify(date)
return td;
}
function tr_week(ds){
var tr = document.createElement('tr');
ds.forEach(function(d){ tr.appendChild(d); });
return tr;
}
function make_tbody(date){
var year = date.getFullYear();
var month = date.getMonth();
var first = new Date(year, month, 1);
var last = new Date(year, month+1, 0);
var i;
var ds = [];
for (i = 0; i < first.getDay(); i++)
ds.push(blank_cell.cloneNode(true));
for (var d = new Date(year, month, 1); d <= last; d.setDate(d.getDate()+1))
ds.push(date_cell(d));
for (i = 0; i < 6 - last.getDay(); i++)
ds.push(blank_cell.cloneNode(true));
var tbody = document.createElement('tbody');
/* .cloneNode(true) で deep copy しないと上手くいかない */
tbody.appendChild(tr_day_of_the_week.cloneNode(true));
while (ds.length !== 0)
tbody.appendChild(tr_week(ds.splice(0,7)));
return tbody;
}
function make_calendar(date){
var table = document.createElement('table');
table.className = 'calendar';
table.appendChild(make_pager(date));
table.appendChild(make_tbody(date));
return table;
}
function mount_calendar(elm, on_date_selected, date){
var calendar = make_calendar(date);
function onclick(e){
var evt = e || window.event;
var target = evt.target || evt.srcElement;
if (target.dataset.calendarDate) {
on_date_selected(new Date(JSON.parse(target.dataset.calendarDate)));
return;
}
if (target.dataset.calendarMonth) {
elm.removeChild(calendar);
mount_calendar(elm, on_date_selected,
new Date(JSON.parse(target.dataset.calendarMonth)));
return;
}
};
calendar.onclick = onclick;
elm.appendChild(calendar);
}
window.mount_calendar = mount_calendar;
})();
</script>
<script>
(function(){
var picked = document.getElementById('picked-date');
mount_calendar(document.getElementById('calendar-holder1'),
function(date){
picked.value = date.getFullYear() +'/'+ (date.getMonth()+1) +'/'+ date.getDate();
},
new Date());
mount_calendar(document.getElementById('calendar-holder2'), alert, new Date());
})();
</script>
</body>
</html>