サイト構築の際に、javascriptでカレンダーを作成する事があったので、ソースコードを載せておきます。
システム構築の際にカレンダーライブラリがあると非常に便利なんですが、OSSライブラリを使うよりも、この程度のカレンダーであれば、自分で書いたほうが早かったので、作っただけです。
結果、他の人には分かりにくい事には変わりませんが、全く同じ仕様でよければ、コピペでできるスニペットって有難くないですか?
ソースコード
;(function(){
var $$ = function(){
$$LIB.prototype.setEvent(window, "load", $$.prototype.start);
};
$$.prototype.start = function(){
if(document.querySelector($$CALENDAR.prototype.option.table) === null){return;}
var d = $$.prototype.getUrlDate();
var data = (d === null)?{}:{date:{year:d.y,month:d.m,day:d.d}};
new $$CALENDAR(data);
};
$$.prototype.getUrlDate = function(){
var url = $$LIB.prototype.urlinfo();
if(typeof url.query.date !== "undefined"){
return {
y:url.query.date.substr(0,4),
m:url.query.date.substr(4,2),
d:url.query.date.substr(6,2)
};
}
else{
return null;
}
};
$$CALENDAR = function(option){
this.setOption(option);
this.option.calendar = document.querySelector(this.option.table);
this.setYM(this.option.date);
this.setDate();
this.setEvent();
};
$$CALENDAR.prototype.option = {
calendar : null,
table : ".calendar-table",
year : ".calendar-year",
month : ".calendar-month",
head : ".calendar-head",
title : ".calendar-title",
week : ".calendar-week",
body : ".calendar-body",
prev : ".calendar-table .calendar-title .prev",
next : ".calendar-table .calendar-title .next",
date : {
year : null,
month : null,
day : null
},
click : function(){},
$EOL:0
};
$$CALENDAR.prototype.setOption = function(option){
for(var i in option){
this.option[i] = option[i];
}
};
$$CALENDAR.prototype.setYM = function(date){
// alert(year+"/"+month);
var d = new Date();
date.year = (date.year === null)?d.getFullYear():date.year;
date.month = (date.month === null)?d.getMonth()+1 :date.month;
date.day = (date.day === null)?d.getDate() :date.day;
// this.option.date = {year:year.textContent , month:month.textContent , day:d.getDate()};
this.option.calendar.querySelector(this.option.year).innerHTML = date.year;
this.option.calendar.querySelector(this.option.month).innerHTML = date.month;
return this.option.date;
};
$$CALENDAR.prototype.getYM = function(){
var y = $$CALENDAR.prototype.option.calendar.querySelector($$CALENDAR.prototype.option.year).textContent;
var m = $$CALENDAR.prototype.option.calendar.querySelector($$CALENDAR.prototype.option.month).textContent;
return {year:Number(y) , month:Number(m)};
};
$$CALENDAR.prototype.setDate = function(){
var d = new Date();
var year = this.option.date.year;
var month = this.option.date.month;
var day = this.option.date.day;
var startDay = new Date(year, month-1, 1).getDay();// その月の最初の日の曜日を取得
var endDay = new Date(year, month , 0).getDay();// その月の最後の日の曜日を取得
var endDate = new Date(year, month , 0).getDate();
var textDate = 1; // 日付(これがカウントアップされます)
var html =''; // テーブルのHTMLを格納する変数
for (var row = 0; row < (endDate + startDay + (7-endDay-1))/7; row++){
html += '<tr>';
for (var col = 0; col < 7; col++) {
if (row === 0 && col < startDay){
html += "<td class='nil'> </td>";
}
else if (endDate < textDate) {
html += "<td class='nil'> </td>";
}
else{
var cls = (day == textDate)?"current":"date";
cls = (new Date(year, month-1, textDate) > new Date(d.getFullYear(), d.getMonth(), d.getDate()))?"over":cls;
html += '<td class="'+cls+'">'+textDate+'</td>';
textDate++;
}
}
html += '</tr>';
}
this.option.calendar.querySelector(this.option.body).innerHTML = html;
};
$$CALENDAR.prototype.setEvent = function(){
// month-move
var prev = document.querySelector(this.option.prev);
var next = document.querySelector(this.option.next);
$$LIB.prototype.setEvent(prev, "click", $$CALENDAR.prototype.prevCalendar);
$$LIB.prototype.setEvent(next, "click", $$CALENDAR.prototype.nextCalendar);
// day-click
var days = this.option.calendar.querySelectorAll(".date");
for(var i=0; i<days.length; i++){
$$LIB.prototype.setEvent(days[i], "click", $$CALENDAR.prototype.dayClick);
}
};
$$CALENDAR.prototype.prevCalendar = function(){
var d = $$CALENDAR.prototype.getYM();
var y = d.year;
var m = d.month+1;
if(m === 0){
y -= 1;
m = 12;
}
new $$CALENDAR({date:{year:d.year,month:(d.month-1),day:1}});
};
$$CALENDAR.prototype.nextCalendar = function(){
var d = $$CALENDAR.prototype.getYM();
var y = d.year;
var m = d.month+1;
if(m === 13){
y += 1;
m = 1;
}
new $$CALENDAR({date:{year:y,month:m,day:1}});
};
$$CALENDAR.prototype.dayClick = function(e){
var elm = e.target;
var y = $$CALENDAR.prototype.option.date.year;
var m = $$CALENDAR.prototype.numKeta($$CALENDAR.prototype.option.date.month);
var d = $$CALENDAR.prototype.numKeta(elm.textContent);
console.log(y+"/"+m+"/"+d);
var url = $$LIB.prototype.urlinfo();
var newQuery = [];
for(var i in url.query){
if(i === "date"){continue;}
newQuery.push(i+"="+url.query[i]);
}
newQuery.push("date="+y+m+d);
location.href = url.url+"?"+newQuery.join("&");
}
$$CALENDAR.prototype.numKeta = function(num){
num = Number(num);
if(num < 10){
return "0" + num.toString();
}
else{
return num;
}
};
/* Library */
var $$LIB = function(){};
$$LIB.prototype.urlinfo = function(uri){
if(!uri){uri = location.href;}
var data={};
//URLとクエリ分離分解;
var query=[];
if(uri.indexOf("?")!=-1){query = uri.split("?")}
else if(uri.indexOf(";")!=-1){query = uri.split(";")}
else{
query[0] = uri;
query[1] = '';
}
//基本情報取得;
var sp = query[0].split("/");
var data={
url:query[0],
dir:$$LIB.prototype.pathinfo(uri).dirname,
domain:sp[2],
protocol:sp[0].replace(":",""),
query:(query[1])?(function(q){
var data=[];
var sp = q.split("&");
for(var i=0;i<sp .length;i++){
var kv = sp[i].split("=");
if(!kv[0]){continue}
data[kv[0]]=kv[1];
}
return data;
})(query[1]):[],
};
return data;
};
$$LIB.prototype.pathinfo = function(p){
var basename="",
dirname=[],
filename=[],
ext="";
var p2 = p.split("?");
var urls = p2[0].split("/");
for(var i=0; i<urls.length-1; i++){
dirname.push(urls[i]);
}
basename = urls[urls.length-1];
var basenames = basename.split(".");
for(var i=0;i<basenames.length-1;i++){
filename.push(basenames[i]);
}
ext = basenames[basenames.length-1];
return {
"hostname":urls[2],
"basename":basename,
"dirname":dirname.join("/"),
"filename":filename.join("."),
"extension":ext,
"query":(p2[1])?p2[1]:"",
"path":p2[0]
};
};
//ハイフン区切りを大文字に変換する。
$$LIB.prototype.camelize = function(v){
if(typeof(v)!='string'){return}
return v.replace(/-([a-z])/g , function(m){return m.charAt(1).toUpperCase();});
};
// URL切り替え処理 [key , value , flg(before,*after)]
$$LIB.prototype.setUrl = function(key,val,flg){
var urlinfo = $$LIB.prototype.urlinfo();
var query = [];
if(flg==="before"){
query.push(key + "=" + val);
}
for(var i in urlinfo.query){
if(i !== key){
query.push(i + "=" + urlinfo.query[i]);
}
}
if(flg!=="before"){
query.push(key + "=" + val);
}
history.pushState(null,null,urlinfo.url+"?"+query.join("&"));
};
$$LIB.prototype.number_format = function(num){
num = num.toString();
var tmpStr = "";
while (num != (tmpStr = num.replace(/^([+-]?\d+)(\d\d\d)/,"$1,$2"))){num = tmpStr;}
return num;
};
$$LIB.prototype.setEvent = function(target, mode, func){
//other Browser
if (typeof target.addEventListener !== "undefined"){
target.addEventListener(mode, func, false);
}
else if(typeof target.attachEvent !== "undefined"){
target.attachEvent('on' + mode, function(){func.call(target , window.event)});
}
else{
console.log(target);
console.log("[warning] "+target);
}
};
window.$$CALENDAR = $$CALENDAR;
new $$;
})();
.calendar-table{
margin:8px;
/*display:none;*/
}
.calendar-table .calendar-head .calendar-title{
text-align:center;
}
.calendar-table .calendar-head .calendar-week{
background-color:#EEE;
}
.calendar-table th,
.calendar-table td{
width:40px;
height:24px;
border:1px solid #DDD;
padding:2px 8px;
font-size:12px;
text-align:center;
cursor:pointer;
user-select: none;
}
.calendar-table .calendar-body td.date:hover{
background-color:#FFC;
font-weight:bold;
}
.calendar-table .calendar-body td.current{
background-color:#FEE;
}
.calendar-table .calendar-body td.nil{
background-color:#EEE;
}
.calendar-table .calendar-body td.over{
color:#CCC;
}
.calendar-table .calendar-title{
position:relative;
}
.calendar-table .calendar-title .prev,
.calendar-table .calendar-title .next{
width:40px;
position:absolute;
display:inline-block;
cursor:pointer;
}
.calendar-table .calendar-title .prev:hover,
.calendar-table .calendar-title .next:hover{
background-color:#FFC;
}
.calendar-table .calendar-title .prev{
left:0;
}
.calendar-table .calendar-title .next{
right:0;
}
使い方
事前に上記ライブラリを読み込んで、下記タグ構造をページに記載すると、カレンダーが現れるようになります。
<div class="calendar">
<table class="calendar-table">
<thead class="calendar-head">
<tr>
<th class="calendar-title" colspan="7">
<span class="prev"><<</span>
<span class="calendar-year"></span> 年
<span class="calendar-month"></span> 月
<span class="next">>></span>
</th>
</tr>
<tr class="calendar-week">
<th>日</th>
<th>月</th>
<th>火</th>
<th>水</th>
<th>木</th>
<th>金</th>
<th>土</th>
</tr>
</thead>
<tbody class="calendar-body"></tbody>
</table>
</div>
<script src="lib/js/calendar/calendar.js"></script>
<link rel="stylesheet" href="lib/js/calendar/calendar.css" />
<script>
new $$CALENDAR({});
</script>
解説
HTMLタグのclass名などを基準にコーディングしているので、HTMLのタグ箇所は変更しないでご使用ください。
デザインに関しては、CSSファイルを変更するのは、問題なさそうなので、現状を壊さないように、カラーリングなどを変更してください。
とりあえず、機能としては、「月の移動」「当日のカラーリング」ぐらいを用意しているので、日付切り替えで、inputタグのtype=dateを使うよりは便利なはずです。
ついでに、スマホで使うことも考慮しているので、便利に使えるはずです。
日付箇所をクリックした際のイベントについては、JSコードの「$$CALENDAR.prototype.dayClick」関数を書き換えれば、それだけで挙動するはずです。
ちなみに、今回のコピペで行った場合は、「date=YYYYMMDD」クエリを付けてURL遷移するようになります。
後は、煮るなり焼くなり、自己責任にてお願いいたします。
尚、要望などがあれば、コメントで受け付けます。
0 件のコメント:
コメントを投稿