You can not select more than 25 topics
Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
221 lines
8.3 KiB
221 lines
8.3 KiB
/*global gettext, pgettext, get_format, quickElement, removeChildren*/ |
|
/* |
|
calendar.js - Calendar functions by Adrian Holovaty |
|
depends on core.js for utility functions like removeChildren or quickElement |
|
*/ |
|
'use strict'; |
|
{ |
|
// CalendarNamespace -- Provides a collection of HTML calendar-related helper functions |
|
const CalendarNamespace = { |
|
monthsOfYear: [ |
|
gettext('January'), |
|
gettext('February'), |
|
gettext('March'), |
|
gettext('April'), |
|
gettext('May'), |
|
gettext('June'), |
|
gettext('July'), |
|
gettext('August'), |
|
gettext('September'), |
|
gettext('October'), |
|
gettext('November'), |
|
gettext('December') |
|
], |
|
monthsOfYearAbbrev: [ |
|
pgettext('abbrev. month January', 'Jan'), |
|
pgettext('abbrev. month February', 'Feb'), |
|
pgettext('abbrev. month March', 'Mar'), |
|
pgettext('abbrev. month April', 'Apr'), |
|
pgettext('abbrev. month May', 'May'), |
|
pgettext('abbrev. month June', 'Jun'), |
|
pgettext('abbrev. month July', 'Jul'), |
|
pgettext('abbrev. month August', 'Aug'), |
|
pgettext('abbrev. month September', 'Sep'), |
|
pgettext('abbrev. month October', 'Oct'), |
|
pgettext('abbrev. month November', 'Nov'), |
|
pgettext('abbrev. month December', 'Dec') |
|
], |
|
daysOfWeek: [ |
|
pgettext('one letter Sunday', 'S'), |
|
pgettext('one letter Monday', 'M'), |
|
pgettext('one letter Tuesday', 'T'), |
|
pgettext('one letter Wednesday', 'W'), |
|
pgettext('one letter Thursday', 'T'), |
|
pgettext('one letter Friday', 'F'), |
|
pgettext('one letter Saturday', 'S') |
|
], |
|
firstDayOfWeek: parseInt(get_format('FIRST_DAY_OF_WEEK')), |
|
isLeapYear: function(year) { |
|
return (((year % 4) === 0) && ((year % 100) !== 0 ) || ((year % 400) === 0)); |
|
}, |
|
getDaysInMonth: function(month, year) { |
|
let days; |
|
if (month === 1 || month === 3 || month === 5 || month === 7 || month === 8 || month === 10 || month === 12) { |
|
days = 31; |
|
} |
|
else if (month === 4 || month === 6 || month === 9 || month === 11) { |
|
days = 30; |
|
} |
|
else if (month === 2 && CalendarNamespace.isLeapYear(year)) { |
|
days = 29; |
|
} |
|
else { |
|
days = 28; |
|
} |
|
return days; |
|
}, |
|
draw: function(month, year, div_id, callback, selected) { // month = 1-12, year = 1-9999 |
|
const today = new Date(); |
|
const todayDay = today.getDate(); |
|
const todayMonth = today.getMonth() + 1; |
|
const todayYear = today.getFullYear(); |
|
let todayClass = ''; |
|
|
|
// Use UTC functions here because the date field does not contain time |
|
// and using the UTC function variants prevent the local time offset |
|
// from altering the date, specifically the day field. For example: |
|
// |
|
// ``` |
|
// var x = new Date('2013-10-02'); |
|
// var day = x.getDate(); |
|
// ``` |
|
// |
|
// The day variable above will be 1 instead of 2 in, say, US Pacific time |
|
// zone. |
|
let isSelectedMonth = false; |
|
if (typeof selected !== 'undefined') { |
|
isSelectedMonth = (selected.getUTCFullYear() === year && (selected.getUTCMonth() + 1) === month); |
|
} |
|
|
|
month = parseInt(month); |
|
year = parseInt(year); |
|
const calDiv = document.getElementById(div_id); |
|
removeChildren(calDiv); |
|
const calTable = document.createElement('table'); |
|
quickElement('caption', calTable, CalendarNamespace.monthsOfYear[month - 1] + ' ' + year); |
|
const tableBody = quickElement('tbody', calTable); |
|
|
|
// Draw days-of-week header |
|
let tableRow = quickElement('tr', tableBody); |
|
for (let i = 0; i < 7; i++) { |
|
quickElement('th', tableRow, CalendarNamespace.daysOfWeek[(i + CalendarNamespace.firstDayOfWeek) % 7]); |
|
} |
|
|
|
const startingPos = new Date(year, month - 1, 1 - CalendarNamespace.firstDayOfWeek).getDay(); |
|
const days = CalendarNamespace.getDaysInMonth(month, year); |
|
|
|
let nonDayCell; |
|
|
|
// Draw blanks before first of month |
|
tableRow = quickElement('tr', tableBody); |
|
for (let i = 0; i < startingPos; i++) { |
|
nonDayCell = quickElement('td', tableRow, ' '); |
|
nonDayCell.className = "nonday"; |
|
} |
|
|
|
function calendarMonth(y, m) { |
|
function onClick(e) { |
|
e.preventDefault(); |
|
callback(y, m, this.textContent); |
|
} |
|
return onClick; |
|
} |
|
|
|
// Draw days of month |
|
let currentDay = 1; |
|
for (let i = startingPos; currentDay <= days; i++) { |
|
if (i % 7 === 0 && currentDay !== 1) { |
|
tableRow = quickElement('tr', tableBody); |
|
} |
|
if ((currentDay === todayDay) && (month === todayMonth) && (year === todayYear)) { |
|
todayClass = 'today'; |
|
} else { |
|
todayClass = ''; |
|
} |
|
|
|
// use UTC function; see above for explanation. |
|
if (isSelectedMonth && currentDay === selected.getUTCDate()) { |
|
if (todayClass !== '') { |
|
todayClass += " "; |
|
} |
|
todayClass += "selected"; |
|
} |
|
|
|
const cell = quickElement('td', tableRow, '', 'class', todayClass); |
|
const link = quickElement('a', cell, currentDay, 'href', '#'); |
|
link.addEventListener('click', calendarMonth(year, month)); |
|
currentDay++; |
|
} |
|
|
|
// Draw blanks after end of month (optional, but makes for valid code) |
|
while (tableRow.childNodes.length < 7) { |
|
nonDayCell = quickElement('td', tableRow, ' '); |
|
nonDayCell.className = "nonday"; |
|
} |
|
|
|
calDiv.appendChild(calTable); |
|
} |
|
}; |
|
|
|
// Calendar -- A calendar instance |
|
function Calendar(div_id, callback, selected) { |
|
// div_id (string) is the ID of the element in which the calendar will |
|
// be displayed |
|
// callback (string) is the name of a JavaScript function that will be |
|
// called with the parameters (year, month, day) when a day in the |
|
// calendar is clicked |
|
this.div_id = div_id; |
|
this.callback = callback; |
|
this.today = new Date(); |
|
this.currentMonth = this.today.getMonth() + 1; |
|
this.currentYear = this.today.getFullYear(); |
|
if (typeof selected !== 'undefined') { |
|
this.selected = selected; |
|
} |
|
} |
|
Calendar.prototype = { |
|
drawCurrent: function() { |
|
CalendarNamespace.draw(this.currentMonth, this.currentYear, this.div_id, this.callback, this.selected); |
|
}, |
|
drawDate: function(month, year, selected) { |
|
this.currentMonth = month; |
|
this.currentYear = year; |
|
|
|
if(selected) { |
|
this.selected = selected; |
|
} |
|
|
|
this.drawCurrent(); |
|
}, |
|
drawPreviousMonth: function() { |
|
if (this.currentMonth === 1) { |
|
this.currentMonth = 12; |
|
this.currentYear--; |
|
} |
|
else { |
|
this.currentMonth--; |
|
} |
|
this.drawCurrent(); |
|
}, |
|
drawNextMonth: function() { |
|
if (this.currentMonth === 12) { |
|
this.currentMonth = 1; |
|
this.currentYear++; |
|
} |
|
else { |
|
this.currentMonth++; |
|
} |
|
this.drawCurrent(); |
|
}, |
|
drawPreviousYear: function() { |
|
this.currentYear--; |
|
this.drawCurrent(); |
|
}, |
|
drawNextYear: function() { |
|
this.currentYear++; |
|
this.drawCurrent(); |
|
} |
|
}; |
|
window.Calendar = Calendar; |
|
window.CalendarNamespace = CalendarNamespace; |
|
}
|
|
|