/* ex: set tabstop=2 softtabstop=2 shiftwidth=2 : */ /** * @param element * @param year * @param month */ /*jshint boss:true, plusplus:false */ function Qal(element) { /*global jQuery:true*/ element = ("jQuery" in window && element instanceof jQuery) ? element[0] : element; this.element = element; this.year = 0; this.month = 0; this._event = null; var controls = this.element.getElementsByTagName("span"); if (controls.length === 2 && controls[0].getAttribute("data-manipulation") && controls[1].getAttribute("data-manipulation")) { // make it an ordinary array instead of DOMList this.controls = [controls[0], controls[1]]; } else { throw new Error("Malformed controls in " + element + "."); } } Qal.prototype.toString = function() { return "" + this.year + "-" + this.month + "-1"; }; Qal.prototype.set = function(month, year) { var str, _now = new Date(); var old_year = this.year; var old_month = this.month; this.year = year ? parseInt(year, 10) : _now.getFullYear(); this.month = month ? parseInt(month, 10) : _now.getMonth() + 1; if (old_year !== this.year || old_month !== this.month) { // in case this.year is a Number, we prepend "" to convert it to a string str = "" + this.year + "-" + ("0" + this.month).slice(-2) + "-01"; // cache value in DOM this.element.setAttribute("data-date", str); } var now = new Date(this.year, this.month - 1, 1); this.updateDOM(now); this.updateEvent(); return this; }; Qal.prototype.updateDOM = function(now) { var oneDayInMilliseconds = 86400000, arr = [], timeAt, i, item, str = "", lastMonthLastSunday, currentMonthEndTimeStamp, currentMonthEnd, lastMonthEnd; document.getElementById("ftc-calendar-description").innerHTML = ""; function appendTo(arr, from, to) { to = to + 1; for (i = from; i < to; i++) { arr.push(i); } return arr; } lastMonthEnd = new Date(now - oneDayInMilliseconds).getDate(); // month is actually pointed to next month currentMonthEndTimeStamp = new Date(now).setMonth(this.month) - oneDayInMilliseconds; currentMonthEnd = new Date(currentMonthEndTimeStamp).getDate(); // find nearest Sunday in last month for (i = 0; i < 7; i++) { timeAt = new Date(now); if (timeAt.getDay() === 0) { lastMonthLastSunday = timeAt.getDate(); break; } now = now - oneDayInMilliseconds; } // prepend last month // if the first day of this month is Sunday, then we do not prepend any if (lastMonthLastSunday > 1) { arr = appendTo(arr, lastMonthLastSunday, lastMonthEnd); } // append current month arr = appendTo(arr, 1, currentMonthEnd); // append next month var lengthToCurrentMonthEnd = arr.length - 1; var nextMonthFirstSaturday = 6 - (lengthToCurrentMonthEnd % 7); arr = appendTo(arr, 1, nextMonthFirstSaturday); var calendarLength = arr.length; function repeater(str, item, index) { var className = "", prefix; if (index < 7) { className += " first-row"; if (item <= 7) { className += " this-month"; } } else if (index <= lengthToCurrentMonthEnd) { className += " this-month"; } if (index % 7 === 6) { className += " last-column"; } if (className.charAt(0) === " ") { className = className.substring(1); } prefix = className ? "" : ""; str += prefix + item + ""; return str; } for (i = 0; item = arr[i]; i++) { str = repeater(str, item, i); } var monthsInChinese = ["Error", "一", "二", "三", "四", "五", "六", "七", "八", "九", "十", "十一", "十二"]; this.element.getElementsByTagName("div")[0].innerHTML = str; this.element.getElementsByTagName("h2")[0].innerHTML = this.year + "年" + this.month + "月"; }; Qal.prototype.change = function(manipulation, callback) { var year = this.year; var month = this.month; month = manipulation === "next" ? month + 1 : month - 1; if (month < 1) { month = 12; year -= 1; } else if (month > 12) { month = 1; year += 1; } this.set(month, year); if (callback) { callback.call(null, this.year, this.month); } }; Qal.prototype.updateEvent = function(_event) { if (_event) { this._event = _event; } else { if (!this._event) { return; } } var i, _monthEvent = this._event[this.month], eventItem, _className, spans = [0], item, _spans = this.element.getElementsByTagName("span"); for (i = 0; item = _spans[i]; i++) { if (/\bthis-month\b/.test(item.className)) { spans.push(item); } } item = null; function linkTo(item) { return function() { document.getElementById("ftc-calendar-description").innerHTML = "" + item._date + "日:" + item.name +""; }; } for (i = 0; item = _monthEvent[i]; i++) { if (!item._date || !spans[item._date]) { break; } _className = spans[item._date].className; _className += " hasEvent"; if (_className.charAt(0) === " ") { _className = _className.substring(1); } spans[item._date].className = _className; spans[item._date].onclick = linkTo(item); } };