You are viewing a plain text version of this content. The canonical link for it is here.
Posted to commits@tapestry.apache.org by hl...@apache.org on 2007/11/12 23:23:28 UTC

svn commit: r594319 [18/40] - in /tapestry/tapestry5/trunk: ./ tapestry-annotations/ tapestry-annotations/src/main/java/org/apache/tapestry/beaneditor/ tapestry-annotations/src/site/ tapestry-component-report/ tapestry-component-report/src/main/java/or...

Modified: tapestry/tapestry5/trunk/tapestry-core/src/main/resources/org/apache/tapestry/jscalendar-1.0/calendar.js
URL: http://svn.apache.org/viewvc/tapestry/tapestry5/trunk/tapestry-core/src/main/resources/org/apache/tapestry/jscalendar-1.0/calendar.js?rev=594319&r1=594318&r2=594319&view=diff
==============================================================================
--- tapestry/tapestry5/trunk/tapestry-core/src/main/resources/org/apache/tapestry/jscalendar-1.0/calendar.js (original)
+++ tapestry/tapestry5/trunk/tapestry-core/src/main/resources/org/apache/tapestry/jscalendar-1.0/calendar.js Mon Nov 12 14:22:31 2007
@@ -15,67 +15,71 @@
 // $Id: calendar.js,v 1.51 2005/03/07 16:44:31 mishoo Exp $
 
 /** The Calendar object constructor. */
-Calendar = function (firstDayOfWeek, dateStr, onSelected, onClose) {
-	// member variables
-	this.activeDiv = null;
-	this.currentDateEl = null;
-	this.getDateStatus = null;
-	this.getDateToolTip = null;
-	this.getDateText = null;
-	this.timeout = null;
-	this.onSelected = onSelected || null;
-	this.onClose = onClose || null;
-	this.dragging = false;
-	this.hidden = false;
-	this.minYear = 1970;
-	this.maxYear = 2050;
-	this.dateFormat = Calendar._TT["DEF_DATE_FORMAT"];
-	this.ttDateFormat = Calendar._TT["TT_DATE_FORMAT"];
-	this.isPopup = true;
-	this.weekNumbers = true;
-	this.firstDayOfWeek = typeof firstDayOfWeek == "number" ? firstDayOfWeek : Calendar._FD; // 0 for Sunday, 1 for Monday, etc.
-	this.showsOtherMonths = false;
-	this.dateStr = dateStr;
-	this.ar_days = null;
-	this.showsTime = false;
-	this.time24 = true;
-	this.yearStep = 2;
-	this.hiliteToday = true;
-	this.multiple = null;
+Calendar = function (firstDayOfWeek, dateStr, onSelected, onClose)
+{
+    // member variables
+    this.activeDiv = null;
+    this.currentDateEl = null;
+    this.getDateStatus = null;
+    this.getDateToolTip = null;
+    this.getDateText = null;
+    this.timeout = null;
+    this.onSelected = onSelected || null;
+    this.onClose = onClose || null;
+    this.dragging = false;
+    this.hidden = false;
+    this.minYear = 1970;
+    this.maxYear = 2050;
+    this.dateFormat = Calendar._TT["DEF_DATE_FORMAT"];
+    this.ttDateFormat = Calendar._TT["TT_DATE_FORMAT"];
+    this.isPopup = true;
+    this.weekNumbers = true;
+    this.firstDayOfWeek = typeof firstDayOfWeek == "number" ? firstDayOfWeek : Calendar._FD; // 0 for Sunday, 1 for Monday, etc.
+    this.showsOtherMonths = false;
+    this.dateStr = dateStr;
+    this.ar_days = null;
+    this.showsTime = false;
+    this.time24 = true;
+    this.yearStep = 2;
+    this.hiliteToday = true;
+    this.multiple = null;
 	// HTML elements
-	this.table = null;
-	this.element = null;
-	this.tbody = null;
-	this.firstdayname = null;
+    this.table = null;
+    this.element = null;
+    this.tbody = null;
+    this.firstdayname = null;
 	// Combo boxes
-	this.monthsCombo = null;
-	this.yearsCombo = null;
-	this.hilitedMonth = null;
-	this.activeMonth = null;
-	this.hilitedYear = null;
-	this.activeYear = null;
+    this.monthsCombo = null;
+    this.yearsCombo = null;
+    this.hilitedMonth = null;
+    this.activeMonth = null;
+    this.hilitedYear = null;
+    this.activeYear = null;
 	// Information
-	this.dateClicked = false;
+    this.dateClicked = false;
 
 	// one-time initializations
-	if (typeof Calendar._SDN == "undefined") {
-		// table of short day names
-		if (typeof Calendar._SDN_len == "undefined")
-			Calendar._SDN_len = 3;
-		var ar = new Array();
-		for (var i = 8; i > 0;) {
-			ar[--i] = Calendar._DN[i].substr(0, Calendar._SDN_len);
-		}
-		Calendar._SDN = ar;
+    if (typeof Calendar._SDN == "undefined")
+    {
+        // table of short day names
+        if (typeof Calendar._SDN_len == "undefined")
+            Calendar._SDN_len = 3;
+        var ar = new Array();
+        for (var i = 8; i > 0;)
+        {
+            ar[--i] = Calendar._DN[i].substr(0, Calendar._SDN_len);
+        }
+        Calendar._SDN = ar;
 		// table of short month names
-		if (typeof Calendar._SMN_len == "undefined")
-			Calendar._SMN_len = 3;
-		ar = new Array();
-		for (var i = 12; i > 0;) {
-			ar[--i] = Calendar._MN[i].substr(0, Calendar._SMN_len);
-		}
-		Calendar._SMN = ar;
-	}
+        if (typeof Calendar._SMN_len == "undefined")
+            Calendar._SMN_len = 3;
+        ar = new Array();
+        for (var i = 12; i > 0;)
+        {
+            ar[--i] = Calendar._MN[i].substr(0, Calendar._SMN_len);
+        }
+        Calendar._SMN = ar;
+    }
 };
 
 // ** constants
@@ -85,7 +89,7 @@
 
 /// detect a special case of "web browser"
 Calendar.is_ie = ( /msie/i.test(navigator.userAgent) &&
-		   !/opera/i.test(navigator.userAgent) );
+                   !/opera/i.test(navigator.userAgent) );
 
 Calendar.is_ie5 = ( Calendar.is_ie && /msie 5\.0/i.test(navigator.userAgent) );
 
@@ -98,120 +102,157 @@
 // BEGIN: UTILITY FUNCTIONS; beware that these might be moved into a separate
 //        library, at some point.
 
