
サイト構築の際に、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 件のコメント:
コメントを投稿