module.exports = new Class ({ Extends: Htk.Field ,Tag: 'htk-calendar' ,Properties: { restrictFunc: { type: Function ,set: function (x) { this._restrictFunc = x; } ,get: function (x) { return this._restrictFunc; } } } ,cells: [] ,selectedCell: -1 ,year: null ,month: null ,render: function () { var len = Vn.Date.WDays.length; var node = this.createRoot ('div'); node.className = 'htk-calendar'; var table = this.createElement ('table'); this.node.appendChild (table); var colgroup = this.createElement ('colgroup'); table.appendChild (colgroup); for (var i = 0; i < len; i++) colgroup.appendChild (this.createElement ('col')); var thead = this.createElement ('thead'); table.appendChild (thead); var tr = this.createElement ('tr'); thead.appendChild (tr); var th = this.createElement ('th'); th.appendChild (this.createTextNode ('<')); th.className = 'button'; th.addEventListener ('click', this.prevMonthClicked.bind (this)); tr.appendChild (th); var th = this.createElement ('th'); th.colSpan = 5; tr.appendChild (th); var monthNode = this.createElement ('span'); th.appendChild (monthNode); var space = this.createTextNode (' '); th.appendChild (space); var yearNode = this.createElement ('span'); th.appendChild (yearNode); var th = this.createElement ('th'); th.appendChild (this.createTextNode ('>')); th.className = 'button'; th.addEventListener ('click', this.nextMonthClicked.bind (this)); tr.appendChild (th); var tr = this.createElement ('tr'); thead.appendChild (tr); for (var i = 1; i <= len; i++) { var th = this.createElement ('th'); tr.appendChild (th); var weekday = _(Vn.Date.AbrWDays [i%len]); th.appendChild (this.createTextNode (weekday)); } var tbody = this.createElement ('tbody'); table.appendChild (tbody); for (var i = 0; i < 6; i++) { var tr = this.createElement ('tr'); tbody.appendChild (tr); for (var j = 0; j < len; j++) { var td = this.createElement ('td'); td.addEventListener ('click', this.dayClicked.bind (this, td, i*len+j)); tr.appendChild (td); var div = this.createElement ('div'); td.appendChild (div); this.cells.push ({ node: div, enabled: false, day: -1 }); } } this.monthNode = monthNode; this.yearNode = yearNode; this.goToCurrentMonth (); } ,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 day = 1; var cellDate = new Date (this.year, this.month, 1); var weekDay = cellDate.getDay (); var firstWeekDay = (weekDay != 0) ? weekDay - 1 : 6; var monthDays = this.getMonthDays (); for (var i = 0; i < this.cells.length; i++) { var cell = this.cells[i]; if (firstWeekDay <= i && day <= monthDays) { Vn.Node.setText (cell.node, day); cell.enabled = true; cell.day = day++; if (this._restrictFunc) { cell.enabled = this._restrictFunc (cellDate); cellDate.setDate (cellDate.getDate () + 1); } } else { Vn.Node.removeChilds (cell.node); cell.enabled = false; cell.day = -1; } cell.node.className = cell.enabled ? 'enabled' : 'disabled'; } // Marks the current day var today = new Date (); if (this.year == today.getFullYear () && this.month == today.getMonth ()) { var cellIndex = (firstWeekDay + today.getDate ()) - 1; Vn.Node.addClass (this.cells[cellIndex].node, 'today'); } // Marks the selected day var date = this._value; if (date instanceof Date && this.year == date.getFullYear () && this.month == date.getMonth ()) this.selectCell ((firstWeekDay + date.getDate ()) - 1); else this.selectCell (-1); } ,selectCell: function (cellIndex) { if (this.selectedCell != -1) { var node = this.cells[this.selectedCell].node; Vn.Node.removeClass (node, 'selected'); } if (cellIndex != -1) { var node = this.cells[cellIndex].node; Vn.Node.addClass (node, 'selected'); } this.selectedCell = cellIndex; } ,putValue: function (value) { this.goToSelectedMonth (); } ,dayClicked: function (td, cellIndex) { var cell = this.cells[cellIndex]; if (cell.enabled) { this.selectCell (cellIndex); var newDate = new Date (this.year, this.month, cell.day); 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 (); } });