-Calendar.getAbsolutePos = function(el) {
-	var SL = 0, ST = 0;
-	var is_div = /^div$/i.test(el.tagName);
-	if (is_div && el.scrollLeft)
-		SL = el.scrollLeft;
-	if (is_div && el.scrollTop)
-		ST = el.scrollTop;
-	var r = { x: el.offsetLeft - SL, y: el.offsetTop - ST };
-	if (el.offsetParent) {
-		var tmp = this.getAbsolutePos(el.offsetParent);
-		r.x += tmp.x;
-		r.y += tmp.y;
-	}
-	return r;
-};
-
-Calendar.isRelated = function (el, evt) {
-	var related = evt.relatedTarget;
-	if (!related) {
-		var type = evt.type;
-		if (type == "mouseover") {
-			related = evt.fromElement;
-		} else if (type == "mouseout") {
-			related = evt.toElement;
-		}
-	}
-	while (related) {
-		if (related == el) {
-			return true;
-		}
-		related = related.parentNode;
-	}
-	return false;
-};
-
-Calendar.removeClass = function(el, className) {
-	if (!(el && el.className)) {
-		return;
-	}
-	var cls = el.className.split(" ");
-	var ar = new Array();
-	for (var i = cls.length; i > 0;) {
-		if (cls[--i] != className) {
-			ar[ar.length] = cls[i];
-		}
-	}
-	el.className = ar.join(" ");
-};
-
-Calendar.addClass = function(el, className) {
-	Calendar.removeClass(el, className);
-	el.className += " " + className;
+Calendar.getAbsolutePos = function(el)
+{
+    var SL = 0, ST = 0;
+    var is_div = /^div$/i.test(el.tagName);
+    if (is_div && el.scrollLeft)
+        SL = el.scrollLeft;
+    if (is_div && el.scrollTop)
+        ST = el.scrollTop;
+    var r = { x: el.offsetLeft - SL, y: el.offsetTop - ST };
+    if (el.offsetParent)
+    {
+        var tmp = this.getAbsolutePos(el.offsetParent);
+        r.x += tmp.x;
+        r.y += tmp.y;
+    }
+    return r;
+};
+
+Calendar.isRelated = function (el, evt)
+{
+    var related = evt.relatedTarget;
+    if (!related)
+    {
+        var type = evt.type;
+        if (type == "mouseover")
+        {
+            related = evt.fromElement;
+        }
+        else if (type == "mouseout")
+        {
+            related = evt.toElement;
+        }
+    }
+    while (related)
+    {
+        if (related == el)
+        {
+            return true;
+        }
+        related = related.parentNode;
+    }
+    return false;
+};
+
+Calendar.removeClass = function(el, className)
+{
+    if (!(el && el.className))
+    {
+        return;
+    }
+    var cls = el.className.split(" ");
+    var ar = new Array();
+    for (var i = cls.length; i > 0;)
+    {
+        if (cls[--i] != className)
+        {
+            ar[ar.length] = cls[i];
+        }
+    }
+    el.className = ar.join(" ");
+};
+
+Calendar.addClass = function(el, className)
+{
+    Calendar.removeClass(el, className);
+    el.className += " " + className;
 };
 
 // FIXME: the following 2 functions totally suck, are useless and should be replaced immediately.
-Calendar.getElement = function(ev) {
-	var f = Calendar.is_ie ? window.event.srcElement : ev.currentTarget;
-	while (f.nodeType != 1 || /^div$/i.test(f.tagName))
-		f = f.parentNode;
-	return f;
-};
-
-Calendar.getTargetElement = function(ev) {
-	var f = Calendar.is_ie ? window.event.srcElement : ev.target;
-	while (f.nodeType != 1)
-		f = f.parentNode;
-	return f;
-};
-
-Calendar.stopEvent = function(ev) {
-	ev || (ev = window.event);
-	if (Calendar.is_ie) {
-		ev.cancelBubble = true;
-		ev.returnValue = false;
-	} else {
-		ev.preventDefault();
-		ev.stopPropagation();
-	}
-	return false;
-};
-
-Calendar.addEvent = function(el, evname, func) {
-	if (el.attachEvent) { // IE
-		el.attachEvent("on" + evname, func);
-	} else if (el.addEventListener) { // Gecko / W3C
-		el.addEventListener(evname, func, true);
-	} else {
-		el["on" + evname] = func;
-	}
-};
-
-Calendar.removeEvent = function(el, evname, func) {
-	if (el.detachEvent) { // IE
-		el.detachEvent("on" + evname, func);
-	} else if (el.removeEventListener) { // Gecko / W3C
-		el.removeEventListener(evname, func, true);
-	} else {
-		el["on" + evname] = null;
-	}
-};
-
-Calendar.createElement = function(type, parent) {
-	var el = null;
-	if (document.createElementNS) {
-		// use the XHTML namespace; IE won't normally get here unless
-		// _they_ "fix" the DOM2 implementation.
-		el = document.createElementNS("http://www.w3.org/1999/xhtml", type);
-	} else {
-		el = document.createElement(type);
-	}
-	if (typeof parent != "undefined") {
-		parent.appendChild(el);
-	}
-	return el;
+Calendar.getElement = function(ev)
+{
+    var f = Calendar.is_ie ? window.event.srcElement : ev.currentTarget;
+    while (f.nodeType != 1 || /^div$/i.test(f.tagName))
+        f = f.parentNode;
+    return f;
+};
+
+Calendar.getTargetElement = function(ev)
+{
+    var f = Calendar.is_ie ? window.event.srcElement : ev.target;
+    while (f.nodeType != 1)
+        f = f.parentNode;
+    return f;
+};
+
+Calendar.stopEvent = function(ev)
+{
+    ev || (ev = window.event);
+    if (Calendar.is_ie)
+    {
+        ev.cancelBubble = true;
+        ev.returnValue = false;
+    }
+    else
+    {
+        ev.preventDefault();
+        ev.stopPropagation();
+    }
+    return false;
+};
+
+Calendar.addEvent = function(el, evname, func)
+{
+    if (el.attachEvent)
+    { // IE
+        el.attachEvent("on" + evname, func);
+    }
+    else if (el.addEventListener)
+    { // Gecko / W3C
+        el.addEventListener(evname, func, true);
+    }
+    else
+    {
+        el["on" + evname] = func;
+    }
+};
+
+Calendar.removeEvent = function(el, evname, func)
+{
+    if (el.detachEvent)
+    { // IE
+        el.detachEvent("on" + evname, func);
+    }
+    else if (el.removeEventListener)
+    { // Gecko / W3C
+        el.removeEventListener(evname, func, true);
+    }
+    else
+    {
+        el["on" + evname] = null;
+    }
+};
+
+Calendar.createElement = function(type, parent)
+{
+    var el = null;
+    if (document.createElementNS)
+    {
+        // use the XHTML namespace; IE won't normally get here unless
+        // _they_ "fix" the DOM2 implementation.
+        el = document.createElementNS("http://www.w3.org/1999/xhtml", type);
+    }
+    else
+    {
+        el = document.createElement(type);
+    }
+    if (typeof parent != "undefined")
+    {
+        parent.appendChild(el);
+    }
+    return el;
 };
 
 // END: UTILITY FUNCTIONS
@@ -219,492 +260,616 @@
 // BEGIN: CALENDAR STATIC FUNCTIONS
 
 /** Internal -- adds a set of events to make some element behave like a button. */
-Calendar._add_evs = function(el) {
-	with (Calendar) {
-		addEvent(el, "mouseover", dayMouseOver);
-		addEvent(el, "mousedown", dayMouseDown);
-		addEvent(el, "mouseout", dayMouseOut);
-		if (is_ie) {
-			addEvent(el, "dblclick", dayMouseDblClick);
-			el.setAttribute("unselectable", true);
-		}
-	}
-};
-
-Calendar.findMonth = function(el) {
-	if (typeof el.month != "undefined") {
-		return el;
-	} else if (typeof el.parentNode.month != "undefined") {
-		return el.parentNode;
-	}
-	return null;
-};
-
-Calendar.findYear = function(el) {
-	if (typeof el.year != "undefined") {
-		return el;
-	} else if (typeof el.parentNode.year != "undefined") {
-		return el.parentNode;
-	}
-	return null;
-};
-
-Calendar.showMonthsCombo = function () {
-	var cal = Calendar._C;
-	if (!cal) {
-		return false;
-	}
-	var cal = cal;
-	var cd = cal.activeDiv;
-	var mc = cal.monthsCombo;
-	if (cal.hilitedMonth) {
-		Calendar.removeClass(cal.hilitedMonth, "hilite");
-	}
-	if (cal.activeMonth) {
-		Calendar.removeClass(cal.activeMonth, "active");
-	}
-	var mon = cal.monthsCombo.getElementsByTagName("div")[cal.date.getMonth()];
-	Calendar.addClass(mon, "active");
-	cal.activeMonth = mon;
-	var s = mc.style;
-	s.display = "block";
-	if (cd.navtype < 0)
-		s.left = cd.offsetLeft + "px";
-	else {
-		var mcw = mc.offsetWidth;
-		if (typeof mcw == "undefined")
-			// Konqueror brain-dead techniques
-			mcw = 50;
-		s.left = (cd.offsetLeft + cd.offsetWidth - mcw) + "px";
-	}
-	s.top = (cd.offsetTop + cd.offsetHeight) + "px";
-};
-
-Calendar.showYearsCombo = function (fwd) {
-	var cal = Calendar._C;
-	if (!cal) {
-		return false;
-	}
-	var cal = cal;
-	var cd = cal.activeDiv;
-	var yc = cal.yearsCombo;
-	if (cal.hilitedYear) {
-		Calendar.removeClass(cal.hilitedYear, "hilite");
-	}
-	if (cal.activeYear) {
-		Calendar.removeClass(cal.activeYear, "active");
-	}
-	cal.activeYear = null;
-	var Y = cal.date.getFullYear() + (fwd ? 1 : -1);
-	var yr = yc.firstChild;
-	var show = false;
-	for (var i = 12; i > 0; --i) {
-		if (Y >= cal.minYear && Y <= cal.maxYear) {
-			yr.innerHTML = Y;
-			yr.year = Y;
-			yr.style.display = "block";
-			show = true;
-		} else {
-			yr.style.display = "none";
-		}
-		yr = yr.nextSibling;
-		Y += fwd ? cal.yearStep : -cal.yearStep;
-	}
-	if (show) {
-		var s = yc.style;
-		s.display = "block";
-		if (cd.navtype < 0)
-			s.left = cd.offsetLeft + "px";
-		else {
-			var ycw = yc.offsetWidth;
-			if (typeof ycw == "undefined")
-				// Konqueror brain-dead techniques
-				ycw = 50;
-			s.left = (cd.offsetLeft + cd.offsetWidth - ycw) + "px";
-		}
-		s.top = (cd.offsetTop + cd.offsetHeight) + "px";
-	}
+Calendar._add_evs = function(el)
+{
+    with (Calendar)
+    {
+        addEvent(el, "mouseover", dayMouseOver);
+        addEvent(el, "mousedown", dayMouseDown);
+        addEvent(el, "mouseout", dayMouseOut);
+        if (is_ie)
+        {
+            addEvent(el, "dblclick", dayMouseDblClick);
+            el.setAttribute("unselectable", true);
+        }
+    }
+};
+
+Calendar.findMonth = function(el)
+{
+    if (typeof el.month != "undefined")
+    {
+        return el;
+    }
+    else if (typeof el.parentNode.month != "undefined")
+    {
+        return el.parentNode;
+    }
+    return null;
+};
+
+Calendar.findYear = function(el)
+{
+    if (typeof el.year != "undefined")
+    {
+        return el;
+    }
+    else if (typeof el.parentNode.year != "undefined")
+    {
+        return el.parentNode;
+    }
+    return null;
+};
+
+Calendar.showMonthsCombo = function ()
+{
+    var cal = Calendar._C;
+    if (!cal)
+    {
+        return false;
+    }
+    var cal = cal;
+    var cd = cal.activeDiv;
+    var mc = cal.monthsCombo;
+    if (cal.hilitedMonth)
+    {
+        Calendar.removeClass(cal.hilitedMonth, "hilite");
+    }
+    if (cal.activeMonth)
+    {
+        Calendar.removeClass(cal.activeMonth, "active");
+    }
+    var mon = cal.monthsCombo.getElementsByTagName("div")[cal.date.getMonth()];
+    Calendar.addClass(mon, "active");
+    cal.activeMonth = mon;
+    var s = mc.style;
+    s.display = "block";
+    if (cd.navtype < 0)
+        s.left = cd.offsetLeft + "px";
+    else
+    {
+        var mcw = mc.offsetWidth;
+        if (typeof mcw == "undefined")
+        // Konqueror brain-dead techniques
+            mcw = 50;
+        s.left = (cd.offsetLeft + cd.offsetWidth - mcw) + "px";
+    }
+    s.top = (cd.offsetTop + cd.offsetHeight) + "px";
+};
+
+Calendar.showYearsCombo = function (fwd)
+{
+    var cal = Calendar._C;
+    if (!cal)
+    {
+        return false;
+    }
+    var cal = cal;
+    var cd = cal.activeDiv;
+    var yc = cal.yearsCombo;
+    if (cal.hilitedYear)
+    {
+        Calendar.removeClass(cal.hilitedYear, "hilite");
+    }
+    if (cal.activeYear)
+    {
+        Calendar.removeClass(cal.activeYear, "active");
+    }
+    cal.activeYear = null;
+    var Y = cal.date.getFullYear() + (fwd ? 1 : -1);
+    var yr = yc.firstChild;
+    var show = false;
+    for (var i = 12; i > 0; --i)
+    {
+        if (Y >= cal.minYear && Y <= cal.maxYear)
+        {
+            yr.innerHTML = Y;
+            yr.year = Y;
+            yr.style.display = "block";
+            show = true;
+        }
+        else
+        {
+            yr.style.display = "none";
+        }
+        yr = yr.nextSibling;
+        Y += fwd ? cal.yearStep : -cal.yearStep;
+    }
+    if (show)
+    {
+        var s = yc.style;
+        s.display = "block";
+        if (cd.navtype < 0)
+            s.left = cd.offsetLeft + "px";
+        else
+        {
+            var ycw = yc.offsetWidth;
+            if (typeof ycw == "undefined")
+            // Konqueror brain-dead techniques
+                ycw = 50;
+            s.left = (cd.offsetLeft + cd.offsetWidth - ycw) + "px";
+        }
+        s.top = (cd.offsetTop + cd.offsetHeight) + "px";
+    }
 };
 
 // event handlers
 
-Calendar.tableMouseUp = function(ev) {
-	var cal = Calendar._C;
-	if (!cal) {
-		return false;
-	}
-	if (cal.timeout) {
-		clearTimeout(cal.timeout);
-	}
-	var el = cal.activeDiv;
-	if (!el) {
-		return false;
-	}
-	var target = Calendar.getTargetElement(ev);
-	ev || (ev = window.event);
-	Calendar.removeClass(el, "active");
-	if (target == el || target.parentNode == el) {
-		Calendar.cellClick(el, ev);
-	}
-	var mon = Calendar.findMonth(target);
-	var date = null;
-	if (mon) {
-		date = new Date(cal.date);
-		if (mon.month != date.getMonth()) {
-			date.setMonth(mon.month);
-			cal.setDate(date);
-			cal.dateClicked = false;
-			cal.callHandler();
-		}
-	} else {
-		var year = Calendar.findYear(target);
-		if (year) {
-			date = new Date(cal.date);
-			if (year.year != date.getFullYear()) {
-				date.setFullYear(year.year);
-				cal.setDate(date);
-				cal.dateClicked = false;
-				cal.callHandler();
-			}
-		}
-	}
-	with (Calendar) {
-		removeEvent(document, "mouseup", tableMouseUp);
-		removeEvent(document, "mouseover", tableMouseOver);
-		removeEvent(document, "mousemove", tableMouseOver);
-		cal._hideCombos();
-		_C = null;
-		return stopEvent(ev);
-	}
-};
-
-Calendar.tableMouseOver = function (ev) {
-	var cal = Calendar._C;
-	if (!cal) {
-		return;
-	}
-	var el = cal.activeDiv;
-	var target = Calendar.getTargetElement(ev);
-	if (target == el || target.parentNode == el) {
-		Calendar.addClass(el, "hilite active");
-		Calendar.addClass(el.parentNode, "rowhilite");
-	} else {
-		if (typeof el.navtype == "undefined" || (el.navtype != 50 && (el.navtype == 0 || Math.abs(el.navtype) > 2)))
-			Calendar.removeClass(el, "active");
-		Calendar.removeClass(el, "hilite");
-		Calendar.removeClass(el.parentNode, "rowhilite");
-	}
-	ev || (ev = window.event);
-	if (el.navtype == 50 && target != el) {
-		var pos = Calendar.getAbsolutePos(el);
-		var w = el.offsetWidth;
-		var x = ev.clientX;
-		var dx;
-		var decrease = true;
-		if (x > pos.x + w) {
-			dx = x - pos.x - w;
-			decrease = false;
-		} else
-			dx = pos.x - x;
-
-		if (dx < 0) dx = 0;
-		var range = el._range;
-		var current = el._current;
-		var count = Math.floor(dx / 10) % range.length;
-		for (var i = range.length; --i >= 0;)
-			if (range[i] == current)
-				break;
-		while (count-- > 0)
-			if (decrease) {
-				if (--i < 0)
-					i = range.length - 1;
-			} else if ( ++i >= range.length )
-				i = 0;
-		var newval = range[i];
-		el.innerHTML = newval;
-
-		cal.onUpdateTime();
-	}
-	var mon = Calendar.findMonth(target);
-	if (mon) {
-		if (mon.month != cal.date.getMonth()) {
-			if (cal.hilitedMonth) {
-				Calendar.removeClass(cal.hilitedMonth, "hilite");
-			}
-			Calendar.addClass(mon, "hilite");
-			cal.hilitedMonth = mon;
-		} else if (cal.hilitedMonth) {
-			Calendar.removeClass(cal.hilitedMonth, "hilite");
-		}
-	} else {
-		if (cal.hilitedMonth) {
-			Calendar.removeClass(cal.hilitedMonth, "hilite");
-		}
-		var year = Calendar.findYear(target);
-		if (year) {
-			if (year.year != cal.date.getFullYear()) {
-				if (cal.hilitedYear) {
-					Calendar.removeClass(cal.hilitedYear, "hilite");
-				}
-				Calendar.addClass(year, "hilite");
-				cal.hilitedYear = year;
-			} else if (cal.hilitedYear) {
-				Calendar.removeClass(cal.hilitedYear, "hilite");
-			}
-		} else if (cal.hilitedYear) {
-			Calendar.removeClass(cal.hilitedYear, "hilite");
-		}
-	}
-	return Calendar.stopEvent(ev);
-};
-
-Calendar.tableMouseDown = function (ev) {
-	if (Calendar.getTargetElement(ev) == Calendar.getElement(ev)) {
-		return Calendar.stopEvent(ev);
-	}
-};
-
-Calendar.calDragIt = function (ev) {
-	var cal = Calendar._C;
-	if (!(cal && cal.dragging)) {
-		return false;
-	}
-	var posX;
-	var posY;
-	if (Calendar.is_ie) {
-		posY = window.event.clientY + document.body.scrollTop;
-		posX = window.event.clientX + document.body.scrollLeft;
-	} else {
-		posX = ev.pageX;
-		posY = ev.pageY;
-	}
-	cal.hideShowCovered();
-	var st = cal.element.style;
-	st.left = (posX - cal.xOffs) + "px";
-	st.top = (posY - cal.yOffs) + "px";
-	return Calendar.stopEvent(ev);
-};
-
-Calendar.calDragEnd = function (ev) {
-	var cal = Calendar._C;
-	if (!cal) {
-		return false;
-	}
-	cal.dragging = false;
-	with (Calendar) {
-		removeEvent(document, "mousemove", calDragIt);
-		removeEvent(document, "mouseup", calDragEnd);
-		tableMouseUp(ev);
-	}
-	cal.hideShowCovered();
-};
-
-Calendar.dayMouseDown = function(ev) {
-	var el = Calendar.getElement(ev);
-	if (el.disabled) {
-		return false;
-	}
-	var cal = el.calendar;
-	cal.activeDiv = el;
-	Calendar._C = cal;
-	if (el.navtype != 300) with (Calendar) {
-		if (el.navtype == 50) {
-			el._current = el.innerHTML;
-			addEvent(document, "mousemove", tableMouseOver);
-		} else
-			addEvent(document, Calendar.is_ie5 ? "mousemove" : "mouseover", tableMouseOver);
-		addClass(el, "hilite active");
-		addEvent(document, "mouseup", tableMouseUp);
-	} else if (cal.isPopup) {
-		cal._dragStart(ev);
-	}
-	if (el.navtype == -1 || el.navtype == 1) {
-		if (cal.timeout) clearTimeout(cal.timeout);
-		cal.timeout = setTimeout("Calendar.showMonthsCombo()", 250);
-	} else if (el.navtype == -2 || el.navtype == 2) {
-		if (cal.timeout) clearTimeout(cal.timeout);
-		cal.timeout = setTimeout((el.navtype > 0) ? "Calendar.showYearsCombo(true)" : "Calendar.showYearsCombo(false)", 250);
-	} else {
-		cal.timeout = null;
-	}
-	return Calendar.stopEvent(ev);
-};
-
-Calendar.dayMouseDblClick = function(ev) {
-	Calendar.cellClick(Calendar.getElement(ev), ev || window.event);
-	if (Calendar.is_ie) {
-		document.selection.empty();
-	}
-};
-
-Calendar.dayMouseOver = function(ev) {
-	var el = Calendar.getElement(ev);
-	if (Calendar.isRelated(el, ev) || Calendar._C || el.disabled) {
-		return false;
-	}
-	if (el.ttip) {
-		if (el.ttip.substr(0, 1) == "_") {
-			el.ttip = el.caldate.print(el.calendar.ttDateFormat) + el.ttip.substr(1);
-		}
-		el.calendar.tooltips.innerHTML = el.ttip;
-	}
-	if (el.navtype != 300) {
-		Calendar.addClass(el, "hilite");
-		if (el.caldate) {
-			Calendar.addClass(el.parentNode, "rowhilite");
-		}
-	}
-	return Calendar.stopEvent(ev);
-};
-
-Calendar.dayMouseOut = function(ev) {
-	with (Calendar) {
-		var el = getElement(ev);
-		if (isRelated(el, ev) || _C || el.disabled)
-			return false;
-		removeClass(el, "hilite");
-		if (el.caldate)
-			removeClass(el.parentNode, "rowhilite");
-		if (el.calendar)
-			el.calendar.tooltips.innerHTML = _TT["SEL_DATE"];
-		return stopEvent(ev);
-	}
+Calendar.tableMouseUp = function(ev)
+{
+    var cal = Calendar._C;
+    if (!cal)
+    {
+        return false;
+    }
+    if (cal.timeout)
+    {
+        clearTimeout(cal.timeout);
+    }
+    var el = cal.activeDiv;
+    if (!el)
+    {
+        return false;
+    }
+    var target = Calendar.getTargetElement(ev);
+    ev || (ev = window.event);
+    Calendar.removeClass(el, "active");
+    if (target == el || target.parentNode == el)
+    {
+        Calendar.cellClick(el, ev);
+    }
+    var mon = Calendar.findMonth(target);
+    var date = null;
+    if (mon)
+    {
+        date = new Date(cal.date);
+        if (mon.month != date.getMonth())
+        {
+            date.setMonth(mon.month);
+            cal.setDate(date);
+            cal.dateClicked = false;
+            cal.callHandler();
+        }
+    }
+    else
+    {
+        var year = Calendar.findYear(target);
+        if (year)
+        {
+            date = new Date(cal.date);
+            if (year.year != date.getFullYear())
+            {
+                date.setFullYear(year.year);
+                cal.setDate(date);
+                cal.dateClicked = false;
+                cal.callHandler();
+            }
+        }
+    }
+    with (Calendar)
+    {
+        removeEvent(document, "mouseup", tableMouseUp);
+        removeEvent(document, "mouseover", tableMouseOver);
+        removeEvent(document, "mousemove", tableMouseOver);
+        cal._hideCombos();
+        _C = null;
+        return stopEvent(ev);
+    }
+};
+
+Calendar.tableMouseOver = function (ev)
+{
+    var cal = Calendar._C;
+    if (!cal)
+    {
+        return;
+    }
+    var el = cal.activeDiv;
+    var target = Calendar.getTargetElement(ev);
+    if (target == el || target.parentNode == el)
+    {
+        Calendar.addClass(el, "hilite active");
+        Calendar.addClass(el.parentNode, "rowhilite");
+    }
+    else
+    {
+        if (typeof el.navtype == "undefined" || (el.navtype != 50 && (el.navtype == 0 || Math.abs(el.navtype) > 2)))
+            Calendar.removeClass(el, "active");
+        Calendar.removeClass(el, "hilite");
+        Calendar.removeClass(el.parentNode, "rowhilite");
+    }
+    ev || (ev = window.event);
+    if (el.navtype == 50 && target != el)
+    {
+        var pos = Calendar.getAbsolutePos(el);
+        var w = el.offsetWidth;
+        var x = ev.clientX;
+        var dx;
+        var decrease = true;
+        if (x > pos.x + w)
+        {
+            dx = x - pos.x - w;
+            decrease = false;
+        }
+        else
+            dx = pos.x - x;
+
+        if (dx < 0) dx = 0;
+        var range = el._range;
+        var current = el._current;
+        var count = Math.floor(dx / 10) % range.length;
+        for (var i = range.length; --i >= 0;)
+            if (range[i] == current)
+                break;
+        while (count-- > 0)
+            if (decrease)
+            {
+                if (--i < 0)
+                    i = range.length - 1;
+            }
+            else if (++i >= range.length)
+                i = 0;
+        var newval = range[i];
+        el.innerHTML = newval;
+
+        cal.onUpdateTime();
+    }
+    var mon = Calendar.findMonth(target);
+    if (mon)
+    {
+        if (mon.month != cal.date.getMonth())
+        {
+            if (cal.hilitedMonth)
+            {
+                Calendar.removeClass(cal.hilitedMonth, "hilite");
+            }
+            Calendar.addClass(mon, "hilite");
+            cal.hilitedMonth = mon;
+        }
+        else if (cal.hilitedMonth)
+        {
+            Calendar.removeClass(cal.hilitedMonth, "hilite");
+        }
+    }
+    else
+    {
+        if (cal.hilitedMonth)
+        {
+            Calendar.removeClass(cal.hilitedMonth, "hilite");
+        }
+        var year = Calendar.findYear(target);
+        if (year)
+        {
+            if (year.year != cal.date.getFullYear())
+            {
+                if (cal.hilitedYear)
+                {
+                    Calendar.removeClass(cal.hilitedYear, "hilite");
+                }
+                Calendar.addClass(year, "hilite");
+                cal.hilitedYear = year;
+            }
+            else if (cal.hilitedYear)
+            {
+                Calendar.removeClass(cal.hilitedYear, "hilite");
+            }
+        }
+        else if (cal.hilitedYear)
+        {
+            Calendar.removeClass(cal.hilitedYear, "hilite");
+        }
+    }
+    return Calendar.stopEvent(ev);
+};
+
+Calendar.tableMouseDown = function (ev)
+{
+    if (Calendar.getTargetElement(ev) == Calendar.getElement(ev))
+    {
+        return Calendar.stopEvent(ev);
+    }
+};
+
+Calendar.calDragIt = function (ev)
+{
+    var cal = Calendar._C;
+    if (!(cal && cal.dragging))
+    {
+        return false;
+    }
+    var posX;
+    var posY;
+    if (Calendar.is_ie)
+    {
+        posY = window.event.clientY + document.body.scrollTop;
+        posX = window.event.clientX + document.body.scrollLeft;
+    }
+    else
+    {
+        posX = ev.pageX;
+        posY = ev.pageY;
+    }
+    cal.hideShowCovered();
+    var st = cal.element.style;
+    st.left = (posX - cal.xOffs) + "px";
+    st.top = (posY - cal.yOffs) + "px";
+    return Calendar.stopEvent(ev);
+};
+
+Calendar.calDragEnd = function (ev)
+{
+    var cal = Calendar._C;
+    if (!cal)
+    {
+        return false;
+    }
+    cal.dragging = false;
+    with (Calendar)
+    {
+        removeEvent(document, "mousemove", calDragIt);
+        removeEvent(document, "mouseup", calDragEnd);
+        tableMouseUp(ev);
+    }
+    cal.hideShowCovered();
+};
+
+Calendar.dayMouseDown = function(ev)
+{
+    var el = Calendar.getElement(ev);
+    if (el.disabled)
+    {
+        return false;
+    }
+    var cal = el.calendar;
+    cal.activeDiv = el;
+    Calendar._C = cal;
+    if (el.navtype != 300) with (Calendar)
+    {
+        if (el.navtype == 50)
+        {
+            el._current = el.innerHTML;
+            addEvent(document, "mousemove", tableMouseOver);
+        }
+        else
+            addEvent(document, Calendar.is_ie5 ? "mousemove" : "mouseover", tableMouseOver);
+        addClass(el, "hilite active");
+        addEvent(document, "mouseup", tableMouseUp);
+    }
+    else if (cal.isPopup)
+    {
+        cal._dragStart(ev);
+    }
+    if (el.navtype == -1 || el.navtype == 1)
+    {
+        if (cal.timeout) clearTimeout(cal.timeout);
+        cal.timeout = setTimeout("Calendar.showMonthsCombo()", 250);
+    }
+    else if (el.navtype == -2 || el.navtype == 2)
+    {
+        if (cal.timeout) clearTimeout(cal.timeout);
+        cal.timeout = setTimeout((el.navtype > 0) ? "Calendar.showYearsCombo(true)" : "Calendar.showYearsCombo(false)", 250);
+    }
+    else
+    {
+        cal.timeout = null;
+    }
+    return Calendar.stopEvent(ev);
+};
+
+Calendar.dayMouseDblClick = function(ev)
+{
+    Calendar.cellClick(Calendar.getElement(ev), ev || window.event);
+    if (Calendar.is_ie)
+    {
+        document.selection.empty();
+    }
+};
+
+Calendar.dayMouseOver = function(ev)
+{
+    var el = Calendar.getElement(ev);
+    if (Calendar.isRelated(el, ev) || Calendar._C || el.disabled)
+    {
+        return false;
+    }
+    if (el.ttip)
+    {
+        if (el.ttip.substr(0, 1) == "_")
+        {
+            el.ttip = el.caldate.print(el.calendar.ttDateFormat) + el.ttip.substr(1);
+        }
+        el.calendar.tooltips.innerHTML = el.ttip;
+    }
+    if (el.navtype != 300)
+    {
+        Calendar.addClass(el, "hilite");
+        if (el.caldate)
+        {
+            Calendar.addClass(el.parentNode, "rowhilite");
+        }
+    }
+    return Calendar.stopEvent(ev);
+};
+
+Calendar.dayMouseOut = function(ev)
+{
+    with (Calendar)
+    {
+        var el = getElement(ev);
+        if (isRelated(el, ev) || _C || el.disabled)
+            return false;
+        removeClass(el, "hilite");
+        if (el.caldate)
+            removeClass(el.parentNode, "rowhilite");
+        if (el.calendar)
+            el.calendar.tooltips.innerHTML = _TT["SEL_DATE"];
+        return stopEvent(ev);
+    }
 };
 
 /**
  *  A generic "click" handler :) handles all types of buttons defined in this
  *  calendar.
  */
-Calendar.cellClick = function(el, ev) {
-	var cal = el.calendar;
-	var closing = false;
-	var newdate = false;
-	var date = null;
-	if (typeof el.navtype == "undefined") {
-		if (cal.currentDateEl) {
-			Calendar.removeClass(cal.currentDateEl, "selected");
-			Calendar.addClass(el, "selected");
-			closing = (cal.currentDateEl == el);
-			if (!closing) {
-				cal.currentDateEl = el;
-			}
-		}
-		cal.date.setDateOnly(el.caldate);
-		date = cal.date;
-		var other_month = !(cal.dateClicked = !el.otherMonth);
-		if (!other_month && !cal.currentDateEl)
-			cal._toggleMultipleDate(new Date(date));
-		else
-			newdate = !el.disabled;
+Calendar.cellClick = function(el, ev)
+{
+    var cal = el.calendar;
+    var closing = false;
+    var newdate = false;
+    var date = null;
+    if (typeof el.navtype == "undefined")
+    {
+        if (cal.currentDateEl)
+        {
+            Calendar.removeClass(cal.currentDateEl, "selected");
+            Calendar.addClass(el, "selected");
+            closing = (cal.currentDateEl == el);
+            if (!closing)
+            {
+                cal.currentDateEl = el;
+            }
+        }
+        cal.date.setDateOnly(el.caldate);
+        date = cal.date;
+        var other_month = !(cal.dateClicked = !el.otherMonth);
+        if (!other_month && !cal.currentDateEl)
+            cal._toggleMultipleDate(new Date(date));
+        else
+            newdate = !el.disabled;
 		// a date was clicked
-		if (other_month)
-			cal._init(cal.firstDayOfWeek, date);
-	} else {
-		if (el.navtype == 200) {
-			Calendar.removeClass(el, "hilite");
-			cal.callCloseHandler();
-			return;
-		}
-		date = new Date(cal.date);
-		if (el.navtype == 0)
-			date.setDateOnly(new Date()); // TODAY
-		// unless "today" was clicked, we assume no date was clicked so
-		// the selected handler will know not to close the calenar when
-		// in single-click mode.
-		// cal.dateClicked = (el.navtype == 0);
-		cal.dateClicked = false;
-		var year = date.getFullYear();
-		var mon = date.getMonth();
-		function setMonth(m) {
-			var day = date.getDate();
-			var max = date.getMonthDays(m);
-			if (day > max) {
-				date.setDate(max);
-			}
-			date.setMonth(m);
-		};
-		switch (el.navtype) {
-		    case 400:
-			Calendar.removeClass(el, "hilite");
-			var text = Calendar._TT["ABOUT"];
-			if (typeof text != "undefined") {
-				text += cal.showsTime ? Calendar._TT["ABOUT_TIME"] : "";
-			} else {
-				// FIXME: this should be removed as soon as lang files get updated!
-				text = "Help and about box text is not translated into this language.\n" +
-					"If you know this language and you feel generous please update\n" +
-					"the corresponding file in \"lang\" subdir to match calendar-en.js\n" +
-					"and send it back to <mi...@yahoo.com> to get it into the distribution  ;-)\n\n" +
-					"Thank you!\n" +
-					"http://dynarch.com/mishoo/calendar.epl\n";
-			}
-			alert(text);
-			return;
-		    case -2:
-			if (year > cal.minYear) {
-				date.setFullYear(year - 1);
-			}
-			break;
-		    case -1:
-			if (mon > 0) {
-				setMonth(mon - 1);
-			} else if (year-- > cal.minYear) {
-				date.setFullYear(year);
-				setMonth(11);
-			}
-			break;
-		    case 1:
-			if (mon < 11) {
-				setMonth(mon + 1);
-			} else if (year < cal.maxYear) {
-				date.setFullYear(year + 1);
-				setMonth(0);
-			}
-			break;
-		    case 2:
-			if (year < cal.maxYear) {
-				date.setFullYear(year + 1);
-			}
-			break;
-		    case 100:
-			cal.setFirstDayOfWeek(el.fdow);
-			return;
-		    case 50:
-			var range = el._range;
-			var current = el.innerHTML;
-			for (var i = range.length; --i >= 0;)
-				if (range[i] == current)
-					break;
-			if (ev && ev.shiftKey) {
-				if (--i < 0)
-					i = range.length - 1;
-			} else if ( ++i >= range.length )
-				i = 0;
-			var newval = range[i];
-			el.innerHTML = newval;
-			cal.onUpdateTime();
-			return;
-		    case 0:
-			// TODAY will bring us here
-			if ((typeof cal.getDateStatus == "function") &&
-			    cal.getDateStatus(date, date.getFullYear(), date.getMonth(), date.getDate())) {
-				return false;
-			}
-			break;
-		}
-		if (!date.equalsTo(cal.date)) {
-			cal.setDate(date);
-			newdate = true;
-		} else if (el.navtype == 0)
-			newdate = closing = true;
-	}
-	if (newdate) {
-		ev && cal.callHandler();
-	}
-	if (closing) {
-		Calendar.removeClass(el, "hilite");
-		ev && cal.callCloseHandler();
-	}
+        if (other_month)
+            cal._init(cal.firstDayOfWeek, date);
+    }
+    else
+    {
+        if (el.navtype == 200)
+        {
+            Calendar.removeClass(el, "hilite");
+            cal.callCloseHandler();
+            return;
+        }
+        date = new Date(cal.date);
+        if (el.navtype == 0)
+            date.setDateOnly(new Date()); // TODAY
+        // unless "today" was clicked, we assume no date was clicked so
+        // the selected handler will know not to close the calenar when
+        // in single-click mode.
+        // cal.dateClicked = (el.navtype == 0);
+        cal.dateClicked = false;
+        var year = date.getFullYear();
+        var mon = date.getMonth();
+        function setMonth(m)
+        {
+            var day = date.getDate();
+            var max = date.getMonthDays(m);
+            if (day > max)
+            {
+                date.setDate(max);
+            }
+            date.setMonth(m);
+        }
+        ;
+        switch (el.navtype)
+                {
+            case 400:
+                Calendar.removeClass(el, "hilite");
+                var text = Calendar._TT["ABOUT"];
+                if (typeof text != "undefined")
+                {
+                    text += cal.showsTime ? Calendar._TT["ABOUT_TIME"] : "";
+                }
+                else
+                {
+                    // FIXME: this should be removed as soon as lang files get updated!
+                    text = "Help and about box text is not translated into this language.\n" +
+                           "If you know this language and you feel generous please update\n" +
+                           "the corresponding file in \"lang\" subdir to match calendar-en.js\n" +
+                           "and send it back to <mi...@yahoo.com> to get it into the distribution  ;-)\n\n" +
+                           "Thank you!\n" +
+                           "http://dynarch.com/mishoo/calendar.epl\n";
+                }
+                alert(text);
+                return;
+            case -2:
+                if (year > cal.minYear)
+                {
+                    date.setFullYear(year - 1);
+                }
+                break;
+            case -1:
+                if (mon > 0)
+                {
+                    setMonth(mon - 1);
+                }
+                else if (year-- > cal.minYear)
+                {
+                    date.setFullYear(year);
+                    setMonth(11);
+                }
+                break;
+            case 1:
+                if (mon < 11)
+                {
+                    setMonth(mon + 1);
+                }
+                else if (year < cal.maxYear)
+                {
+                    date.setFullYear(year + 1);
+                    setMonth(0);
+                }
+                break;
+            case 2:
+                if (year < cal.maxYear)
+                {
+                    date.setFullYear(year + 1);
+                }
+                break;
+            case 100:
+                cal.setFirstDayOfWeek(el.fdow);
+                return;
+            case 50:
+                var range = el._range;
+                var current = el.innerHTML;
+                for (var i = range.length; --i >= 0;)
+                    if (range[i] == current)
+                        break;
+                if (ev && ev.shiftKey)
+                {
+                    if (--i < 0)
+                        i = range.length - 1;
+                }
+                else if (++i >= range.length)
+                    i = 0;
+                var newval = range[i];
+                el.innerHTML = newval;
+                cal.onUpdateTime();
+                return;
+            case 0:
+            // TODAY will bring us here
+                if ((typeof cal.getDateStatus == "function") &&
+                    cal.getDateStatus(date, date.getFullYear(), date.getMonth(), date.getDate()))
+                {
+                    return false;
+                }
+                break;
+        }
+        if (!date.equalsTo(cal.date))
+        {
+            cal.setDate(date);
+            newdate = true;
+        }
+        else if (el.navtype == 0)
+            newdate = closing = true;
+    }
+    if (newdate)
+    {
+        ev && cal.callHandler();
+    }
+    if (closing)
+    {
+        Calendar.removeClass(el, "hilite");
+        ev && cal.callCloseHandler();
+    }
 };
 
 // END: CALENDAR STATIC FUNCTIONS
@@ -717,523 +882,606 @@
  *  an element, be it BODY, then it creates a non-popup calendar (still
  *  hidden).  Some properties need to be set before calling this function.
  */
-Calendar.prototype.create = function (_par) {
-	var parent = null;
-	if (! _par) {
-		// default parent is the document body, in which case we create
-		// a popup calendar.
-		parent = document.getElementsByTagName("body")[0];
-		this.isPopup = true;
-	} else {
-		parent = _par;
-		this.isPopup = false;
-	}
-	this.date = this.dateStr ? new Date(this.dateStr) : new Date();
-
-	var table = Calendar.createElement("table");
-	this.table = table;
-	table.cellSpacing = 0;
-	table.cellPadding = 0;
-	table.calendar = this;
-	Calendar.addEvent(table, "mousedown", Calendar.tableMouseDown);
-
-	var div = Calendar.createElement("div");
-	this.element = div;
-	div.className = "calendar";
-	if (this.isPopup) {
-		div.style.position = "absolute";
-		div.style.display = "none";
-	}
-	div.appendChild(table);
-
-	var thead = Calendar.createElement("thead", table);
-	var cell = null;
-	var row = null;
-
-	var cal = this;
-	var hh = function (text, cs, navtype) {
-		cell = Calendar.createElement("td", row);
-		cell.colSpan = cs;
-		cell.className = "button";
-		if (navtype != 0 && Math.abs(navtype) <= 2)
-			cell.className += " nav";
-		Calendar._add_evs(cell);
-		cell.calendar = cal;
-		cell.navtype = navtype;
-		cell.innerHTML = "<div unselectable='on'>" + text + "</div>";
-		return cell;
-	};
-
-	row = Calendar.createElement("tr", thead);
-	var title_length = 6;
-	(this.isPopup) && --title_length;
-	(this.weekNumbers) && ++title_length;
-
-	hh("?", 1, 400).ttip = Calendar._TT["INFO"];
-	this.title = hh("", title_length, 300);
-	this.title.className = "title";
-	if (this.isPopup) {
-		this.title.ttip = Calendar._TT["DRAG_TO_MOVE"];
-		this.title.style.cursor = "move";
-		hh("&#x00d7;", 1, 200).ttip = Calendar._TT["CLOSE"];
-	}
-
-	row = Calendar.createElement("tr", thead);
-	row.className = "headrow";
-
-	this._nav_py = hh("&#x00ab;", 1, -2);
-	this._nav_py.ttip = Calendar._TT["PREV_YEAR"];
-
-	this._nav_pm = hh("&#x2039;", 1, -1);
-	this._nav_pm.ttip = Calendar._TT["PREV_MONTH"];
+Calendar.prototype.create = function (_par)
+{
+    var parent = null;
+    if (! _par)
+    {
+        // default parent is the document body, in which case we create
+        // a popup calendar.
+        parent = document.getElementsByTagName("body")[0];
+        this.isPopup = true;
+    }
+    else
+    {
+        parent = _par;
+        this.isPopup = false;
+    }
+    this.date = this.dateStr ? new Date(this.dateStr) : new Date();
+
+    var table = Calendar.createElement("table");
+    this.table = table;
+    table.cellSpacing = 0;
+    table.cellPadding = 0;
+    table.calendar = this;
+    Calendar.addEvent(table, "mousedown", Calendar.tableMouseDown);
+
+    var div = Calendar.createElement("div");
+    this.element = div;
+    div.className = "calendar";
+    if (this.isPopup)
+    {
+        div.style.position = "absolute";
+        div.style.display = "none";
+    }
+    div.appendChild(table);
+
+    var thead = Calendar.createElement("thead", table);
+    var cell = null;
+    var row = null;
+
+    var cal = this;
+    var hh = function (text, cs, navtype)
+    {
+        cell = Calendar.createElement("td", row);
+        cell.colSpan = cs;
+        cell.className = "button";
+        if (navtype != 0 && Math.abs(navtype) <= 2)
+            cell.className += " nav";
+        Calendar._add_evs(cell);
+        cell.calendar = cal;
+        cell.navtype = navtype;
+        cell.innerHTML = "<div unselectable='on'>" + text + "</div>";
+        return cell;
+    };
+
+    row = Calendar.createElement("tr", thead);
+    var title_length = 6;
+    (this.isPopup) && --title_length;
+    (this.weekNumbers) && ++title_length;
+
+    hh("?", 1, 400).ttip = Calendar._TT["INFO"];
+    this.title = hh("", title_length, 300);
+    this.title.className = "title";
+    if (this.isPopup)
+    {
+        this.title.ttip = Calendar._TT["DRAG_TO_MOVE"];
+        this.title.style.cursor = "move";
+        hh("&#x00d7;", 1, 200).ttip = Calendar._TT["CLOSE"];
+    }
+
+    row = Calendar.createElement("tr", thead);
+    row.className = "headrow";
+
+    this._nav_py = hh("&#x00ab;", 1, -2);
+    this._nav_py.ttip = Calendar._TT["PREV_YEAR"];
+
+    this._nav_pm = hh("&#x2039;", 1, -1);
+    this._nav_pm.ttip = Calendar._TT["PREV_MONTH"];
 
-	this._nav_now = hh(Calendar._TT["TODAY"], this.weekNumbers ? 4 : 3, 0);
-	this._nav_now.ttip = Calendar._TT["GO_TODAY"];
+    this._nav_now = hh(Calendar._TT["TODAY"], this.weekNumbers ? 4 : 3, 0);
+    this._nav_now.ttip = Calendar._TT["GO_TODAY"];
 
-	this._nav_nm = hh("&#x203a;", 1, 1);
-	this._nav_nm.ttip = Calendar._TT["NEXT_MONTH"];
+    this._nav_nm = hh("&#x203a;", 1, 1);
+    this._nav_nm.ttip = Calendar._TT["NEXT_MONTH"];
 
-	this._nav_ny = hh("&#x00bb;", 1, 2);
-	this._nav_ny.ttip = Calendar._TT["NEXT_YEAR"];
+    this._nav_ny = hh("&#x00bb;", 1, 2);
+    this._nav_ny.ttip = Calendar._TT["NEXT_YEAR"];
 
 	// day names
-	row = Calendar.createElement("tr", thead);
-	row.className = "daynames";
-	if (this.weekNumbers) {
-		cell = Calendar.createElement("td", row);
-		cell.className = "name wn";
-		cell.innerHTML = Calendar._TT["WK"];
-	}
-	for (var i = 7; i > 0; --i) {
-		cell = Calendar.createElement("td", row);
-		if (!i) {
-			cell.navtype = 100;
-			cell.calendar = this;
-			Calendar._add_evs(cell);
-		}
-	}
-	this.firstdayname = (this.weekNumbers) ? row.firstChild.nextSibling : row.firstChild;
-	this._displayWeekdays();
-
-	var tbody = Calendar.createElement("tbody", table);
-	this.tbody = tbody;
-
-	for (i = 6; i > 0; --i) {
-		row = Calendar.createElement("tr", tbody);
-		if (this.weekNumbers) {
-			cell = Calendar.createElement("td", row);
-		}
-		for (var j = 7; j > 0; --j) {
-			cell = Calendar.createElement("td", row);
-			cell.calendar = this;
-			Calendar._add_evs(cell);
-		}
-	}
-
-	if (this.showsTime) {
-		row = Calendar.createElement("tr", tbody);
-		row.className = "time";
-
-		cell = Calendar.createElement("td", row);
-		cell.className = "time";
-		cell.colSpan = 2;
-		cell.innerHTML = Calendar._TT["TIME"] || "&nbsp;";
-
-		cell = Calendar.createElement("td", row);
-		cell.className = "time";
-		cell.colSpan = this.weekNumbers ? 4 : 3;
-
-		(function(){
-			function makeTimePart(className, init, range_start, range_end) {
-				var part = Calendar.createElement("span", cell);
-				part.className = className;
-				part.innerHTML = init;
-				part.calendar = cal;
-				part.ttip = Calendar._TT["TIME_PART"];
-				part.navtype = 50;
-				part._range = [];
-				if (typeof range_start != "number")
-					part._range = range_start;
-				else {
-					for (var i = range_start; i <= range_end; ++i) {
-						var txt;
-						if (i < 10 && range_end >= 10) txt = '0' + i;
-						else txt = '' + i;
-						part._range[part._range.length] = txt;
-					}
-				}
-				Calendar._add_evs(part);
-				return part;
-			};
-			var hrs = cal.date.getHours();
-			var mins = cal.date.getMinutes();
-			var t12 = !cal.time24;
-			var pm = (hrs > 12);
-			if (t12 && pm) hrs -= 12;
-			var H = makeTimePart("hour", hrs, t12 ? 1 : 0, t12 ? 12 : 23);
-			var span = Calendar.createElement("span", cell);
-			span.innerHTML = ":";
-			span.className = "colon";
-			var M = makeTimePart("minute", mins, 0, 59);
-			var AP = null;
-			cell = Calendar.createElement("td", row);
-			cell.className = "time";
-			cell.colSpan = 2;
-			if (t12)
-				AP = makeTimePart("ampm", pm ? "pm" : "am", ["am", "pm"]);
-			else
-				cell.innerHTML = "&nbsp;";
-
-			cal.onSetTime = function() {
-				var pm, hrs = this.date.getHours(),
-					mins = this.date.getMinutes();
-				if (t12) {
-					pm = (hrs >= 12);
-					if (pm) hrs -= 12;
-					if (hrs == 0) hrs = 12;
-					AP.innerHTML = pm ? "pm" : "am";
-				}
-				H.innerHTML = (hrs < 10) ? ("0" + hrs) : hrs;
-				M.innerHTML = (mins < 10) ? ("0" + mins) : mins;
-			};
-
-			cal.onUpdateTime = function() {
-				var date = this.date;
-				var h = parseInt(H.innerHTML, 10);
-				if (t12) {
-					if (/pm/i.test(AP.innerHTML) && h < 12)
-						h += 12;
-					else if (/am/i.test(AP.innerHTML) && h == 12)
-						h = 0;
-				}
-				var d = date.getDate();
-				var m = date.getMonth();
-				var y = date.getFullYear();
-				date.setHours(h);
-				date.setMinutes(parseInt(M.innerHTML, 10));
-				date.setFullYear(y);
-				date.setMonth(m);
-				date.setDate(d);
-				this.dateClicked = false;
-				this.callHandler();
-			};
-		})();
-	} else {
-		this.onSetTime = this.onUpdateTime = function() {};
-	}
-
-	var tfoot = Calendar.createElement("tfoot", table);
-
-	row = Calendar.createElement("tr", tfoot);
-	row.className = "footrow";
-
-	cell = hh(Calendar._TT["SEL_DATE"], this.weekNumbers ? 8 : 7, 300);
-	cell.className = "ttip";
-	if (this.isPopup) {
-		cell.ttip = Calendar._TT["DRAG_TO_MOVE"];
-		cell.style.cursor = "move";
-	}
-	this.tooltips = cell;
-
-	div = Calendar.createElement("div", this.element);
-	this.monthsCombo = div;
-	div.className = "combo";
-	for (i = 0; i < Calendar._MN.length; ++i) {
-		var mn = Calendar.createElement("div");
-		mn.className = Calendar.is_ie ? "label-IEfix" : "label";
-		mn.month = i;
-		mn.innerHTML = Calendar._SMN[i];
-		div.appendChild(mn);
-	}
-
-	div = Calendar.createElement("div", this.element);
-	this.yearsCombo = div;
-	div.className = "combo";
-	for (i = 12; i > 0; --i) {
-		var yr = Calendar.createElement("div");
-		yr.className = Calendar.is_ie ? "label-IEfix" : "label";
-		div.appendChild(yr);
-	}
+    row = Calendar.createElement("tr", thead);
+    row.className = "daynames";
+    if (this.weekNumbers)
+    {
+        cell = Calendar.createElement("td", row);
+        cell.className = "name wn";
+        cell.innerHTML = Calendar._TT["WK"];
+    }
+    for (var i = 7; i > 0; --i)
+    {
+        cell = Calendar.createElement("td", row);
+        if (!i)
+        {
+            cell.navtype = 100;
+            cell.calendar = this;
+            Calendar._add_evs(cell);
+        }
+    }
+    this.firstdayname = (this.weekNumbers) ? row.firstChild.nextSibling : row.firstChild;
+    this._displayWeekdays();
+
+    var tbody = Calendar.createElement("tbody", table);
+    this.tbody = tbody;
+
+    for (i = 6; i > 0; --i)
+    {
+        row = Calendar.createElement("tr", tbody);
+        if (this.weekNumbers)
+        {
+            cell = Calendar.createElement("td", row);
+        }
+        for (var j = 7; j > 0; --j)
+        {
+            cell = Calendar.createElement("td", row);
+            cell.calendar = this;
+            Calendar._add_evs(cell);
+        }
+    }
+
+    if (this.showsTime)
+    {
+        row = Calendar.createElement("tr", tbody);
+        row.className = "time";
+
+        cell = Calendar.createElement("td", row);
+        cell.className = "time";
+        cell.colSpan = 2;
+        cell.innerHTML = Calendar._TT["TIME"] || "&nbsp;";
+
+        cell = Calendar.createElement("td", row);
+        cell.className = "time";
+        cell.colSpan = this.weekNumbers ? 4 : 3;
+
+        (function()
+        {
+            function makeTimePart(className, init, range_start, range_end)
+            {
+                var part = Calendar.createElement("span", cell);
+                part.className = className;
+                part.innerHTML = init;
+                part.calendar = cal;
+                part.ttip = Calendar._TT["TIME_PART"];
+                part.navtype = 50;
+                part._range = [];
+                if (typeof range_start != "number")
+                    part._range = range_start;
+                else
+                {
+                    for (var i = range_start; i <= range_end; ++i)
+                    {
+                        var txt;
+                        if (i < 10 && range_end >= 10) txt = '0' + i;
+                        else txt = '' + i;
+                        part._range[part._range.length] = txt;
+                    }
+                }
+                Calendar._add_evs(part);
+                return part;
+            }
+            ;
+            var hrs = cal.date.getHours();
+            var mins = cal.date.getMinutes();
+            var t12 = !cal.time24;
+            var pm = (hrs > 12);
+            if (t12 && pm) hrs -= 12;
+            var H = makeTimePart("hour", hrs, t12 ? 1 : 0, t12 ? 12 : 23);
+            var span = Calendar.createElement("span", cell);
+            span.innerHTML = ":";
+            span.className = "colon";
+            var M = makeTimePart("minute", mins, 0, 59);
+            var AP = null;
+            cell = Calendar.createElement("td", row);
+            cell.className = "time";
+            cell.colSpan = 2;
+            if (t12)
+                AP = makeTimePart("ampm", pm ? "pm" : "am", ["am", "pm"]);
+            else
+                cell.innerHTML = "&nbsp;";
+
+            cal.onSetTime = function()
+            {
+                var pm, hrs = this.date.getHours(),
+                        mins = this.date.getMinutes();
+                if (t12)
+                {
+                    pm = (hrs >= 12);
+                    if (pm) hrs -= 12;
+                    if (hrs == 0) hrs = 12;
+                    AP.innerHTML = pm ? "pm" : "am";
+                }
+                H.innerHTML = (hrs < 10) ? ("0" + hrs) : hrs;
+                M.innerHTML = (mins < 10) ? ("0" + mins) : mins;
+            };
+
+            cal.onUpdateTime = function()
+            {
+                var date = this.date;
+                var h = parseInt(H.innerHTML, 10);
+                if (t12)
+                {
+                    if (/pm/i.test(AP.innerHTML) && h < 12)
+                        h += 12;
+                    else if (/am/i.test(AP.innerHTML) && h == 12)
+                        h = 0;
+                }
+                var d = date.getDate();
+                var m = date.getMonth();
+                var y = date.getFullYear();
+                date.setHours(h);
+                date.setMinutes(parseInt(M.innerHTML, 10));
+                date.setFullYear(y);
+                date.setMonth(m);
+                date.setDate(d);
+                this.dateClicked = false;
+                this.callHandler();
+            };
+        })();
+    }
+    else
+    {
+        this.onSetTime = this.onUpdateTime = function()
+        {
+        };
+    }
+
+    var tfoot = Calendar.createElement("tfoot", table);
+
+    row = Calendar.createElement("tr", tfoot);
+    row.className = "footrow";
+
+    cell = hh(Calendar._TT["SEL_DATE"], this.weekNumbers ? 8 : 7, 300);
+    cell.className = "ttip";
+    if (this.isPopup)
+    {
+        cell.ttip = Calendar._TT["DRAG_TO_MOVE"];
+        cell.style.cursor = "move";
+    }
+    this.tooltips = cell;
+
+    div = Calendar.createElement("div", this.element);
+    this.monthsCombo = div;
+    div.className = "combo";
+    for (i = 0; i < Calendar._MN.length; ++i)
+    {
+        var mn = Calendar.createElement("div");
+        mn.className = Calendar.is_ie ? "label-IEfix" : "label";
+        mn.month = i;
+        mn.innerHTML = Calendar._SMN[i];
+        div.appendChild(mn);
+    }
+
+    div = Calendar.createElement("div", this.element);
+    this.yearsCombo = div;
+    div.className = "combo";
+    for (i = 12; i > 0; --i)
+    {
+        var yr = Calendar.createElement("div");
+        yr.className = Calendar.is_ie ? "label-IEfix" : "label";
+        div.appendChild(yr);
+    }
 
-	this._init(this.firstDayOfWeek, this.date);
-	parent.appendChild(this.element);
+    this._init(this.firstDayOfWeek, this.date);
+    parent.appendChild(this.element);
 };
 
 /** keyboard navigation, only for popup calendars */
-Calendar._keyEvent = function(ev) {
-	var cal = window._dynarch_popupCalendar;
-	if (!cal || cal.multiple)
-		return false;
-	(Calendar.is_ie) && (ev = window.event);
-	var act = (Calendar.is_ie || ev.type == "keypress"),
-		K = ev.keyCode;
-	if (ev.ctrlKey) {
-		switch (K) {
-		    case 37: // KEY left
-			act && Calendar.cellClick(cal._nav_pm);
-			break;
-		    case 38: // KEY up
-			act && Calendar.cellClick(cal._nav_py);
-			break;
-		    case 39: // KEY right
-			act && Calendar.cellClick(cal._nav_nm);
-			break;
-		    case 40: // KEY down
-			act && Calendar.cellClick(cal._nav_ny);
-			break;
-		    default:
-			return false;
-		}
-	} else switch (K) {
-	    case 32: // KEY space (now)
-		Calendar.cellClick(cal._nav_now);
-		break;
-	    case 27: // KEY esc
-		act && cal.callCloseHandler();
-		break;
-	    case 37: // KEY left
-	    case 38: // KEY up
-	    case 39: // KEY right
-	    case 40: // KEY down
-		if (act) {
-			var prev, x, y, ne, el, step;
-			prev = K == 37 || K == 38;
-			step = (K == 37 || K == 39) ? 1 : 7;
-			function setVars() {
-				el = cal.currentDateEl;
-				var p = el.pos;
-				x = p & 15;
-				y = p >> 4;
-				ne = cal.ar_days[y][x];
-			};setVars();
-			function prevMonth() {
-				var date = new Date(cal.date);
-				date.setDate(date.getDate() - step);
-				cal.setDate(date);
-			};
-			function nextMonth() {
-				var date = new Date(cal.date);
-				date.setDate(date.getDate() + step);
-				cal.setDate(date);
-			};
-			while (1) {
-				switch (K) {
-				    case 37: // KEY left
-					if (--x >= 0)
-						ne = cal.ar_days[y][x];
-					else {
-						x = 6;
-						K = 38;
-						continue;
-					}
-					break;
-				    case 38: // KEY up
-					if (--y >= 0)
-						ne = cal.ar_days[y][x];
-					else {
-						prevMonth();
-						setVars();
-					}
-					break;
-				    case 39: // KEY right
-					if (++x < 7)
-						ne = cal.ar_days[y][x];
-					else {
-						x = 0;
-						K = 40;
-						continue;
-					}
-					break;
-				    case 40: // KEY down
-					if (++y < cal.ar_days.length)
-						ne = cal.ar_days[y][x];
-					else {
-						nextMonth();
-						setVars();
-					}
-					break;
-				}
-				break;
-			}
-			if (ne) {
-				if (!ne.disabled)
-					Calendar.cellClick(ne);
-				else if (prev)
-					prevMonth();
-				else
-					nextMonth();
-			}
-		}
-		break;
-	    case 13: // KEY enter
-		if (act)
-			Calendar.cellClick(cal.currentDateEl, ev);
-		break;
-	    default:
-		return false;
-	}
-	return Calendar.stopEvent(ev);
+Calendar._keyEvent = function(ev)
+{
+    var cal = window._dynarch_popupCalendar;
+    if (!cal || cal.multiple)
+        return false;
+    (Calendar.is_ie) && (ev = window.event);
+    var act = (Calendar.is_ie || ev.type == "keypress"),
+            K = ev.keyCode;
+    if (ev.ctrlKey)
+    {
+        switch (K)
+                {
+            case 37: // KEY left
+                act && Calendar.cellClick(cal._nav_pm);
+                break;
+            case 38: // KEY up
+                act && Calendar.cellClick(cal._nav_py);
+                break;
+            case 39: // KEY right
+                act && Calendar.cellClick(cal._nav_nm);
+                break;
+            case 40: // KEY down
+                act && Calendar.cellClick(cal._nav_ny);
+                break;
+            default:
+                return false;
+        }
+    }
+    else switch (K)
+            {
+        case 32: // KEY space (now)
+            Calendar.cellClick(cal._nav_now);
+            break;
+        case 27: // KEY esc
+            act && cal.callCloseHandler();
+            break;
+        case 37: // KEY left
+        case 38: // KEY up
+        case 39: // KEY right
+        case 40: // KEY down
+            if (act)
+            {
+                var prev, x, y, ne, el, step;
+                prev = K == 37 || K == 38;
+                step = (K == 37 || K == 39) ? 1 : 7;
+                function setVars()
+                {
+                    el = cal.currentDateEl;
+                    var p = el.pos;
+                    x = p & 15;
+                    y = p >> 4;
+                    ne = cal.ar_days[y][x];
+                }
+                ;
+                setVars();
+                function prevMonth()
+                {
+                    var date = new Date(cal.date);
+                    date.setDate(date.getDate() - step);
+                    cal.setDate(date);
+                }
+                ;
+                function nextMonth()
+                {
+                    var date = new Date(cal.date);
+                    date.setDate(date.getDate() + step);
+                    cal.setDate(date);
+                }
+                ;
+                while (1)
+                {
+                    switch (K)
+                            {
+                        case 37: // KEY left
+                            if (--x >= 0)
+                                ne = cal.ar_days[y][x];
+                            else
+                            {
+                                x = 6;
+                                K = 38;
+                                continue;
+                            }
+                            break;
+                        case 38: // KEY up
+                            if (--y >= 0)
+                                ne = cal.ar_days[y][x];
+                            else
+                            {
+                                prevMonth();
+                                setVars();
+                            }
+                            break;
+                        case 39: // KEY right
+                            if (++x < 7)
+                                ne = cal.ar_days[y][x];
+                            else
+                            {
+                                x = 0;
+                                K = 40;
+                                continue;
+                            }
+                            break;
+                        case 40: // KEY down
+                            if (++y < cal.ar_days.length)
+                                ne = cal.ar_days[y][x];
+                            else
+                            {
+                                nextMonth();
+                                setVars();
+                            }
+                            break;
+                    }
+                    break;
+                }
+                if (ne)
+                {
+                    if (!ne.disabled)
+                        Calendar.cellClick(ne);
+                    else if (prev)
+                        prevMonth();
+                    else
+                        nextMonth();
+                }
+            }
+            break;
+        case 13: // KEY enter
+            if (act)
+                Calendar.cellClick(cal.currentDateEl, ev);
+            break;
+        default:
+            return false;
+    }
+    return Calendar.stopEvent(ev);
 };
 
 /**
  *  (RE)Initializes the calendar to the given date and firstDayOfWeek
  */
-Calendar.prototype._init = function (firstDayOfWeek, date) {
-	var today = new Date(),
-		TY = today.getFullYear(),
-		TM = today.getMonth(),
-		TD = today.getDate();
-	this.table.style.visibility = "hidden";
-	var year = date.getFullYear();
-	if (year < this.minYear) {
-		year = this.minYear;
-		date.setFullYear(year);
-	} else if (year > this.maxYear) {
-		year = this.maxYear;
-		date.setFullYear(year);
-	}
-	this.firstDayOfWeek = firstDayOfWeek;
-	this.date = new Date(date);
-	var month = date.getMonth();
-	var mday = date.getDate();
-	var no_days = date.getMonthDays();
+Calendar.prototype._init = function (firstDayOfWeek, date)
+{
+    var today = new Date(),
+            TY = today.getFullYear(),
+            TM = today.getMonth(),
+            TD = today.getDate();
+    this.table.style.visibility = "hidden";
+    var year = date.getFullYear();
+    if (year < this.minYear)
+    {
+        year = this.minYear;
+        date.setFullYear(year);
+    }
+    else if (year > this.maxYear)
+    {
+        year = this.maxYear;
+        date.setFullYear(year);
+    }
+    this.firstDayOfWeek = firstDayOfWeek;
+    this.date = new Date(date);
+    var month = date.getMonth();
+    var mday = date.getDate();
+    var no_days = date.getMonthDays();
 
 	// calendar voodoo for computing the first day that would actually be
-	// displayed in the calendar, even if it's from the previous month.
-	// WARNING: this is magic. ;-)
-	date.setDate(1);
-	var day1 = (date.getDay() - this.firstDayOfWeek) % 7;
-	if (day1 < 0)
-		day1 += 7;
-	date.setDate(-day1);
-	date.setDate(date.getDate() + 1);
-
-	var row = this.tbody.firstChild;
-	var MN = Calendar._SMN[month];
-	var ar_days = this.ar_days = new Array();
-	var weekend = Calendar._TT["WEEKEND"];
-	var dates = this.multiple ? (this.datesCells = {}) : null;
-	for (var i = 0; i < 6; ++i, row = row.nextSibling) {
-		var cell = row.firstChild;
-		if (this.weekNumbers) {
-			cell.className = "day wn";
-			cell.innerHTML = date.getWeekNumber();
-			cell = cell.nextSibling;
-		}
-		row.className = "daysrow";
-		var hasdays = false, iday, dpos = ar_days[i] = [];
-		for (var j = 0; j < 7; ++j, cell = cell.nextSibling, date.setDate(iday + 1)) {
-			iday = date.getDate();
-			var wday = date.getDay();
-			cell.className = "day";
-			cell.pos = i << 4 | j;
-			dpos[j] = cell;
-			var current_month = (date.getMonth() == month);
-			if (!current_month) {
-				if (this.showsOtherMonths) {
-					cell.className += " othermonth";
-					cell.otherMonth = true;
-				} else {
-					cell.className = "emptycell";
-					cell.innerHTML = "&nbsp;";
-					cell.disabled = true;
-					continue;
-				}
-			} else {
-				cell.otherMonth = false;
-				hasdays = true;
-			}
-			cell.disabled = false;
-			cell.innerHTML = this.getDateText ? this.getDateText(date, iday) : iday;
-			if (dates)
-				dates[date.print("%Y%m%d")] = cell;
-			if (this.getDateStatus) {
-				var status = this.getDateStatus(date, year, month, iday);
-				if (this.getDateToolTip) {
-					var toolTip = this.getDateToolTip(date, year, month, iday);
-					if (toolTip)
-						cell.title = toolTip;
-				}
-				if (status === true) {
-					cell.className += " disabled";
-					cell.disabled = true;
-				} else {
-					if (/disabled/i.test(status))
-						cell.disabled = true;
-					cell.className += " " + status;
-				}
-			}
-			if (!cell.disabled) {
-				cell.caldate = new Date(date);
-				cell.ttip = "_";
-				if (!this.multiple && current_month
-				    && iday == mday && this.hiliteToday) {
-					cell.className += " selected";
-					this.currentDateEl = cell;
-				}
-				if (date.getFullYear() == TY &&
-				    date.getMonth() == TM &&
-				    iday == TD) {
-					cell.className += " today";
-					cell.ttip += Calendar._TT["PART_TODAY"];
-				}
-				if (weekend.indexOf(wday.toString()) != -1)
-					cell.className += cell.otherMonth ? " oweekend" : " weekend";
-			}
-		}
-		if (!(hasdays || this.showsOtherMonths))
-			row.className = "emptyrow";
-	}
-	this.title.innerHTML = Calendar._MN[month] + ", " + year;
-	this.onSetTime();
-	this.table.style.visibility = "visible";
-	this._initMultipleDates();
+    // displayed in the calendar, even if it's from the previous month.
+    // WARNING: this is magic. ;-)
+    date.setDate(1);
+    var day1 = (date.getDay() - this.firstDayOfWeek) % 7;
+    if (day1 < 0)
+        day1 += 7;
+    date.setDate(-day1);
+    date.setDate(date.getDate() + 1);
+
+    var row = this.tbody.firstChild;
+    var MN = Calendar._SMN[month];
+    var ar_days = this.ar_days = new Array();
+    var weekend = Calendar._TT["WEEKEND"];
+    var dates = this.multiple ? (this.datesCells = {}) : null;
+    for (var i = 0; i < 6; ++i,row = row.nextSibling)
+    {
+        var cell = row.firstChild;
+        if (this.weekNumbers)
+        {
+            cell.className = "day wn";
+            cell.innerHTML = date.getWeekNumber();
+            cell = cell.nextSibling;
+        }
+        row.className = "daysrow";
+        var hasdays = false, iday, dpos = ar_days[i] = [];
+        for (var j = 0; j < 7; ++j,cell = cell.nextSibling,date.setDate(iday + 1))
+        {
+            iday = date.getDate();
+            var wday = date.getDay();
+            cell.className = "day";
+            cell.pos = i << 4 | j;
+            dpos[j] = cell;
+            var current_month = (date.getMonth() == month);
+            if (!current_month)
+            {
+                if (this.showsOtherMonths)
+                {
+                    cell.className += " othermonth";
+                    cell.otherMonth = true;
+                }
+                else
+                {
+                    cell.className = "emptycell";
+                    cell.innerHTML = "&nbsp;";
+                    cell.disabled = true;
+                    continue;
+                }
+            }
+            else
+            {
+                cell.otherMonth = false;
+                hasdays = true;
+            }
+            cell.disabled = false;
+            cell.innerHTML = this.getDateText ? this.getDateText(date, iday) : iday;
+            if (dates)
+                dates[date.print("%Y%m%d")] = cell;
+            if (this.getDateStatus)
+            {
+                var status = this.getDateStatus(date, year, month, iday);
+                if (this.getDateToolTip)
+                {
+                    var toolTip = this.getDateToolTip(date, year, month, iday);
+                    if (toolTip)
+                        cell.title = toolTip;
+                }
+                if (status === true)
+                {
+                    cell.className += " disabled";
+                    cell.disabled = true;
+                }
+                else
+                {
+                    if (/disabled/i.test(status))
+                        cell.disabled = true;
+                    cell.className += " " + status;
+                }
+            }
+            if (!cell.disabled)
+            {
+                cell.caldate = new Date(date);
+                cell.ttip = "_";
+                if (!this.multiple && current_month
+                        && iday == mday && this.hiliteToday)
+                {
+                    cell.className += " selected";
+                    this.currentDateEl = cell;
+                }
+                if (date.getFullYear() == TY &&
+                    date.getMonth() == TM &&
+                    iday == TD)
+                {
+                    cell.className += " today";
+                    cell.ttip += Calendar._TT["PART_TODAY"];
+                }
+                if (weekend.indexOf(wday.toString()) != -1)
+                    cell.className += cell.otherMonth ? " oweekend" : " weekend";
+            }
+        }
+        if (!(hasdays || this.showsOtherMonths))
+            row.className = "emptyrow";
+    }
+    this.title.innerHTML = Calendar._MN[month] + ", " + year;
+    this.onSetTime();
+    this.table.style.visibility = "visible";
+    this._initMultipleDates();
 	// PROFILE
-	// this.tooltips.innerHTML = "Generated in " + ((new Date()) - today) + " ms";
+    // this.tooltips.innerHTML = "Generated in " + ((new Date()) - today) + " ms";
 };
 
-Calendar.prototype._initMultipleDates = function() {
-	if (this.multiple) {
-		for (var i in this.multiple) {
-			var cell = this.datesCells[i];
-			var d = this.multiple[i];
-			if (!d)
-				continue;
-			if (cell)
-				cell.className += " selected";
-		}
-	}
-};
-
-Calendar.prototype._toggleMultipleDate = function(date) {
-	if (this.multiple) {
-		var ds = date.print("%Y%m%d");
-		var cell = this.datesCells[ds];
-		if (cell) {
-			var d = this.multiple[ds];
-			if (!d) {
-				Calendar.addClass(cell, "selected");
-				this.multiple[ds] = date;
-			} else {
-				Calendar.removeClass(cell, "selected");
-				delete this.multiple[ds];
-			}
-		}
-	}
-};
-
-Calendar.prototype.setDateToolTipHandler = function (unaryFunction) {
-	this.getDateToolTip = unaryFunction;
+Calendar.prototype._initMultipleDates = function()
+{
+    if (this.multiple)
+    {
+        for (var i in this.multiple)
+        {
+            var cell = this.datesCells[i];
+            var d = this.multiple[i];
+            if (!d)
+                continue;
+            if (cell)
+                cell.className += " selected";
+        }
+    }
+};
+
+Calendar.prototype._toggleMultipleDate = function(date)
+{
+    if (this.multiple)
+    {
+        var ds = date.print("%Y%m%d");
+        var cell = this.datesCells[ds];
+        if (cell)
+        {
+            var d = this.multiple[ds];
+            if (!d)
+            {
+                Calendar.addClass(cell, "selected");
+                this.multiple[ds] = date;
+            }
+            else
+            {
+                Calendar.removeClass(cell, "selected");
+                delete this.multiple[ds];
+            }
+        }
+    }
+};
+
+Calendar.prototype.setDateToolTipHandler = function (unaryFunction)
+{
+    this.getDateToolTip = unaryFunction;
 };
 
 /**
  *  Calls _init function above for going to a certain date (but only if the
  *  date is different than the currently selected one).
  */
-Calendar.prototype.setDate = function (date) {
-	if (!date.equalsTo(this.date)) {
-		this._init(this.firstDayOfWeek, date);
-	}
+Calendar.prototype.setDate = function (date)
+{
+    if (!date.equalsTo(this.date))
+    {
+        this._init(this.firstDayOfWeek, date);
+    }
 };
 
 /**
@@ -1242,14 +1490,16 @@
  *  Just * call this function if you think that the list of disabled dates
  *  should * change.
  */
-Calendar.prototype.refresh = function () {
-	this._init(this.firstDayOfWeek, this.date);
+Calendar.prototype.refresh = function ()
+{
+    this._init(this.firstDayOfWeek, this.date);
 };
 
 /** Modifies the "firstDayOfWeek" parameter (pass 0 for Synday, 1 for Monday, etc.). */
-Calendar.prototype.setFirstDayOfWeek = function (firstDayOfWeek) {
-	this._init(firstDayOfWeek, this.date);
-	this._displayWeekdays();
+Calendar.prototype.setFirstDayOfWeek = function (firstDayOfWeek)
+{
+    this._init(firstDayOfWeek, this.date);
+    this._displayWeekdays();
 };
 
 /**
@@ -1258,103 +1508,120 @@
  *  object) and returns a boolean value.  If the returned value is true then
  *  the passed date will be marked as disabled.
  */
-Calendar.prototype.setDateStatusHandler = Calendar.prototype.setDisabledHandler = function (unaryFunction) {
-	this.getDateStatus = unaryFunction;
+Calendar.prototype.setDateStatusHandler = Calendar.prototype.setDisabledHandler = function (unaryFunction)
+{
+    this.getDateStatus = unaryFunction;
 };
 
 /** Customization of allowed year range for the calendar. */
-Calendar.prototype.setRange = function (a, z) {
-	this.minYear = a;
-	this.maxYear = z;
+Calendar.prototype.setRange = function (a, z)
+{
+    this.minYear = a;
+    this.maxYear = z;
 };
 
 /** Calls the first user handler (selectedHandler). */
-Calendar.prototype.callHandler = function () {
-	if (this.onSelected) {
-		this.onSelected(this, this.date.print(this.dateFormat));
-	}
+Calendar.prototype.callHandler = function ()
+{
+    if (this.onSelected)
+    {
+        this.onSelected(this, this.date.print(this.dateFormat));
+    }
 };
 
 /** Calls the second user handler (closeHandler). */
-Calendar.prototype.callCloseHandler = function () {
-	if (this.onClose) {
-		this.onClose(this);
-	}
-	this.hideShowCovered();
+Calendar.prototype.callCloseHandler = function ()
+{
+    if (this.onClose)
+    {
+        this.onClose(this);
+    }
+    this.hideShowCovered();
 };
 
 /** Removes the calendar object from the DOM tree and destroys it. */
-Calendar.prototype.destroy = function () {
-	var el = this.element.parentNode;
-	el.removeChild(this.element);
-	Calendar._C = null;
-	window._dynarch_popupCalendar = null;
+Calendar.prototype.destroy = function ()
+{
+    var el = this.element.parentNode;
+    el.removeChild(this.element);
+    Calendar._C = null;
+    window._dynarch_popupCalendar = null;
 };
 
 /**
  *  Moves the calendar element to a different section in the DOM tree (changes
  *  its parent).
  */
-Calendar.prototype.reparent = function (new_parent) {
-	var el = this.element;
-	el.parentNode.removeChild(el);
-	new_parent.appendChild(el);
+Calendar.prototype.reparent = function (new_parent)
+{
+    var el = this.element;
+    el.parentNode.removeChild(el);
+    new_parent.appendChild(el);
 };
 
 // This gets called when the user presses a mouse button anywhere in the
 // document, if the calendar is shown.  If the click was outside the open
 // calendar this function closes it.
-Calendar._checkCalendar = function(ev) {
-	var calendar = window._dynarch_popupCalendar;
-	if (!calendar) {
-		return false;
-	}
-	var el = Calendar.is_ie ? Calendar.getElement(ev) : Calendar.getTargetElement(ev);
-	for (; el != null && el != calendar.element; el = el.parentNode);
-	if (el == null) {
-		// calls closeHandler which should hide the calendar.
-		window._dynarch_popupCalendar.callCloseHandler();
-		return Calendar.stopEvent(ev);
-	}
+Calendar._checkCalendar = function(ev)
+{
+    var calendar = window._dynarch_popupCalendar;
+    if (!calendar)
+    {
+        return false;
+    }
+    var el = Calendar.is_ie ? Calendar.getElement(ev) : Calendar.getTargetElement(ev);
+    for (; el != null && el != calendar.element; el = el.parentNode);
+    if (el == null)
+    {
+        // calls closeHandler which should hide the calendar.
+        window._dynarch_popupCalendar.callCloseHandler();
+        return Calendar.stopEvent(ev);
+    }
 };
 
 /** Shows the calendar. */
-Calendar.prototype.show = function () {
-	var rows = this.table.getElementsByTagName("tr");
-	for (var i = rows.length; i > 0;) {
-		var row = rows[--i];
-		Calendar.removeClass(row, "rowhilite");
-		var cells = row.getElementsByTagName("td");
-		for (var j = cells.length; j > 0;) {
-			var cell = cells[--j];
-			Calendar.removeClass(cell, "hilite");
-			Calendar.removeClass(cell, "active");
-		}
-	}
-	this.element.style.display = "block";
-	this.hidden = false;
-	if (this.isPopup) {
-		window._dynarch_popupCalendar = this;
-		Calendar.addEvent(document, "keydown", Calendar._keyEvent);
-		Calendar.addEvent(document, "keypress", Calendar._keyEvent);
-		Calendar.addEvent(document, "mousedown", Calendar._checkCalendar);
-	}
-	this.hideShowCovered();
+Calendar.prototype.show = function ()
+{
+    var rows = this.table.getElementsByTagName("tr");
+    for (var i = rows.length; i > 0;)
+    {
+        var row = rows[--i];
+        Calendar.removeClass(row, "rowhilite");
+        var cells = row.getElementsByTagName("td");
+        for (var j = cells.length; j > 0;)
+        {
+            var cell = cells[--j];
+            Calendar.removeClass(cell, "hilite");
+            Calendar.removeClass(cell, "active");
+        }
+    }
+    this.element.style.display = "block";
+    this.hidden = false;
+    if (this.isPopup)
+    {
+        window._dynarch_popupCalendar = this;
+        Calendar.addEvent(document, "keydown", Calendar._keyEvent);
+        Calendar.addEvent(document, "keypress", Calendar._keyEvent);
+        Calendar.addEvent(document, "mousedown", Calendar._checkCalendar);
+    }
+    this.hideShowCovered();
 };
 
 /**
  *  Hides the calendar.  Also removes any "hilite" from the class of any TD
  *  element.
  */
-Calendar.prototype.hide = function () {
-	if (this.isPopup) {
-		Calendar.removeEvent(document, "keydown", Calendar._keyEvent);
-		Calendar.removeEvent(document, "keypress", Calendar._keyEvent);
-		Calendar.removeEvent(document, "mousedown", Calendar._checkCalendar);
-	}
-	this.element.style.display = "none";
-	this.hidden = true;
-	this.hideShowCovered();
+Calendar.prototype.hide = function ()
+{
+    if (this.isPopup)
+    {
+        Calendar.removeEvent(document, "keydown", Calendar._keyEvent);
+        Calendar.removeEvent(document, "keypress", Calendar._keyEvent);
+        Calendar.removeEvent(document, "mousedown", Calendar._checkCalendar);
+    }
+    this.element.style.display = "none";
+    this.hidden = true;
+    this.hideShowCovered();
 };
 
 /**
@@ -1362,441 +1629,523 @@
  *  the calendar element style -- position property -- this might be relative
  *  to the parent's containing rectangle).
  */
-Calendar.prototype.showAt = function (x, y) {
-	var s = this.element.style;
-	s.left = x + "px";
-	s.top = y + "px";
-	this.show();
+Calendar.prototype.showAt = function (x, y)
+{
+    var s = this.element.style;
+    s.left = x + "px";
+    s.top = y + "px";
+    this.show();
 };
 
 /** Shows the calendar near a given element. */
-Calendar.prototype.showAtElement = function (el, opts) {
-	var self = this;
-	var p = Calendar.getAbsolutePos(el);
-	if (!opts || typeof opts != "string") {
-		this.showAt(p.x, p.y + el.offsetHeight);
-		return true;
-	}
-	function fixPosition(box) {
-		if (box.x < 0)
-			box.x = 0;
-		if (box.y < 0)
-			box.y = 0;
-		var cp = document.createElement("div");
-		var s = cp.style;
-		s.position = "absolute";
-		s.right = s.bottom = s.width = s.height = "0px";
-		document.body.appendChild(cp);
-		var br = Calendar.getAbsolutePos(cp);
-		document.body.removeChild(cp);
-		if (Calendar.is_ie) {
-			br.y += document.body.scrollTop;
-			br.x += document.body.scrollLeft;
-		} else {
-			br.y += window.scrollY;
-			br.x += window.scrollX;
-		}
-		var tmp = box.x + box.width - br.x;
-		if (tmp > 0) box.x -= tmp;
-		tmp = box.y + box.height - br.y;
-		if (tmp > 0) box.y -= tmp;
-	};
-	this.element.style.display = "block";
-	Calendar.continuation_for_the_fucking_khtml_browser = function() {
-		var w = self.element.offsetWidth;
-		var h = self.element.offsetHeight;
-		self.element.style.display = "none";
-		var valign = opts.substr(0, 1);
-		var halign = "l";
-		if (opts.length > 1) {
-			halign = opts.substr(1, 1);
-		}
+Calendar.prototype.showAtElement = function (el, opts)
+{
+    var self = this;
+    var p = Calendar.getAbsolutePos(el);
+    if (!opts || typeof opts != "string")
+    {
+        this.showAt(p.x, p.y + el.offsetHeight);
+        return true;
+    }
+    function fixPosition(box)
+    {
+        if (box.x < 0)
+            box.x = 0;
+        if (box.y < 0)
+            box.y = 0;
+        var cp = document.createElement("div");
+        var s = cp.style;
+        s.position = "absolute";
+        s.right = s.bottom = s.width = s.height = "0px";
+        document.body.appendChild(cp);
+        var br = Calendar.getAbsolutePos(cp);
+        document.body.removeChild(cp);
+        if (Calendar.is_ie)
+        {
+            br.y += document.body.scrollTop;
+            br.x += document.body.scrollLeft;
+        }
+        else
+        {
+            br.y += window.scrollY;
+            br.x += window.scrollX;
+        }
+        var tmp = box.x + box.width - br.x;
+        if (tmp > 0) box.x -= tmp;
+        tmp = box.y + box.height - br.y;
+        if (tmp > 0) box.y -= tmp;
+    }
+    ;
+    this.element.style.display = "block";
+    Calendar.continuation_for_the_fucking_khtml_browser = function()
+    {
+        var w = self.element.offsetWidth;
+        var h = self.element.offsetHeight;
+        self.element.style.display = "none";
+        var valign = opts.substr(0, 1);
+        var halign = "l";
+        if (opts.length > 1)
+        {
+            halign = opts.substr(1, 1);
+        }
 		// vertical alignment
-		switch (valign) {
-		    case "T": p.y -= h; break;
-		    case "B": p.y += el.offsetHeight; break;
-		    case "C": p.y += (el.offsetHeight - h) / 2; break;
-		    case "t": p.y += el.offsetHeight - h; break;
-		    case "b": break; // already there
-		}
+        switch (valign)
+                {
+            case "T": p.y -= h; break;
+            case "B": p.y += el.offsetHeight; break;
+            case "C": p.y += (el.offsetHeight - h) / 2; break;
+            case "t": p.y += el.offsetHeight - h; break;
+            case "b": break; // already there
+        }
 		// horizontal alignment
-		switch (halign) {
-		    case "L": p.x -= w; break;
-		    case "R": p.x += el.offsetWidth; break;
-		    case "C": p.x += (el.offsetWidth - w) / 2; break;
-		    case "l": p.x += el.offsetWidth - w; break;
-		    case "r": break; // already there
-		}
-		p.width = w;
-		p.height = h + 40;
-		self.monthsCombo.style.display = "none";
-		fixPosition(p);
-		self.showAt(p.x, p.y);
-	};
-	if (Calendar.is_khtml)
-		setTimeout("Calendar.continuation_for_the_fucking_khtml_browser()", 10);
-	else
-		Calendar.continuation_for_the_fucking_khtml_browser();
+        switch (halign)
+                {
+            case "L": p.x -= w; break;
+            case "R": p.x += el.offsetWidth; break;
+            case "C": p.x += (el.offsetWidth - w) / 2; break;
+            case "l": p.x += el.offsetWidth - w; break;
+            case "r": break; // already there
+        }
+        p.width = w;
+        p.height = h + 40;
+        self.monthsCombo.style.display = "none";
+        fixPosition(p);
+        self.showAt(p.x, p.y);
+    };
+    if (Calendar.is_khtml)
+        setTimeout("Calendar.continuation_for_the_fucking_khtml_browser()", 10);
+    else
+        Calendar.continuation_for_the_fucking_khtml_browser();
 };
 
 /** Customizes the date format. */
-Calendar.prototype.setDateFormat = function (str) {
-	this.dateFormat = str;
+Calendar.prototype.setDateFormat = function (str)
+{
+    this.dateFormat = str;
 };
 
 /** Customizes the tooltip date format. */
-Calendar.prototype.setTtDateFormat = function (str) {
-	this.ttDateFormat = str;
+Calendar.prototype.setTtDateFormat = function (str)
+{
+    this.ttDateFormat = str;
 };
 
 /**
  *  Tries to identify the date represented in a string.  If successful it also
  *  calls this.setDate which moves the calendar to the given date.
  */
-Calendar.prototype.parseDate = function(str, fmt) {
-	if (!fmt)
-		fmt = this.dateFormat;
-	this.setDate(Date.parseDate(str, fmt));
-};
-
-Calendar.prototype.hideShowCovered = function () {
-	if (!Calendar.is_ie && !Calendar.is_opera)
-		return;
-	function getVisib(obj){
-		var value = obj.style.visibility;
-		if (!value) {
-			if (document.defaultView && typeof (document.defaultView.getComputedStyle) == "function") { // Gecko, W3C
-				if (!Calendar.is_khtml)
-					value = document.defaultView.
-						getComputedStyle(obj, "").getPropertyValue("visibility");
-				else
-					value = '';
-			} else if (obj.currentStyle) { // IE
-				value = obj.currentStyle.visibility;
-			} else
-				value = '';
-		}
-		return value;
-	};
-
-	var tags = new Array("applet", "iframe", "select");
-	var el = this.element;
-
-	var p = Calendar.getAbsolutePos(el);
-	var EX1 = p.x;
-	var EX2 = el.offsetWidth + EX1;
-	var EY1 = p.y;
-	var EY2 = el.offsetHeight + EY1;
-
-	for (var k = tags.length; k > 0; ) {
-		var ar = document.getElementsByTagName(tags[--k]);
-		var cc = null;
-
-		for (var i = ar.length; i > 0;) {
-			cc = ar[--i];
-
-			p = Calendar.getAbsolutePos(cc);
-			var CX1 = p.x;
-			var CX2 = cc.offsetWidth + CX1;
-			var CY1 = p.y;
-			var CY2 = cc.offsetHeight + CY1;
-
-			if (this.hidden || (CX1 > EX2) || (CX2 < EX1) || (CY1 > EY2) || (CY2 < EY1)) {
-				if (!cc.__msh_save_visibility) {
-					cc.__msh_save_visibility = getVisib(cc);
-				}
-				cc.style.visibility = cc.__msh_save_visibility;
-			} else {
-				if (!cc.__msh_save_visibility) {
-					cc.__msh_save_visibility = getVisib(cc);
-				}
-				cc.style.visibility = "hidden";
-			}
-		}
-	}
+Calendar.prototype.parseDate = function(str, fmt)
+{
+    if (!fmt)
+        fmt = this.dateFormat;
+    this.setDate(Date.parseDate(str, fmt));
+};
+
+Calendar.prototype.hideShowCovered = function ()
+{
+    if (!Calendar.is_ie && !Calendar.is_opera)
+        return;
+    function getVisib(obj)
+    {
+        var value = obj.style.visibility;
+        if (!value)
+        {
+            if (document.defaultView && typeof (document.defaultView.getComputedStyle) == "function")
+            { // Gecko, W3C
+                if (!Calendar.is_khtml)
+                    value = document.defaultView.
+                            getComputedStyle(obj, "").getPropertyValue("visibility");
+                else
+                    value = '';
+            }
+            else if (obj.currentStyle)
+            { // IE
+                value = obj.currentStyle.visibility;
+            }
+            else
+                value = '';
+        }
+        return value;
+    }
+    ;
+
+    var tags = new Array("applet", "iframe", "select");
+    var el = this.element;
+
+    var p = Calendar.getAbsolutePos(el);
+    var EX1 = p.x;
+    var EX2 = el.offsetWidth + EX1;
+    var EY1 = p.y;
+    var EY2 = el.offsetHeight + EY1;
+
+    for (var k = tags.length; k > 0;)
+    {
+        var ar = document.getElementsByTagName(tags[--k]);
+        var cc = null;
+
+        for (var i = ar.length; i > 0;)
+        {
+            cc = ar[--i];
+
+            p = Calendar.getAbsolutePos(cc);
+            var CX1 = p.x;
+            var CX2 = cc.offsetWidth + CX1;
+            var CY1 = p.y;
+            var CY2 = cc.offsetHeight + CY1;
+
+            if (this.hidden || (CX1 > EX2) || (CX2 < EX1) || (CY1 > EY2) || (CY2 < EY1))
+            {
+                if (!cc.__msh_save_visibility)
+                {

[... 595 lines stripped ...]