Htk.Calendar = new Class ({ Extends: Htk.Field ,Tag: 'htk-calendar' ,tds: [] ,selectedTd: null ,todayTd: null ,year: null ,month: null ,initialize: function (props) { this.parent (props); var len = Vn.Date.WDays.length; this.createElement ('div'); this.node.className = 'htk-calendar'; var table = document.createElement ('table'); this.node.appendChild (table); var colgroup = document.createElement ('colgroup'); table.appendChild (colgroup); for (var i = 0; i < len; i++) colgroup.appendChild (document.createElement ('col')); var thead = document.createElement ('thead'); table.appendChild (thead); var tr = document.createElement ('tr'); thead.appendChild (tr); var th = document.createElement ('th'); th.appendChild (document.createTextNode ('<')); th.className = 'button'; th.addEventListener ('click', this.prevMonthClicked.bind (this)); tr.appendChild (th); var monthNode = document.createElement ('th'); monthNode.colSpan = 5; tr.appendChild (monthNode); var th = document.createElement ('th'); th.appendChild (document.createTextNode ('>')); th.className = 'button'; th.addEventListener ('click', this.nextMonthClicked.bind (this)); tr.appendChild (th); var tr = document.createElement ('tr'); thead.appendChild (tr); for (i = 1; i <= len; i++) { var th = document.createElement ('th'); tr.appendChild (th); var weekday = Vn.Date.AbrWDays [i%len]; th.appendChild (document.createTextNode (weekday)); } var tfoot = document.createElement ('tfoot'); table.appendChild (tfoot); var tr = document.createElement ('tr'); tfoot.appendChild (tr); var th = document.createElement ('th'); th.appendChild (document.createTextNode ('<')); th.className = 'button'; th.addEventListener ('click', this.prevYearClicked.bind (this)); tr.appendChild (th); var yearNode = document.createElement ('th'); yearNode.colSpan = 5; tr.appendChild (yearNode); var th = document.createElement ('th'); th.appendChild (document.createTextNode ('>')); th.className = 'button'; th.addEventListener ('click', this.nextYearClicked.bind (this)); tr.appendChild (th); var tbody = document.createElement ('tbody'); table.appendChild (tbody); for (i = 0; i < 6; i++) { tr = document.createElement ('tr'); tbody.appendChild (tr); for (j = 0; j < len; j++) { td = document.createElement ('td'); td.addEventListener ('click', this.dayClicked.bind (this, td, i*len+j)); tr.appendChild (td); this.tds.push (td); } } this.monthNode = monthNode; this.yearNode = yearNode; this.goToCurrentMonth (); } ,getFirstWeekDay: function () { var weekDay = new Date (this.year, this.month, 1).getDay (); return (weekDay != 0) ? weekDay - 1 : 6; } ,getMonthDays: function () { if (this.month > 6) return (this.month % 2 != 0) ? 31 : 30; else if (this.month != 1) return (this.month % 2 != 1) ? 31 : 30; else return (this.year % 4 != 0) ? 28 : 29; } ,goToMonth: function (year, month) { if (year) this.year = year; if (!isNaN (month)) this.month = month; this.refresh (); } ,goToSelectedMonth: function () { var date = this._value; if (date instanceof Date) this.goToMonth (date.getFullYear (), date.getMonth ()); else this.goToCurrentMonth (); } ,goToCurrentMonth: function () { var date = new Date (); this.goToMonth (date.getFullYear (), date.getMonth ()); } ,refresh: function () { Vn.Node.setText (this.yearNode, this.year); Vn.Node.setText (this.monthNode, Vn.Date.Months[this.month]); var firstWeekDay = this.getFirstWeekDay (); var monthDays = this.getMonthDays (); var day = 1; for (i = 0; i < this.tds.length; i++) { if (firstWeekDay <= i && day <= monthDays) Vn.Node.setText (this.tds[i], day++); else Vn.Node.removeChilds (this.tds[i]); } // Marks the current day var today = new Date (); if (this.year == today.getFullYear () && this.month == today.getMonth ()) { var tdIndex = (firstWeekDay + today.getDate ()) - 1; this.tds[tdIndex].style.fontWeight = 'bold'; this.todayTd = this.tds[tdIndex]; } else if (this.todayTd) { this.todayTd.style.fontWeight = ''; this.todayTd = null; } // Marks the selected day var date = this._value; if (date instanceof Date && this.year == date.getFullYear () && this.month == date.getMonth ()) { var tdIndex = (firstWeekDay + date.getDate ()) - 1; this.selectTd (this.tds[tdIndex]); } else this.selectTd (null); } ,selectTd: function (td) { if (this.selectedTd) this.selectedTd.className = undefined; if (td) td.className = 'highlight'; this.selectedTd = td; } ,putValue: function (value) { this.goToSelectedMonth (); } ,dayClicked: function (td, tdIndex) { var monthDay = (tdIndex - this.getFirstWeekDay ()) + 1; if (monthDay >= 1 && monthDay <= this.getMonthDays ()) { this.selectTd (td); var newDate = new Date (this.year, this.month, monthDay); this.valueChanged (newDate); } } ,prevMonthClicked: function () { if (this.month > 0) this.month--; else { this.month = 11; this.year--; } this.refresh (); } ,nextMonthClicked: function () { if (this.month < 11) this.month++; else { this.month = 0; this.year++; } this.refresh (); } ,prevYearClicked: function () { this.year--; this.refresh (); } ,nextYearClicked: function () { this.year++; this.refresh (); } });