ryoakg
7/1/2016 - 11:58 AM

js-calender.html

<!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>