var MooCal = new Class({ initialize: function (elementID, options) {
    this.setOptions({ base: 1, x: 0, y: 0, calendarClass: "calendar", todayClass: "today", selectedClass: "selected", defaultYear: new Date().getFullYear(), defaultMonth: new Date().getMonth(), defaultDay: new Date().getDate(), dayNames: ["Sun", "Mon", "Tue", "Wed", "Thr", "Fri", "Sat", "Sun"], monthNames: ["Jan", "Feb", "Mar", "Apr", "May", "Jun", "Jul", "Aug", "Sep", "Oct", "Nov", "Dec"] }, options); this.calendarID = null; this.visible = true; this.displayTimer = 0; this.minYear = this.options.defaultYear; this.maxYear = this.options.defaultYear; this.elementID = elementID; this.yearElement = $(elementID + "-year"); this.monthElement = $(elementID + "-month"); this.dayElement = $(elementID + "-day"); this.chosenDate = new Date(); if (this.yearElement) { this.year = this.yearElement.getValue(); if (this.yearElement.getTag() == "select") { var totalOptions = this.yearElement.length - 1; if (totalOptions > 0) { var firstOptionValue = this.yearElement.options[0].value; var lastOptionValue = this.yearElement.options[totalOptions].value; if (firstOptionValue < lastOptionValue) { this.minYear = firstOptionValue; this.maxYear = lastOptionValue; } else { this.minYear = lastOptionValue; this.maxYear = firstOptionValue; } } } } else { this.year = this.options.defaultYear; }
    this.chosenDate.setYear(this.year); if (this.monthElement) { this.month = this.monthElement.getValue() - this.options.base; } else { this.month = this.options.defaultMonth; }
    this.chosenDate.setMonth(this.month); if (this.dayElement) { this.day = this.dayElement.getValue(); } else { this.day = this.options.defaultDay; }
    this.chosenDate.setDate(this.day); this.currentDate = this.chosenDate; this.monthAndYear = null;
}, show: function (x, y) {
    if (this.visible && this.calendarID == null) { this.calendarID = "calendar_" + Date.parse(new Date()); this.draw($pick(x, this.options.x), $pick(y, this.options.y)); } else { this.redraw(); $(this.calendarID).setStyles({ "display": "block", "left": $pick(x, this.options.x), "top": $pick(y, this.options.y) }); }
    this.visible = true;
}, hide: function () { if (this.visible) { $(this.calendarID).setStyle("display", "none"); this.visible = false; clearTimeout(this.displayTimer); } }, selectDate: function (e, d) {
    new Event(e).stop(); if ($type(d) != "number")
        return; this.currentDate.setDate(d); this.chosenDate = this.currentDate; if (this.yearElement)
        this.yearElement.setProperty("value", this.currentDate.getFullYear()); if (this.monthElement)
        this.monthElement.setProperty("value", this.currentDate.getMonth() + this.options.base); if (this.dayElement)
        this.dayElement.setProperty("value", this.currentDate.getDate()); if (!this.dayElement && !this.monthElement && !this.yearElement && $(this.elementID).getTag() == "input") { $(this.elementID).setProperty("value", this.currentDate.getDate() + " " + this.options.monthNames[this.currentDate.getMonth()] + " " + this.currentDate.getFullYear()); }
    this.hide();
}, setDates: function () { this.lastMonth = new Date(this.currentDate).setMonth(this.currentDate.getMonth() - 1); this.nextMonth = new Date(this.currentDate).setMonth(this.currentDate.getMonth() + 1); this.lastYear = new Date(this.currentDate).setFullYear(this.currentDate.getFullYear() - 1); this.nextYear = new Date(this.currentDate).setFullYear(this.currentDate.getFullYear() + 1); this.today = new Date(); }, repaint: function (e, d) {
    new Event(e).stop(); var dateToCheck = new Date(d); if (dateToCheck.getFullYear() < this.minYear || dateToCheck.getFullYear() > this.maxYear) { return; }
    this.currentDate = dateToCheck; this.setDates(); this.redraw();
}, mouseOver: function () { clearTimeout(this.displayTimer); }, mouseOut: function () { this.displayTimer = this.hide.delay(500, this); }, draw: function (x, y) {
    var tableContainer, table, thead, tbody, row, td; tableContainer = new Element("div", { "class": this.options.calendarClass, "id": this.calendarID, "events": { "mouseover": this.mouseOver.bind(this), "mouseout": this.mouseOut.bind(this)} })
.setStyles({ "position": "absolute", "left": x, "top": y }); table = new Element("table", { "id": this.calendarID + "-table", "class": this.calendarID + "-table" }); thead = new Element("thead").injectInside(table); row = new Element("tr").injectInside(thead); new Element("a", { "href": "#", "events": { "click": (function (e) { this.repaint(e, this.lastYear); }).bindWithEvent(this)} }).setHTML("&laquo;").injectInside(new Element("th", { "class": this.options.calendarClass + "-yearswitch" }).injectInside(row)); new Element("a", { "href": "#", "events": { "click": (function (e) { this.repaint(e, this.lastMonth); }).bindWithEvent(this)} }).setHTML("&#139;").injectInside(new Element("th", { "class": this.options.calendarClass + "-monthswitch" }).injectInside(row)); this.monthAndYear = new Element("th", { "colSpan": 3, "class": this.options.calendarClass + "-monthandyear" }).appendText(this.options.monthNames[this.currentDate.getMonth()] + " " + this.currentDate.getFullYear()).injectInside(row); new Element("a", { "href": "#", "events": { "click": (function (e) { this.repaint(e, this.nextMonth); }).bindWithEvent(this)} }).setHTML("&#155;").injectInside(new Element("th", { "class": this.options.calendarClass + "-monthswitch" }).injectInside(row)); new Element("a", { "href": "#", "events": { "click": (function (e) { this.repaint(e, this.nextYear); }).bindWithEvent(this)} }).setHTML("&raquo;").injectInside(new Element("th", { "class": this.options.calendarClass + "-yearswitch" }).injectInside(row)); row = new Element("tr").injectInside(thead); for (i = 0; i < 7; i++) { new Element("th").appendText(this.options.dayNames[i]).injectInside(row); }
    tbody = new Element("tbody").injectInside(table); for (r = 0; r < 6; r++) { row = new Element("tr").injectInside(tbody); for (c = 0; c < 7; c++) { td = new Element("td").injectInside(row); new Element("a", { "href": "#" }).setHTML("&nbsp;").injectInside(td); } }
    table.injectInside(tableContainer); tableContainer.injectInside(document.body); this.redraw();
}, redraw: function () {
    this.setDates(); this.monthAndYear.setText(this.options.monthNames[this.currentDate.getMonth()] + " " + this.currentDate.getFullYear()); var dates = $ES("tbody a", $(this.calendarID)); var firstDay = new Date(this.currentDate); firstDay.setDate(1); if (firstDay.getDay() > 0) { firstDay.setDate(-firstDay.getDay() + 1); }
    var currentDay = new Date(firstDay); var today = new Date(); for (i = 0; i < dates.length; i++) {
        var txt = "&nbsp;"; if (currentDay.getMonth() == this.currentDate.getMonth()) { txt = currentDay.getDate(); }
        $(dates[i]).removeClass(this.options.todayClass); $(dates[i]).removeClass(this.options.selectedClass); $(dates[i]).removeEvents(); $(dates[i]).addEvent("click", (function (e, day) { this.selectDate(e, day); }).bindWithEvent(this, txt)); $(dates[i]).setHTML(txt); if (currentDay.getDate() == today.getDate() && currentDay.getMonth() == today.getMonth() && currentDay.getFullYear() == today.getFullYear()) { $(dates[i]).addClass(this.options.todayClass); }
        if (this.currentDate.getMonth() == this.chosenDate.getMonth() && currentDay.getDate() == this.chosenDate.getDate() && currentDay.getMonth() == this.chosenDate.getMonth() && currentDay.getFullYear() == this.chosenDate.getFullYear()) { $(dates[i]).addClass(this.options.selectedClass); }
        currentDay.setDate(currentDay.getDate() + 1);
    } 
} 
}); MooCal.implement(new Options);
