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() { 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); if (this.value) { var orgDate = this.value instanceof Date ? this.value : new Date(this.value); if (!isNaN(orgDate.getTime())) newDate.setHours( orgDate.getHours(), orgDate.getMinutes(), orgDate.getSeconds(), orgDate.getMilliseconds() ); } 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(); } });