calendar.js 7.6 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208
  1. /*global gettext, pgettext, get_format, quickElement, removeChildren, addEvent*/
  2. /*
  3. calendar.js - Calendar functions by Adrian Holovaty
  4. depends on core.js for utility functions like removeChildren or quickElement
  5. */
  6. (function() {
  7. 'use strict';
  8. // CalendarNamespace -- Provides a collection of HTML calendar-related helper functions
  9. var CalendarNamespace = {
  10. monthsOfYear: [
  11. gettext('January'),
  12. gettext('February'),
  13. gettext('March'),
  14. gettext('April'),
  15. gettext('May'),
  16. gettext('June'),
  17. gettext('July'),
  18. gettext('August'),
  19. gettext('September'),
  20. gettext('October'),
  21. gettext('November'),
  22. gettext('December')
  23. ],
  24. daysOfWeek: [
  25. pgettext('one letter Sunday', 'S'),
  26. pgettext('one letter Monday', 'M'),
  27. pgettext('one letter Tuesday', 'T'),
  28. pgettext('one letter Wednesday', 'W'),
  29. pgettext('one letter Thursday', 'T'),
  30. pgettext('one letter Friday', 'F'),
  31. pgettext('one letter Saturday', 'S')
  32. ],
  33. firstDayOfWeek: parseInt(get_format('FIRST_DAY_OF_WEEK')),
  34. isLeapYear: function(year) {
  35. return (((year % 4) === 0) && ((year % 100) !== 0 ) || ((year % 400) === 0));
  36. },
  37. getDaysInMonth: function(month, year) {
  38. var days;
  39. if (month === 1 || month === 3 || month === 5 || month === 7 || month === 8 || month === 10 || month === 12) {
  40. days = 31;
  41. }
  42. else if (month === 4 || month === 6 || month === 9 || month === 11) {
  43. days = 30;
  44. }
  45. else if (month === 2 && CalendarNamespace.isLeapYear(year)) {
  46. days = 29;
  47. }
  48. else {
  49. days = 28;
  50. }
  51. return days;
  52. },
  53. draw: function(month, year, div_id, callback, selected) { // month = 1-12, year = 1-9999
  54. var today = new Date();
  55. var todayDay = today.getDate();
  56. var todayMonth = today.getMonth() + 1;
  57. var todayYear = today.getFullYear();
  58. var todayClass = '';
  59. // Use UTC functions here because the date field does not contain time
  60. // and using the UTC function variants prevent the local time offset
  61. // from altering the date, specifically the day field. For example:
  62. //
  63. // ```
  64. // var x = new Date('2013-10-02');
  65. // var day = x.getDate();
  66. // ```
  67. //
  68. // The day variable above will be 1 instead of 2 in, say, US Pacific time
  69. // zone.
  70. var isSelectedMonth = false;
  71. if (typeof selected !== 'undefined') {
  72. isSelectedMonth = (selected.getUTCFullYear() === year && (selected.getUTCMonth() + 1) === month);
  73. }
  74. month = parseInt(month);
  75. year = parseInt(year);
  76. var calDiv = document.getElementById(div_id);
  77. removeChildren(calDiv);
  78. var calTable = document.createElement('table');
  79. quickElement('caption', calTable, CalendarNamespace.monthsOfYear[month - 1] + ' ' + year);
  80. var tableBody = quickElement('tbody', calTable);
  81. // Draw days-of-week header
  82. var tableRow = quickElement('tr', tableBody);
  83. for (var i = 0; i < 7; i++) {
  84. quickElement('th', tableRow, CalendarNamespace.daysOfWeek[(i + CalendarNamespace.firstDayOfWeek) % 7]);
  85. }
  86. var startingPos = new Date(year, month - 1, 1 - CalendarNamespace.firstDayOfWeek).getDay();
  87. var days = CalendarNamespace.getDaysInMonth(month, year);
  88. var nonDayCell;
  89. // Draw blanks before first of month
  90. tableRow = quickElement('tr', tableBody);
  91. for (i = 0; i < startingPos; i++) {
  92. nonDayCell = quickElement('td', tableRow, ' ');
  93. nonDayCell.className = "nonday";
  94. }
  95. function calendarMonth(y, m) {
  96. function onClick(e) {
  97. e.preventDefault();
  98. callback(y, m, django.jQuery(this).text());
  99. }
  100. return onClick;
  101. }
  102. // Draw days of month
  103. var currentDay = 1;
  104. for (i = startingPos; currentDay <= days; i++) {
  105. if (i % 7 === 0 && currentDay !== 1) {
  106. tableRow = quickElement('tr', tableBody);
  107. }
  108. if ((currentDay === todayDay) && (month === todayMonth) && (year === todayYear)) {
  109. todayClass = 'today';
  110. } else {
  111. todayClass = '';
  112. }
  113. // use UTC function; see above for explanation.
  114. if (isSelectedMonth && currentDay === selected.getUTCDate()) {
  115. if (todayClass !== '') {
  116. todayClass += " ";
  117. }
  118. todayClass += "selected";
  119. }
  120. var cell = quickElement('td', tableRow, '', 'class', todayClass);
  121. var link = quickElement('a', cell, currentDay, 'href', '#');
  122. addEvent(link, 'click', calendarMonth(year, month));
  123. currentDay++;
  124. }
  125. // Draw blanks after end of month (optional, but makes for valid code)
  126. while (tableRow.childNodes.length < 7) {
  127. nonDayCell = quickElement('td', tableRow, ' ');
  128. nonDayCell.className = "nonday";
  129. }
  130. calDiv.appendChild(calTable);
  131. }
  132. };
  133. // Calendar -- A calendar instance
  134. function Calendar(div_id, callback, selected) {
  135. // div_id (string) is the ID of the element in which the calendar will
  136. // be displayed
  137. // callback (string) is the name of a JavaScript function that will be
  138. // called with the parameters (year, month, day) when a day in the
  139. // calendar is clicked
  140. this.div_id = div_id;
  141. this.callback = callback;
  142. this.today = new Date();
  143. this.currentMonth = this.today.getMonth() + 1;
  144. this.currentYear = this.today.getFullYear();
  145. if (typeof selected !== 'undefined') {
  146. this.selected = selected;
  147. }
  148. }
  149. Calendar.prototype = {
  150. drawCurrent: function() {
  151. CalendarNamespace.draw(this.currentMonth, this.currentYear, this.div_id, this.callback, this.selected);
  152. },
  153. drawDate: function(month, year, selected) {
  154. this.currentMonth = month;
  155. this.currentYear = year;
  156. if(selected) {
  157. this.selected = selected;
  158. }
  159. this.drawCurrent();
  160. },
  161. drawPreviousMonth: function() {
  162. if (this.currentMonth === 1) {
  163. this.currentMonth = 12;
  164. this.currentYear--;
  165. }
  166. else {
  167. this.currentMonth--;
  168. }
  169. this.drawCurrent();
  170. },
  171. drawNextMonth: function() {
  172. if (this.currentMonth === 12) {
  173. this.currentMonth = 1;
  174. this.currentYear++;
  175. }
  176. else {
  177. this.currentMonth++;
  178. }
  179. this.drawCurrent();
  180. },
  181. drawPreviousYear: function() {
  182. this.currentYear--;
  183. this.drawCurrent();
  184. },
  185. drawNextYear: function() {
  186. this.currentYear++;
  187. this.drawCurrent();
  188. }
  189. };
  190. window.Calendar = Calendar;
  191. window.CalendarNamespace = CalendarNamespace;
  192. })();