www/common/calendar.js

Code
Comments
Other
Rev Date Author Line
7604 25 Feb 19 nicklas 1 /* $Id $
7604 25 Feb 19 nicklas 2   ------------------------------------------------------------------
7604 25 Feb 19 nicklas 3   Copyright (C) 2012 Nicklas Nordborg
7604 25 Feb 19 nicklas 4
7604 25 Feb 19 nicklas 5   This file is part of BASE - BioArray Software Environment.
7604 25 Feb 19 nicklas 6   Available at http://base.thep.lu.se/
7604 25 Feb 19 nicklas 7
7604 25 Feb 19 nicklas 8   BASE is free software; you can redistribute it and/or
7604 25 Feb 19 nicklas 9   modify it under the terms of the GNU General Public License
7604 25 Feb 19 nicklas 10   as published by the Free Software Foundation; either version 3
7604 25 Feb 19 nicklas 11   of the License, or (at your option) any later version.
7604 25 Feb 19 nicklas 12
7604 25 Feb 19 nicklas 13   BASE is distributed in the hope that it will be useful,
7604 25 Feb 19 nicklas 14   but WITHOUT ANY WARRANTY; without even the implied warranty of
7604 25 Feb 19 nicklas 15   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
7604 25 Feb 19 nicklas 16   GNU General Public License for more details.
7604 25 Feb 19 nicklas 17
7604 25 Feb 19 nicklas 18   You should have received a copy of the GNU General Public License
7604 25 Feb 19 nicklas 19   along with BASE. If not, see <http://www.gnu.org/licenses/>.
7604 25 Feb 19 nicklas 20   ------------------------------------------------------------------
7604 25 Feb 19 nicklas 21
7604 25 Feb 19 nicklas 22   @author Nicklas
7604 25 Feb 19 nicklas 23 */
7604 25 Feb 19 nicklas 24 'use strict';
7604 25 Feb 19 nicklas 25
7604 25 Feb 19 nicklas 26 var Calendar = function()
7604 25 Feb 19 nicklas 27 {
7604 25 Feb 19 nicklas 28   var dateField;
7604 25 Feb 19 nicklas 29   var dateFormat;
7604 25 Feb 19 nicklas 30   var useTime;
7604 25 Feb 19 nicklas 31   var currentDate;
7604 25 Feb 19 nicklas 32   var calendarYear;
7604 25 Feb 19 nicklas 33   var calendarMonth;
7604 25 Feb 19 nicklas 34   
7604 25 Feb 19 nicklas 35   var calendar = {};
7604 25 Feb 19 nicklas 36   calendar.MONTHS = ['January', 'February', 'March', 'April', 'May', 'June', 
7604 25 Feb 19 nicklas 37                      'July', 'August', 'September', 'October', 'November', 'December'];
7604 25 Feb 19 nicklas 38   
7604 25 Feb 19 nicklas 39   calendar.initPage = function()
7604 25 Feb 19 nicklas 40   {
7604 25 Feb 19 nicklas 41     // Dialog buttons
7604 25 Feb 19 nicklas 42     Buttons.addClickHandler('close', App.closeWindow);
7604 25 Feb 19 nicklas 43     Buttons.addClickHandler('btnSave', Calendar.save);
7604 25 Feb 19 nicklas 44     Buttons.addClickHandler('btnToday', Calendar.setToday);
7604 25 Feb 19 nicklas 45     
7604 25 Feb 19 nicklas 46     // Next and previous month
7604 25 Feb 19 nicklas 47     Buttons.addClickHandler('nextMonth', calendar.nextMonth);
7604 25 Feb 19 nicklas 48     Buttons.addClickHandler('prevMonth', calendar.prevMonth);
7604 25 Feb 19 nicklas 49     
7604 25 Feb 19 nicklas 50     // Time controls
7604 25 Feb 19 nicklas 51     Events.addEventHandler('hours', 'keypress', Events.integerOnly);
7604 25 Feb 19 nicklas 52     Events.addEventHandler('minutes', 'keypress', Events.integerOnly);
7604 25 Feb 19 nicklas 53     Events.addEventHandler('seconds', 'keypress', Events.integerOnly);
7604 25 Feb 19 nicklas 54     
7604 25 Feb 19 nicklas 55     // Each day in the calendar; 6 weeks max
7604 25 Feb 19 nicklas 56     // Add a normal click handler and an extra for moving focus with arrow keys
7604 25 Feb 19 nicklas 57     for (var week = 1; week < 7; week++)
7604 25 Feb 19 nicklas 58     {
7604 25 Feb 19 nicklas 59       for (var day = 0; day < 7; day++)
7604 25 Feb 19 nicklas 60       {
7604 25 Feb 19 nicklas 61         var e = 'w'+week+'d'+day;
7604 25 Feb 19 nicklas 62         Buttons.addClickHandler(e, calendar.dayOnClick);
7604 25 Feb 19 nicklas 63         Events.addEventHandler(e, 'keypress', calendar.handleArrowKeys);
7604 25 Feb 19 nicklas 64       }
7604 25 Feb 19 nicklas 65     }
7604 25 Feb 19 nicklas 66     
7604 25 Feb 19 nicklas 67     // Get the field that holds the date value in the parent form
7604 25 Feb 19 nicklas 68     dateField = window.opener.document.getElementById(Data.get('page-data', 'textarea'));
7604 25 Feb 19 nicklas 69     dateFormat = Data.get('page-data', 'date-format');
7604 25 Feb 19 nicklas 70     useTime = Data.int('page-data', 'use-time');
7604 25 Feb 19 nicklas 71     currentDate = Dates.parseString(dateField.value, dateFormat);
7604 25 Feb 19 nicklas 72     if (!currentDate) currentDate = new Date();
7604 25 Feb 19 nicklas 73     
7604 25 Feb 19 nicklas 74     // Display the current month and time
7604 25 Feb 19 nicklas 75     calendar.displayMonth(currentDate.getFullYear(), currentDate.getMonth());
7604 25 Feb 19 nicklas 76     if (useTime)
7604 25 Feb 19 nicklas 77     {
7604 25 Feb 19 nicklas 78       var frm = document.forms['calendar'];
7604 25 Feb 19 nicklas 79       frm.hours.value = calendar.zeroPad(currentDate.getHours());
7604 25 Feb 19 nicklas 80       frm.minutes.value = calendar.zeroPad(currentDate.getMinutes());
7604 25 Feb 19 nicklas 81       frm.seconds.value = calendar.zeroPad(currentDate.getSeconds());
7604 25 Feb 19 nicklas 82     }
7604 25 Feb 19 nicklas 83   }
7604 25 Feb 19 nicklas 84
7604 25 Feb 19 nicklas 85   /**
7604 25 Feb 19 nicklas 86     Display a calendar for the given year and month.
7604 25 Feb 19 nicklas 87   */
7604 25 Feb 19 nicklas 88   calendar.displayMonth = function(year, month)
7604 25 Feb 19 nicklas 89   {
7604 25 Feb 19 nicklas 90     // Normalize month and year
7604 25 Feb 19 nicklas 91     if (month > 11)
7604 25 Feb 19 nicklas 92     {
7604 25 Feb 19 nicklas 93       month -= 12;
7604 25 Feb 19 nicklas 94       year++;
7604 25 Feb 19 nicklas 95     }
7604 25 Feb 19 nicklas 96     else if (month < 0)
7604 25 Feb 19 nicklas 97     {
7604 25 Feb 19 nicklas 98       month += 12;
7604 25 Feb 19 nicklas 99       year--;
7604 25 Feb 19 nicklas 100     }
7604 25 Feb 19 nicklas 101     calendarMonth = month;
7604 25 Feb 19 nicklas 102     calendarYear = year;
7604 25 Feb 19 nicklas 103     
7604 25 Feb 19 nicklas 104     // Display the year and month
7604 25 Feb 19 nicklas 105     Doc.element('year').innerHTML = year;
7604 25 Feb 19 nicklas 106     Doc.element('month').innerHTML = calendar.MONTHS[month];
7604 25 Feb 19 nicklas 107     
7604 25 Feb 19 nicklas 108     // The day of week of the first day in month
7604 25 Feb 19 nicklas 109     // 1=mon, 2=tue, ...7=sun
7604 25 Feb 19 nicklas 110     var firstDayInMonth = new Date(year, month, 1).getDay() || 7;
7604 25 Feb 19 nicklas 111     // Number of day in this month
7604 25 Feb 19 nicklas 112     var daysInMonth = Dates.daysInMonth(year, month+1);
7604 25 Feb 19 nicklas 113     var dayNum = 2-firstDayInMonth;
7604 25 Feb 19 nicklas 114     var today = new Date();
7604 25 Feb 19 nicklas 115     for (var week = 1; week <= 6; week++)
7604 25 Feb 19 nicklas 116     {
7604 25 Feb 19 nicklas 117       for (var day = 0; day <= 6; day++)
7604 25 Feb 19 nicklas 118       {
7604 25 Feb 19 nicklas 119         var cell = Doc.element('w'+week+'d'+day);
7604 25 Feb 19 nicklas 120         {
7604 25 Feb 19 nicklas 121           if (dayNum < 1 || dayNum > daysInMonth)
7604 25 Feb 19 nicklas 122           {
7604 25 Feb 19 nicklas 123             cell.firstChild.nodeValue = '';
7604 25 Feb 19 nicklas 124             cell.tabIndex = -1;
7604 25 Feb 19 nicklas 125             cell.theDate = null;
7604 25 Feb 19 nicklas 126             Doc.removeClass(cell, 'interactable');
7604 25 Feb 19 nicklas 127             if (day == 0 && week > 4) Doc.hide('w' + week);
7604 25 Feb 19 nicklas 128           }
7604 25 Feb 19 nicklas 129           else
7604 25 Feb 19 nicklas 130           {
7604 25 Feb 19 nicklas 131             cell.firstChild.nodeValue = dayNum;
7604 25 Feb 19 nicklas 132             cell.tabIndex = 0;
7604 25 Feb 19 nicklas 133             cell.theDate = new Date(year, month, dayNum);
7604 25 Feb 19 nicklas 134             Doc.addClass(cell, 'interactable');
7604 25 Feb 19 nicklas 135             if (day == 0) Doc.show('w' + week);
7604 25 Feb 19 nicklas 136           }
7604 25 Feb 19 nicklas 137         }
7604 25 Feb 19 nicklas 138         // Mark today's date
7604 25 Feb 19 nicklas 139         if (year == today.getFullYear() && month == today.getMonth() && dayNum == today.getDate())
7604 25 Feb 19 nicklas 140         {
7604 25 Feb 19 nicklas 141           Doc.addClass(cell, 'today');
7604 25 Feb 19 nicklas 142         }
7604 25 Feb 19 nicklas 143         else
7604 25 Feb 19 nicklas 144         {
7604 25 Feb 19 nicklas 145           Doc.removeClass(cell, 'today');
7604 25 Feb 19 nicklas 146         }
7604 25 Feb 19 nicklas 147         // Mark the currently selected date
7604 25 Feb 19 nicklas 148         if (year == currentDate.getFullYear() && month == currentDate.getMonth() && dayNum == currentDate.getDate())
7604 25 Feb 19 nicklas 149         {
7604 25 Feb 19 nicklas 150           Doc.addClass(cell, 'active');
7604 25 Feb 19 nicklas 151           cell.focus();
7604 25 Feb 19 nicklas 152         }
7604 25 Feb 19 nicklas 153         else
7604 25 Feb 19 nicklas 154         {
7604 25 Feb 19 nicklas 155           Doc.removeClass(cell, 'active');
7604 25 Feb 19 nicklas 156         }
7604 25 Feb 19 nicklas 157         dayNum++;
7604 25 Feb 19 nicklas 158       }
7604 25 Feb 19 nicklas 159     }
7604 25 Feb 19 nicklas 160     
7604 25 Feb 19 nicklas 161   }
7604 25 Feb 19 nicklas 162   
7604 25 Feb 19 nicklas 163   // Add an extra '0' to all values below 10.
7604 25 Feb 19 nicklas 164   calendar.zeroPad = function(value)
7604 25 Feb 19 nicklas 165   {
7604 25 Feb 19 nicklas 166     return value <= 9 ? '0' + value : value;
7604 25 Feb 19 nicklas 167   }
7604 25 Feb 19 nicklas 168   
7604 25 Feb 19 nicklas 169   /**
7604 25 Feb 19 nicklas 170     Display the next month in the calendar.
7604 25 Feb 19 nicklas 171   */
7604 25 Feb 19 nicklas 172   calendar.nextMonth = function()
7604 25 Feb 19 nicklas 173   {
7604 25 Feb 19 nicklas 174     calendar.displayMonth(calendarYear, calendarMonth+1);
7604 25 Feb 19 nicklas 175   }
7604 25 Feb 19 nicklas 176   
7604 25 Feb 19 nicklas 177   /**
7604 25 Feb 19 nicklas 178     Display the previous month in the calendar.
7604 25 Feb 19 nicklas 179   */
7604 25 Feb 19 nicklas 180   calendar.prevMonth = function()
7604 25 Feb 19 nicklas 181   {
7604 25 Feb 19 nicklas 182     calendar.displayMonth(calendarYear, calendarMonth-1);
7604 25 Feb 19 nicklas 183   }
7604 25 Feb 19 nicklas 184   
7604 25 Feb 19 nicklas 185   /**
7604 25 Feb 19 nicklas 186     Set the current date as the date and close the
7604 25 Feb 19 nicklas 187     calendar.
7604 25 Feb 19 nicklas 188   */
7604 25 Feb 19 nicklas 189   calendar.setToday = function()
7604 25 Feb 19 nicklas 190   {
7604 25 Feb 19 nicklas 191     currentDate = new Date();
7604 25 Feb 19 nicklas 192     if (useTime)
7604 25 Feb 19 nicklas 193     {
7604 25 Feb 19 nicklas 194       calendar.displayMonth(currentDate.getFullYear(), currentDate.getMonth());
7604 25 Feb 19 nicklas 195     }
7604 25 Feb 19 nicklas 196     else
7604 25 Feb 19 nicklas 197     {
7604 25 Feb 19 nicklas 198       calendar.save();
7604 25 Feb 19 nicklas 199     }
7604 25 Feb 19 nicklas 200   }
7604 25 Feb 19 nicklas 201   
7604 25 Feb 19 nicklas 202   /**
7604 25 Feb 19 nicklas 203     Check that a valid date (and time) has been set.
7604 25 Feb 19 nicklas 204   */
7604 25 Feb 19 nicklas 205   calendar.validate = function()
7604 25 Feb 19 nicklas 206   {
7604 25 Feb 19 nicklas 207     var frm = document.forms['calendar'];
7604 25 Feb 19 nicklas 208     if (useTime)
7604 25 Feb 19 nicklas 209     {
7604 25 Feb 19 nicklas 210       var hours = parseInt(frm.hours.value, 10);
7604 25 Feb 19 nicklas 211       if (hours < 0 || hours > 23)
7604 25 Feb 19 nicklas 212       {
7604 25 Feb 19 nicklas 213         Forms.showNotification(frm.hours, 'Hours must be a value between 0 and 23', 'small');
7604 25 Feb 19 nicklas 214         return false;
7604 25 Feb 19 nicklas 215       }
7604 25 Feb 19 nicklas 216       var minutes = parseInt(frm.minutes.value, 10);
7604 25 Feb 19 nicklas 217       if (minutes < 0 || minutes > 59)
7604 25 Feb 19 nicklas 218       {
7604 25 Feb 19 nicklas 219         Forms.showNotification(frm.minutes, 'Minutes must be a value between 0 and 59', 'small');
7604 25 Feb 19 nicklas 220         return false;
7604 25 Feb 19 nicklas 221       }
7604 25 Feb 19 nicklas 222       var seconds = parseInt(frm.seconds.value, 10);
7604 25 Feb 19 nicklas 223       if (seconds < 0 || seconds > 59)
7604 25 Feb 19 nicklas 224       {
7604 25 Feb 19 nicklas 225         Forms.showNotification(frm.seconds, 'Seconds must be a value between 0 and 59', 'small');
7604 25 Feb 19 nicklas 226         return false;
7604 25 Feb 19 nicklas 227       }
7604 25 Feb 19 nicklas 228     }
7604 25 Feb 19 nicklas 229     return true;
7604 25 Feb 19 nicklas 230   }
7604 25 Feb 19 nicklas 231   
7604 25 Feb 19 nicklas 232   calendar.save = function()
7604 25 Feb 19 nicklas 233   {
7604 25 Feb 19 nicklas 234     // Validate form
7604 25 Feb 19 nicklas 235     if (!calendar.validate()) return;
7604 25 Feb 19 nicklas 236     
7604 25 Feb 19 nicklas 237     // Copy current time values
7604 25 Feb 19 nicklas 238     if (useTime)
7604 25 Feb 19 nicklas 239     {
7604 25 Feb 19 nicklas 240       var frm = document.forms['calendar'];
7604 25 Feb 19 nicklas 241       currentDate.setHours(frm.hours.value);
7604 25 Feb 19 nicklas 242       currentDate.setMinutes(frm.minutes.value);
7604 25 Feb 19 nicklas 243       currentDate.setSeconds(frm.seconds.value);
7604 25 Feb 19 nicklas 244     }
7604 25 Feb 19 nicklas 245     
7604 25 Feb 19 nicklas 246     // Save the value to the date field
7604 25 Feb 19 nicklas 247     dateField.value = Dates.formatDate(currentDate, dateFormat);
7604 25 Feb 19 nicklas 248     // Fire an 'onchange' event
7604 25 Feb 19 nicklas 249     Events.sendChangeEvent(dateField);
7604 25 Feb 19 nicklas 250     // Set the focus...
7604 25 Feb 19 nicklas 251     dateField.focus();
7604 25 Feb 19 nicklas 252     // ...and close the calendar
7604 25 Feb 19 nicklas 253     window.close();
7604 25 Feb 19 nicklas 254   }
7604 25 Feb 19 nicklas 255   
7604 25 Feb 19 nicklas 256   /**
7604 25 Feb 19 nicklas 257     Event handler for 'click' events on a day in the calendar.
7604 25 Feb 19 nicklas 258     Saves the clicked date and closes the calendar (if no time 
7604 25 Feb 19 nicklas 259     is used).
7604 25 Feb 19 nicklas 260   */
7604 25 Feb 19 nicklas 261   calendar.dayOnClick = function(event)
7604 25 Feb 19 nicklas 262   {
7604 25 Feb 19 nicklas 263     if (!event.currentTarget.theDate) return;
7604 25 Feb 19 nicklas 264     currentDate = event.currentTarget.theDate;
7604 25 Feb 19 nicklas 265     if (useTime)
7604 25 Feb 19 nicklas 266     {
7604 25 Feb 19 nicklas 267       calendar.displayMonth(currentDate.getFullYear(), currentDate.getMonth());
7604 25 Feb 19 nicklas 268     }
7604 25 Feb 19 nicklas 269     else
7604 25 Feb 19 nicklas 270     {
7604 25 Feb 19 nicklas 271       calendar.save();
7604 25 Feb 19 nicklas 272     }
7604 25 Feb 19 nicklas 273   }
7604 25 Feb 19 nicklas 274   
7604 25 Feb 19 nicklas 275   /**
7604 25 Feb 19 nicklas 276     Set focus to 'next' day when arrow keys are pressed.
7604 25 Feb 19 nicklas 277   */
7604 25 Feb 19 nicklas 278   calendar.handleArrowKeys = function(event)
7604 25 Feb 19 nicklas 279   {
7604 25 Feb 19 nicklas 280     var keyCode = event.keyCode;
7604 25 Feb 19 nicklas 281     if (keyCode >= 37 && keyCode <= 40)
7604 25 Feb 19 nicklas 282     {
7604 25 Feb 19 nicklas 283       var week = Data.int(event.currentTarget, 'week');
7604 25 Feb 19 nicklas 284       var day = Data.int(event.currentTarget, 'day');
7604 25 Feb 19 nicklas 285       // 37 - left, 38 - up, 39 - right, 40 - down
7604 25 Feb 19 nicklas 286       if (keyCode == 37) day--;
7604 25 Feb 19 nicklas 287       if (keyCode == 38) week--;
7604 25 Feb 19 nicklas 288       if (keyCode == 39) day++;
7604 25 Feb 19 nicklas 289       if (keyCode == 40) week++;
7604 25 Feb 19 nicklas 290       var next = Doc.element('w'+week+'d'+day);
7604 25 Feb 19 nicklas 291       if (next && next.tabIndex != -1)
7604 25 Feb 19 nicklas 292       {
7604 25 Feb 19 nicklas 293         next.focus();
7604 25 Feb 19 nicklas 294       }
7604 25 Feb 19 nicklas 295     }
7604 25 Feb 19 nicklas 296   }
7604 25 Feb 19 nicklas 297   
7604 25 Feb 19 nicklas 298   return calendar;
7604 25 Feb 19 nicklas 299 }();
7604 25 Feb 19 nicklas 300
7604 25 Feb 19 nicklas 301 Doc.onLoad(Calendar.initPage);
7604 25 Feb 19 nicklas 302
7604 25 Feb 19 nicklas 303