JavaScript DHTML/GUI Components/Calendar — различия между версиями

Материал из Web эксперт
Перейти к: навигация, поиск
м (1 версия)
 
м (1 версия)
 
(нет различий)

Текущая версия на 10:44, 26 мая 2010

Содержание

A Dynamic Calendar Table

   <source lang="html4strict">

/* JavaScript Bible, Fourth Edition by Danny Goodman John Wiley & Sons CopyRight 2001

  • /

<HTML> <HEAD> <TITLE>JavaScripted Dynamic Table</TITLE> <SCRIPT LANGUAGE="JavaScript">

</SCRIPT> </HEAD> <BODY>

Month at a Glance (Dynamic)


<SCRIPT LANGUAGE="JavaScript">

</SCRIPT> <SELECT NAME="chooseMonth"> <OPTION SELECTED>January<OPTION>February <OPTION>March<OPTION>April<OPTION>May <OPTION>June<OPTION>July<OPTION>August <OPTION>September<OPTION>October<OPTION>November<OPTION>December </SELECT> <SELECT NAME="chooseYear"> <OPTION SELECTED>2000<OPTION>2001 <OPTION>2002<OPTION>2003 <OPTION>2004<OPTION>2005 <OPTION>2006<OPTION>2007 </SELECT> <INPUT TYPE="button" NAME="updater" VALUE="Update Calendar" onClick="populateFields(this.form)"> </FORM> </BODY> </HTML>


 </source>
   
  


All browser Calendar

   <source lang="html4strict">

<html> <head> <meta http-equiv="content-type" content="text/xml; charset=utf-8" /> <title>Simple calendar setups [popup calendar]</title>

 <style rel="stylesheet" type="text/css" media="all" title="win2k-cold-1">

/* The main calendar widget. DIV containing a table. */ .calendar {

 position: relative;
 display: none;
 border-top: 2px solid #fff;
 border-right: 2px solid #000;
 border-bottom: 2px solid #000;
 border-left: 2px solid #fff;
 font-size: 11px;
 color: #000;
 cursor: default;
 background: #c8d0d4;
 font-family: tahoma,verdana,sans-serif;

} .calendar table {

 border-top: 1px solid #000;
 border-right: 1px solid #fff;
 border-bottom: 1px solid #fff;
 border-left: 1px solid #000;
 font-size: 11px;
 color: #000;
 cursor: default;
 background: #c8d0d4;
 font-family: tahoma,verdana,sans-serif;

} /* Header part -- contains navigation buttons and day names. */ .calendar .button { /* "<<", "<", ">", ">>" buttons have this class */

 text-align: center;
 padding: 1px;
 border-top: 1px solid #fff;
 border-right: 1px solid #000;
 border-bottom: 1px solid #000;
 border-left: 1px solid #fff;

} .calendar .nav {

 background: transparent url(menuarrow.gif) no-repeat 100% 100%;

} .calendar thead .title { /* This holds the current "month, year" */

 font-weight: bold;
 padding: 1px;
 border: 1px solid #000;
 background: #788084;
 color: #fff;
 text-align: center;

} .calendar thead .headrow { /* Row <TR> containing navigation buttons */ } .calendar thead .daynames { /* Row <TR> containing the day names */ } .calendar thead .name { /* Cells <TD> containing the day names */

 border-bottom: 1px solid #000;
 padding: 2px;
 text-align: center;
 background: #e8f0f4;

} .calendar thead .weekend { /* How a weekend day name shows in header */

 color: #f00;

} .calendar thead .hilite { /* How do the buttons in header appear when hover */

 border-top: 2px solid #fff;
 border-right: 2px solid #000;
 border-bottom: 2px solid #000;
 border-left: 2px solid #fff;
 padding: 0px;
 background-color: #d8e0e4;

} .calendar thead .active { /* Active (pressed) buttons in header */

 padding: 2px 0px 0px 2px;
 border-top: 1px solid #000;
 border-right: 1px solid #fff;
 border-bottom: 1px solid #fff;
 border-left: 1px solid #000;
 background-color: #b8c0c4;

} /* The body part -- contains all the days in month. */ .calendar tbody .day { /* Cells <TD> containing month days dates */

 width: 2em;
 text-align: right;
 padding: 2px 4px 2px 2px;

} .calendar tbody .day.othermonth {

 font-size: 80%;
 color: #aaa;

} .calendar tbody .day.othermonth.oweekend {

 color: #faa;

} .calendar table .wn {

 padding: 2px 3px 2px 2px;
 border-right: 1px solid #000;
 background: #e8f4f0;

} .calendar tbody .rowhilite td {

 background: #d8e4e0;

} .calendar tbody .rowhilite td.wn {

 background: #c8d4d0;

} .calendar tbody td.hilite { /* Hovered cells <TD> */

 padding: 1px 3px 1px 1px;
 border: 1px solid;
 border-color: #fff #000 #000 #fff;

} .calendar tbody td.active { /* Active (pressed) cells <TD> */

 padding: 2px 2px 0px 2px;
 border: 1px solid;
 border-color: #000 #fff #fff #000;

} .calendar tbody td.selected { /* Cell showing selected date */

 font-weight: bold;
 padding: 2px 2px 0px 2px;
 border: 1px solid;
 border-color: #000 #fff #fff #000;
 background: #d8e0e4;

} .calendar tbody td.weekend { /* Cells showing weekend days */

 color: #f00;

} .calendar tbody td.today { /* Cell showing today date */

 font-weight: bold;
 color: #00f;

} .calendar tbody .disabled { color: #999; } .calendar tbody .emptycell { /* Empty cells (the best is to hide them) */

 visibility: hidden;

} .calendar tbody .emptyrow { /* Empty row (some months need less than 6 rows) */

 display: none;

} /* The footer part -- status bar and "Close" button */ .calendar tfoot .footrow { /* The <TR> in footer (only one right now) */ } .calendar tfoot .ttip { /* Tooltip (status bar) cell <TD> */

 background: #e8f0f4;
 padding: 1px;
 border: 1px solid #000;
 background: #788084;
 color: #fff;
 text-align: center;

} .calendar tfoot .hilite { /* Hover style for buttons in footer */

 border-top: 1px solid #fff;
 border-right: 1px solid #000;
 border-bottom: 1px solid #000;
 border-left: 1px solid #fff;
 padding: 1px;
 background: #d8e0e4;

} .calendar tfoot .active { /* Active (pressed) style for buttons in footer */

 padding: 2px 0px 0px 2px;
 border-top: 1px solid #000;
 border-right: 1px solid #fff;
 border-bottom: 1px solid #fff;
 border-left: 1px solid #000;

} /* Combo boxes (menus that display months/years for direct selection) */ .calendar .rubo {

 position: absolute;
 display: none;
 width: 4em;
 top: 0px;
 left: 0px;
 cursor: default;
 border-top: 1px solid #fff;
 border-right: 1px solid #000;
 border-bottom: 1px solid #000;
 border-left: 1px solid #fff;
 background: #d8e0e4;
 font-size: 90%;
 padding: 1px;
 z-index: 100;

} .calendar .rubo .label, .calendar .rubo .label-IEfix {

 text-align: center;
 padding: 1px;

} .calendar .rubo .label-IEfix {

 width: 4em;

} .calendar .rubo .active {

 background: #c8d0d4;
 padding: 0px;
 border-top: 1px solid #000;
 border-right: 1px solid #fff;
 border-bottom: 1px solid #fff;
 border-left: 1px solid #000;

} .calendar .rubo .hilite {

 background: #048;
 color: #aef;

} .calendar td.time {

 border-top: 1px solid #000;
 padding: 1px 0px;
 text-align: center;
 background-color: #e8f0f4;

} .calendar td.time .hour, .calendar td.time .minute, .calendar td.time .ampm {

 padding: 0px 3px 0px 4px;
 border: 1px solid #889;
 font-weight: bold;
 background-color: #fff;

} .calendar td.time .ampm {

 text-align: center;

} .calendar td.time .colon {

 padding: 0px 2px 0px 3px;
 font-weight: bold;

} .calendar td.time span.hilite {

 border-color: #000;
 background-color: #667;
 color: #fff;

} .calendar td.time span.active {

 border-color: #f00;
 background-color: #000;
 color: #0f0;

}

 </style>
 
 <script type="text/javascript">

/* Copyright Mihai Bazon, 2002-2005 | www.bazon.net/mishoo

* -----------------------------------------------------------
*
* The DHTML Calendar, version 1.0 "It is happening again"
*
* Details and latest version at:
* www.dynarch.ru/projects/calendar
*
* This script is developed by Dynarch.ru.  Visit us at www.dynarch.ru.
*
* This script is distributed under the GNU Lesser General Public License.
* Read the entire license text here: http://www.gnu.org/licenses/lgpl.html
*/

// $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;
 // HTML elements
 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;
 // Information
 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;
   // 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;
 }

}; // ** constants /// "static", needed for event handlers. Calendar._C = null; /// detect a special case of "web browser" Calendar.is_ie = ( /msie/i.test(navigator.userAgent) &&

      !/opera/i.test(navigator.userAgent) );

Calendar.is_ie5 = ( Calendar.is_ie && /msie 5\.0/i.test(navigator.userAgent) ); /// detect Opera browser Calendar.is_opera = /opera/i.test(navigator.userAgent); /// detect KHTML-based browsers Calendar.is_khtml = /Konqueror|Safari|KHTML/i.test(navigator.userAgent); // 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;

}; // 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;

}; // END: UTILITY FUNCTIONS // 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";
 }

}; // 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);
 }

}; /**

*  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;
   // 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 <mihai_bazon@yahoo.ru> to get it into the distribution  ;-)\n\n" +
         "Thank you!\n" +
         "http://dynarch.ru/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 // BEGIN: CALENDAR OBJECT FUNCTIONS /**

*  This function creates the calendar inside the given parent.  If _par is
*  null than it creates a popup calendar inside the BODY element.  If _par is
*  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 = "
" + text + "
";
   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("×", 1, 200).ttip = Calendar._TT["CLOSE"];
 }
 row = Calendar.createElement("tr", thead);
 row.className = "headrow";
 this._nav_py = hh("«", 1, -2);
 this._nav_py.ttip = Calendar._TT["PREV_YEAR"];
 this._nav_pm = hh("‹", 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_nm = hh("›", 1, 1);
 this._nav_nm.ttip = Calendar._TT["NEXT_MONTH"];
 this._nav_ny = hh("»", 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"] || " ";
   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 = " ";
     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);

}; /** 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);

}; /**

*  (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 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 = " ";
         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";

}; 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);
 }

}; /**

*  Refreshes the calendar.  Useful if the "disabledHandler" function is
*  dynamic, meaning that the list of disabled date can change at runtime.
*  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);

}; /** Modifies the "firstDayOfWeek" parameter (pass 0 for Synday, 1 for Monday, etc.). */ Calendar.prototype.setFirstDayOfWeek = function (firstDayOfWeek) {

 this._init(firstDayOfWeek, this.date);
 this._displayWeekdays();

}; /**

*  Allows customization of what dates are enabled.  The "unaryFunction"
*  parameter must be a function object that receives the date (as a JS Date
*  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;

}; /** Customization of allowed year range for the calendar. */ 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));
 }

}; /** Calls the second user handler (closeHandler). */ 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;

}; /**

*  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);

}; // 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);
 }

}; /** 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();

}; /**

*  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();

}; /**

*  Shows the calendar at a given absolute position (beware that, depending on
*  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();

}; /** 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);
   }
   // 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
   }
   // 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();

}; /** Customizes the date format. */ Calendar.prototype.setDateFormat = function (str) {

 this.dateFormat = str;

}; /** Customizes the tooltip date format. */ 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";
     }
   }
 }

}; /** Internal function; it displays the bar with the names of the weekday. */ Calendar.prototype._displayWeekdays = function () {

 var fdow = this.firstDayOfWeek;
 var cell = this.firstdayname;
 var weekend = Calendar._TT["WEEKEND"];
 for (var i = 0; i < 7; ++i) {
   cell.className = "day name";
   var realday = (i + fdow) % 7;
   if (i) {
     cell.ttip = Calendar._TT["DAY_FIRST"].replace("%s", Calendar._DN[realday]);
     cell.navtype = 100;
     cell.calendar = this;
     cell.fdow = realday;
     Calendar._add_evs(cell);
   }
   if (weekend.indexOf(realday.toString()) != -1) {
     Calendar.addClass(cell, "weekend");
   }
   cell.innerHTML = Calendar._SDN[(i + fdow) % 7];
   cell = cell.nextSibling;
 }

}; /** Internal function. Hides all combo boxes that might be displayed. */ Calendar.prototype._hideCombos = function () {

 this.monthsCombo.style.display = "none";
 this.yearsCombo.style.display = "none";

}; /** Internal function. Starts dragging the element. */ Calendar.prototype._dragStart = function (ev) {

 if (this.dragging) {
   return;
 }
 this.dragging = true;
 var posX;
 var posY;
 if (Calendar.is_ie) {
   posY = window.event.clientY + document.body.scrollTop;
   posX = window.event.clientX + document.body.scrollLeft;
 } else {
   posY = ev.clientY + window.scrollY;
   posX = ev.clientX + window.scrollX;
 }
 var st = this.element.style;
 this.xOffs = posX - parseInt(st.left);
 this.yOffs = posY - parseInt(st.top);
 with (Calendar) {
   addEvent(document, "mousemove", calDragIt);
   addEvent(document, "mouseup", calDragEnd);
 }

}; // BEGIN: DATE OBJECT PATCHES /** Adds the number of days array to the Date object. */ Date._MD = new Array(31,28,31,30,31,30,31,31,30,31,30,31); /** Constants used for time computations */ Date.SECOND = 1000 /* milliseconds */; Date.MINUTE = 60 * Date.SECOND; Date.HOUR = 60 * Date.MINUTE; Date.DAY = 24 * Date.HOUR; Date.WEEK = 7 * Date.DAY; Date.parseDate = function(str, fmt) {

 var today = new Date();
 var y = 0;
 var m = -1;
 var d = 0;
 var a = str.split(/\W+/);
 var b = fmt.match(/%./g);
 var i = 0, j = 0;
 var hr = 0;
 var min = 0;
 for (i = 0; i < a.length; ++i) {
   if (!a[i])
     continue;
   switch (b[i]) {
       case "%d":
       case "%e":
     d = parseInt(a[i], 10);
     break;
       case "%m":
     m = parseInt(a[i], 10) - 1;
     break;
       case "%Y":
       case "%y":
     y = parseInt(a[i], 10);
     (y < 100) && (y += (y > 29) ? 1900 : 2000);
     break;
       case "%b":
       case "%B":
     for (j = 0; j < 12; ++j) {
       if (Calendar._MN[j].substr(0, a[i].length).toLowerCase() == a[i].toLowerCase()) { m = j; break; }
     }
     break;
       case "%H":
       case "%I":
       case "%k":
       case "%l":
     hr = parseInt(a[i], 10);
     break;
       case "%P":
       case "%p":
     if (/pm/i.test(a[i]) && hr < 12)
       hr += 12;
     else if (/am/i.test(a[i]) && hr >= 12)
       hr -= 12;
     break;
       case "%M":
     min = parseInt(a[i], 10);
     break;
   }
 }
 if (isNaN(y)) y = today.getFullYear();
 if (isNaN(m)) m = today.getMonth();
 if (isNaN(d)) d = today.getDate();
 if (isNaN(hr)) hr = today.getHours();
 if (isNaN(min)) min = today.getMinutes();
 if (y != 0 && m != -1 && d != 0)
   return new Date(y, m, d, hr, min, 0);
 y = 0; m = -1; d = 0;
 for (i = 0; i < a.length; ++i) {
   if (a[i].search(/[a-zA-Z]+/) != -1) {
     var t = -1;
     for (j = 0; j < 12; ++j) {
       if (Calendar._MN[j].substr(0, a[i].length).toLowerCase() == a[i].toLowerCase()) { t = j; break; }
     }
     if (t != -1) {
       if (m != -1) {
         d = m+1;
       }
       m = t;
     }
   } else if (parseInt(a[i], 10) <= 12 && m == -1) {
     m = a[i]-1;
   } else if (parseInt(a[i], 10) > 31 && y == 0) {
     y = parseInt(a[i], 10);
     (y < 100) && (y += (y > 29) ? 1900 : 2000);
   } else if (d == 0) {
     d = a[i];
   }
 }
 if (y == 0)
   y = today.getFullYear();
 if (m != -1 && d != 0)
   return new Date(y, m, d, hr, min, 0);
 return today;

}; /** Returns the number of days in the current month */ Date.prototype.getMonthDays = function(month) {

 var year = this.getFullYear();
 if (typeof month == "undefined") {
   month = this.getMonth();
 }
 if (((0 == (year%4)) && ( (0 != (year%100)) || (0 == (year%400)))) && month == 1) {
   return 29;
 } else {
   return Date._MD[month];
 }

}; /** Returns the number of day in the year. */ Date.prototype.getDayOfYear = function() {

 var now = new Date(this.getFullYear(), this.getMonth(), this.getDate(), 0, 0, 0);
 var then = new Date(this.getFullYear(), 0, 0, 0, 0, 0);
 var time = now - then;
 return Math.floor(time / Date.DAY);

}; /** Returns the number of the week in year, as defined in ISO 8601. */ Date.prototype.getWeekNumber = function() {

 var d = new Date(this.getFullYear(), this.getMonth(), this.getDate(), 0, 0, 0);
 var DoW = d.getDay();
 d.setDate(d.getDate() - (DoW + 6) % 7 + 3); // Nearest Thu
 var ms = d.valueOf(); // GMT
 d.setMonth(0);
 d.setDate(4); // Thu in Week 1
 return Math.round((ms - d.valueOf()) / (7 * 864e5)) + 1;

}; /** Checks date and time equality */ Date.prototype.equalsTo = function(date) {

 return ((this.getFullYear() == date.getFullYear()) &&
   (this.getMonth() == date.getMonth()) &&
   (this.getDate() == date.getDate()) &&
   (this.getHours() == date.getHours()) &&
   (this.getMinutes() == date.getMinutes()));

}; /** Set only the year, month, date parts (keep existing time) */ Date.prototype.setDateOnly = function(date) {

 var tmp = new Date(date);
 this.setDate(1);
 this.setFullYear(tmp.getFullYear());
 this.setMonth(tmp.getMonth());
 this.setDate(tmp.getDate());

}; /** Prints the date in a string according to the given format. */ Date.prototype.print = function (str) {

 var m = this.getMonth();
 var d = this.getDate();
 var y = this.getFullYear();
 var wn = this.getWeekNumber();
 var w = this.getDay();
 var s = {};
 var hr = this.getHours();
 var pm = (hr >= 12);
 var ir = (pm) ? (hr - 12) : hr;
 var dy = this.getDayOfYear();
 if (ir == 0)
   ir = 12;
 var min = this.getMinutes();
 var sec = this.getSeconds();
 s["%a"] = Calendar._SDN[w]; // abbreviated weekday name [FIXME: I18N]
 s["%A"] = Calendar._DN[w]; // full weekday name
 s["%b"] = Calendar._SMN[m]; // abbreviated month name [FIXME: I18N]
 s["%B"] = Calendar._MN[m]; // full month name
 // FIXME: %c : preferred date and time representation for the current locale
 s["%C"] = 1 + Math.floor(y / 100); // the century number
 s["%d"] = (d < 10) ? ("0" + d) : d; // the day of the month (range 01 to 31)
 s["%e"] = d; // the day of the month (range 1 to 31)
 // FIXME: %D : american date style: %m/%d/%y
 // FIXME: %E, %F, %G, %g, %h (man strftime)
 s["%H"] = (hr < 10) ? ("0" + hr) : hr; // hour, range 00 to 23 (24h format)
 s["%I"] = (ir < 10) ? ("0" + ir) : ir; // hour, range 01 to 12 (12h format)
 s["%j"] = (dy < 100) ? ((dy < 10) ? ("00" + dy) : ("0" + dy)) : dy; // day of the year (range 001 to 366)
 s["%k"] = hr;    // hour, range 0 to 23 (24h format)
 s["%l"] = ir;    // hour, range 1 to 12 (12h format)
 s["%m"] = (m < 9) ? ("0" + (1+m)) : (1+m); // month, range 01 to 12
 s["%M"] = (min < 10) ? ("0" + min) : min; // minute, range 00 to 59
 s["%n"] = "\n";    // a newline character
 s["%p"] = pm ? "PM" : "AM";
 s["%P"] = pm ? "pm" : "am";
 // FIXME: %r : the time in am/pm notation %I:%M:%S %p
 // FIXME: %R : the time in 24-hour notation %H:%M
 s["%s"] = Math.floor(this.getTime() / 1000);
 s["%S"] = (sec < 10) ? ("0" + sec) : sec; // seconds, range 00 to 59
 s["%t"] = "\t";    // a tab character
 // FIXME: %T : the time in 24-hour notation (%H:%M:%S)
 s["%U"] = s["%W"] = s["%V"] = (wn < 10) ? ("0" + wn) : wn;
 s["%u"] = w + 1;  // the day of the week (range 1 to 7, 1 = MON)
 s["%w"] = w;    // the day of the week (range 0 to 6, 0 = SUN)
 // FIXME: %x : preferred date representation for the current locale without the time
 // FIXME: %X : preferred time representation for the current locale without the date
 s["%y"] = ("" + y).substr(2, 2); // year without the century (range 00 to 99)
 s["%Y"] = y;    // year with the century
 s["%%"] = "%";    // a literal "%" character
 var re = /%./g;
 if (!Calendar.is_ie5 && !Calendar.is_khtml)
   return str.replace(re, function (par) { return s[par] || par; });
 var a = str.match(re);
 for (var i = 0; i < a.length; i++) {
   var tmp = s[a[i]];
   if (tmp) {
     re = new RegExp(a[i], "g");
     str = str.replace(re, tmp);
   }
 }
 return str;

}; Date.prototype.__msh_oldSetFullYear = Date.prototype.setFullYear; Date.prototype.setFullYear = function(y) {

 var d = new Date(this);
 d.__msh_oldSetFullYear(y);
 if (d.getMonth() != this.getMonth())
   this.setDate(28);
 this.__msh_oldSetFullYear(y);

}; // END: DATE OBJECT PATCHES

// global object that remembers the calendar window._dynarch_popupCalendar = null;

 </script>
 
 <script type="text/javascript">

// ** I18N // Calendar EN language // Author: Mihai Bazon, <mihai_bazon@yahoo.ru> // Encoding: any // Distributed under the same terms as the calendar itself. // For translators: please use UTF-8 if possible. We strongly believe that // Unicode is the answer to a real internationalized world. Also please // include your contact information in the header, as can be seen above. // full day names Calendar._DN = new Array ("Sunday",

"Monday",
"Tuesday",
"Wednesday",
"Thursday",
"Friday",
"Saturday",
"Sunday");

// Please note that the following array of short day names (and the same goes // for short month names, _SMN) isn"t absolutely necessary. We give it here // for exemplification on how one can customize the short day names, but if // they are simply the first N letters of the full name you can simply say: // // Calendar._SDN_len = N; // short day name length // Calendar._SMN_len = N; // short month name length // // If N = 3 then this is not needed either since we assume a value of 3 if not // present, to be compatible with translation files that were written before // this feature. // short day names Calendar._SDN = new Array ("Sun",

"Mon",
"Tue",
"Wed",
"Thu",
"Fri",
"Sat",
"Sun");

// First day of the week. "0" means display Sunday first, "1" means display // Monday first, etc. Calendar._FD = 0; // full month names Calendar._MN = new Array ("January",

"February",
"March",
"April",
"May",
"June",
"July",
"August",
"September",
"October",
"November",
"December");

// short month names Calendar._SMN = new Array ("Jan",

"Feb",
"Mar",
"Apr",
"May",
"Jun",
"Jul",
"Aug",
"Sep",
"Oct",
"Nov",
"Dec");

// tooltips Calendar._TT = {}; Calendar._TT["INFO"] = "About the calendar"; Calendar._TT["ABOUT"] = "DHTML Date/Time Selector\n" + "(c) dynarch.ru 2002-2005 / Author: Mihai Bazon\n" + // don"t translate this this ;-) "For latest version visit: http://www.dynarch.ru/projects/calendar/\n" + "Distributed under GNU LGPL. See http://gnu.org/licenses/lgpl.html for details." + "\n\n" + "Date selection:\n" + "- Use the \xab, \xbb buttons to select year\n" + "- Use the " + String.fromCharCode(0x2039) + ", " + String.fromCharCode(0x203a) + " buttons to select month\n" + "- Hold mouse button on any of the above buttons for faster selection."; Calendar._TT["ABOUT_TIME"] = "\n\n" + "Time selection:\n" + "- Click on any of the time parts to increase it\n" + "- or Shift-click to decrease it\n" + "- or click and drag for faster selection."; Calendar._TT["PREV_YEAR"] = "Prev. year (hold for menu)"; Calendar._TT["PREV_MONTH"] = "Prev. month (hold for menu)"; Calendar._TT["GO_TODAY"] = "Go Today"; Calendar._TT["NEXT_MONTH"] = "Next month (hold for menu)"; Calendar._TT["NEXT_YEAR"] = "Next year (hold for menu)"; Calendar._TT["SEL_DATE"] = "Select date"; Calendar._TT["DRAG_TO_MOVE"] = "Drag to move"; Calendar._TT["PART_TODAY"] = " (today)"; // the following is to inform that "%s" is to be the first day of week // %s will be replaced with the day name. Calendar._TT["DAY_FIRST"] = "Display %s first"; // This may be locale-dependent. It specifies the week-end days, as an array // of comma-separated numbers. The numbers are from 0 to 6: 0 means Sunday, 1 // means Monday, etc. Calendar._TT["WEEKEND"] = "0,6"; Calendar._TT["CLOSE"] = "Close"; Calendar._TT["TODAY"] = "Today"; Calendar._TT["TIME_PART"] = "(Shift-)Click or drag to change value"; // date formats Calendar._TT["DEF_DATE_FORMAT"] = "%Y-%m-%d"; Calendar._TT["TT_DATE_FORMAT"] = "%a, %b %e"; Calendar._TT["WK"] = "wk"; Calendar._TT["TIME"] = "Time:";

 </script>
 
 <script type="text/javascript">

/* Copyright Mihai Bazon, 2002, 2003 | http://dynarch.ru/mishoo/

* ---------------------------------------------------------------------------
*
* The DHTML Calendar
*
* Details and latest version at:
* http://dynarch.ru/mishoo/calendar.epl
*
* This script is distributed under the GNU Lesser General Public License.
* Read the entire license text here: http://www.gnu.org/licenses/lgpl.html
*
* This file defines helper functions for setting up the calendar.  They are
* intended to help non-programmers get a working calendar on their site
* quickly.  This script should not be seen as part of the calendar.  It just
* shows you what one can do with the calendar, while in the same time
* providing a quick and simple method for setting it up.  If you need
* exhaustive customization of the calendar creation process feel free to
* modify this code to suit your needs (this is recommended and much better
* than modifying calendar.js itself).
*/

// $Id: calendar-setup.js,v 1.25 2005/03/07 09:51:33 mishoo Exp $ /**

*  This function "patches" an input field (or other element) to use a calendar
*  widget for date selection.
*
*  The "params" is a single object that can have the following properties:
*
*    prop. name   | description
*  -------------------------------------------------------------------------------------------------
*   inputField    | the ID of an input field to store the date
*   displayArea   | the ID of a DIV or other element to show the date
*   button        | ID of a button or other element that will trigger the calendar
*   eventName     | event that will trigger the calendar, without the "on" prefix (default: "click")
*   ifFormat      | date format that will be stored in the input field
*   daFormat      | the date format that will be used to display the date in displayArea
*   singleClick   | (true/false) wether the calendar is in single click mode or not (default: true)
*   firstDay      | numeric: 0 to 6.  "0" means display Sunday first, "1" means display Monday first, etc.
*   align         | alignment (default: "Br"); if you don"t know what"s this see the calendar documentation
*   range         | array with 2 elements.  Default: [1900, 2999] -- the range of years available
*   weekNumbers   | (true/false) if it"s true (default) the calendar will display week numbers
*   flat          | null or element ID; if not null the calendar will be a flat calendar having the parent with the given ID
*   flatCallback  | function that receives a JS Date object and returns an URL to point the browser to (for flat calendar)
*   disableFunc   | function that receives a JS Date object and should return true if that date has to be disabled in the calendar
*   onSelect      | function that gets called when a date is selected.  You don"t _have_ to supply this (the default is generally okay)
*   onClose       | function that gets called when the calendar is closed.  [default]
*   onUpdate      | function that gets called after the date is updated in the input field.  Receives a reference to the calendar.
*   date          | the date that the calendar will be initially displayed to
*   showsTime     | default: false; if true the calendar will include a time selector
*   timeFormat    | the time format; can be "12" or "24", default is "12"
*   electric      | if true (default) then given fields/date areas are updated for each move; otherwise they"re updated only on close
*   step          | configures the step of the years in drop-down boxes; default: 2
*   position      | configures the calendar absolute position; default: null
*   cache         | if "true" (but default: "false") it will reuse the same calendar object, where possible
*   showOthers    | if "true" (but default: "false") it will show days from other months too
*
*  None of them is required, they all have default values.  However, if you
*  pass none of "inputField", "displayArea" or "button" you"ll get a warning
*  saying "nothing to setup".
*/

Calendar.setup = function (params) {

 function param_default(pname, def) { if (typeof params[pname] == "undefined") { params[pname] = def; } };
 param_default("inputField",     null);
 param_default("displayArea",    null);
 param_default("button",         null);
 param_default("eventName",      "click");
 param_default("ifFormat",       "%Y/%m/%d");
 param_default("daFormat",       "%Y/%m/%d");
 param_default("singleClick",    true);
 param_default("disableFunc",    null);
 param_default("dateStatusFunc", params["disableFunc"]);  // takes precedence if both are defined
 param_default("dateText",       null);
 param_default("firstDay",       null);
 param_default("align",          "Br");
 param_default("range",          [1900, 2999]);
 param_default("weekNumbers",    true);
 param_default("flat",           null);
 param_default("flatCallback",   null);
 param_default("onSelect",       null);
 param_default("onClose",        null);
 param_default("onUpdate",       null);
 param_default("date",           null);
 param_default("showsTime",      false);
 param_default("timeFormat",     "24");
 param_default("electric",       true);
 param_default("step",           2);
 param_default("position",       null);
 param_default("cache",          false);
 param_default("showOthers",     false);
 param_default("multiple",       null);
 var tmp = ["inputField", "displayArea", "button"];
 for (var i in tmp) {
   if (typeof params[tmp[i]] == "string") {
     params[tmp[i]] = document.getElementById(params[tmp[i]]);
   }
 }
 if (!(params.flat || params.multiple || params.inputField || params.displayArea || params.button)) {
   alert("Calendar.setup:\n  Nothing to setup (no fields found).  Please check your code");
   return false;
 }
 function onSelect(cal) {
   var p = cal.params;
   var update = (cal.dateClicked || p.electric);
   if (update && p.inputField) {
     p.inputField.value = cal.date.print(p.ifFormat);
     if (typeof p.inputField.onchange == "function")
       p.inputField.onchange();
   }
   if (update && p.displayArea)
     p.displayArea.innerHTML = cal.date.print(p.daFormat);
   if (update && typeof p.onUpdate == "function")
     p.onUpdate(cal);
   if (update && p.flat) {
     if (typeof p.flatCallback == "function")
       p.flatCallback(cal);
   }
   if (update && p.singleClick && cal.dateClicked)
     cal.callCloseHandler();
 };
 if (params.flat != null) {
   if (typeof params.flat == "string")
     params.flat = document.getElementById(params.flat);
   if (!params.flat) {
     alert("Calendar.setup:\n  Flat specified but can"t find parent.");
     return false;
   }
   var cal = new Calendar(params.firstDay, params.date, params.onSelect || onSelect);
   cal.showsOtherMonths = params.showOthers;
   cal.showsTime = params.showsTime;
   cal.time24 = (params.timeFormat == "24");
   cal.params = params;
   cal.weekNumbers = params.weekNumbers;
   cal.setRange(params.range[0], params.range[1]);
   cal.setDateStatusHandler(params.dateStatusFunc);
   cal.getDateText = params.dateText;
   if (params.ifFormat) {
     cal.setDateFormat(params.ifFormat);
   }
   if (params.inputField && typeof params.inputField.value == "string") {
     cal.parseDate(params.inputField.value);
   }
   cal.create(params.flat);
   cal.show();
   return false;
 }
 var triggerEl = params.button || params.displayArea || params.inputField;
 triggerEl["on" + params.eventName] = function() {
   var dateEl = params.inputField || params.displayArea;
   var dateFmt = params.inputField ? params.ifFormat : params.daFormat;
   var mustCreate = false;
   var cal = window.calendar;
   if (dateEl)
     params.date = Date.parseDate(dateEl.value || dateEl.innerHTML, dateFmt);
   if (!(cal && params.cache)) {
     window.calendar = cal = new Calendar(params.firstDay,
                  params.date,
                  params.onSelect || onSelect,
                  params.onClose || function(cal) { cal.hide(); });
     cal.showsTime = params.showsTime;
     cal.time24 = (params.timeFormat == "24");
     cal.weekNumbers = params.weekNumbers;
     mustCreate = true;
   } else {
     if (params.date)
       cal.setDate(params.date);
     cal.hide();
   }
   if (params.multiple) {
     cal.multiple = {};
     for (var i = params.multiple.length; --i >= 0;) {
       var d = params.multiple[i];
       var ds = d.print("%Y%m%d");
       cal.multiple[ds] = d;
     }
   }
   cal.showsOtherMonths = params.showOthers;
   cal.yearStep = params.step;
   cal.setRange(params.range[0], params.range[1]);
   cal.params = params;
   cal.setDateStatusHandler(params.dateStatusFunc);
   cal.getDateText = params.dateText;
   cal.setDateFormat(dateFmt);
   if (mustCreate)
     cal.create();
   cal.refresh();
   if (!params.position)
     cal.showAtElement(params.button || params.displayArea || params.inputField, params.align);
   else
     cal.showAt(params.position[0], params.position[1]);
   return false;
 };
 return cal;

};

 </script>

</head> <body>

DHTML Calendar for the impatient

This page lists some common setups for the popup calendar. In order to see how to do any of them please see the source of this page. For each example it"s structured like this: there"s the <form> that contains the input field, and following there is the JavaScript snippet that setups that form. An example of flat calendar is available in <a href="simple-2.html">another page</a>.

The code in this page uses a helper function defined in "calendar-setup.js". With it you can setup the calendar in minutes. If you"re not that impatient, ;-) <a href="doc/html/reference.html">complete documenation</a> is available.


Basic setup: one input per calendar. Clicking in the input field activates the calendar. The date format is "%m/%d/%Y %I:%M %p". The calendar defaults to "single-click mode".

The example below has been updated to show you how to create "linked" fields. Basically, when some field is filled with a date, the other is updated so that the difference between them remains one week. The property useful here is "onUpdate".

<form action="#" method="get"> <input type="text" name="date" id="f_date_a" /> <input type="text" name="date" id="f_calcdate" /> </form> <script type="text/javascript">

   function catcalc(cal) {
       var date = cal.date;
       var time = date.getTime()
       // use the _other_ field
       var field = document.getElementById("f_calcdate");
       if (field == cal.params.inputField) {
           field = document.getElementById("f_date_a");
           time -= Date.WEEK; // substract one week
       } else {
           time += Date.WEEK; // add one week
       }
       var date2 = new Date(time);
       field.value = date2.print("%Y-%m-%d %H:%M");
   }
   Calendar.setup({
       inputField     :    "f_date_a",   // id of the input field
       ifFormat       :    "%Y-%m-%d %H:%M",       // format of the input field
       showsTime      :    true,
       timeFormat     :    "24",
       onUpdate       :    catcalc
   });
   Calendar.setup({
       inputField     :    "f_calcdate",
       ifFormat       :    "%Y-%m-%d %H:%M",
       showsTime      :    true,
       timeFormat     :    "24",
       onUpdate       :    catcalc
   });

</script>


Input field with a trigger button. Clicking the button activates the calendar. Note that this one needs double-click (singleClick parameter is explicitely set to false). Also demonstrates the "step" parameter introduced in 0.9.6 (show all years in drop-down boxes, instead of every other year as default).

<form action="#" method="get"> <input type="text" name="date" id="f_date_b" /><button type="reset" id="f_trigger_b">...</button> </form> <script type="text/javascript">

   Calendar.setup({
       inputField     :    "f_date_b",      // id of the input field
       ifFormat       :    "%m/%d/%Y %I:%M %p",       // format of the input field
       showsTime      :    true,            // will display a time selector
       button         :    "f_trigger_b",   // trigger for the calendar (button ID)
       singleClick    :    false,           // double-click mode
       step           :    1                // show all years in drop-down boxes (instead of every other year as default)
   });

</script>


Input field with a trigger image. Note that the Calendar.setup function doesn"t care if the trigger is a button, image, or anything else. Also in this example we setup a different alignment, just to show how it"s done. The input field is read-only (that is set from HTML).

<form action="#" method="get">

<input type="text" name="date" id="f_date_c" readonly="1" /> <img src="img.gif" id="f_trigger_c" style="cursor: pointer; border: 1px solid red;" title="Date selector" onmouseover="this.style.background="red";" onmouseout="this.style.background=""" />

</form> <script type="text/javascript">

   Calendar.setup({
       inputField     :    "f_date_c",     // id of the input field
       ifFormat       :    "%B %e, %Y",      // format of the input field
       button         :    "f_trigger_c",  // trigger for the calendar (button ID)
       align          :    "Tl",           // alignment (defaults to "Bl")
       singleClick    :    true
   });

</script>


Hidden field, display area. The calendar now puts the date into 2 elements: one is an input field of type "hidden" ;so that the user can"t directly see or modify it; and one is a <span> element in which the date is displayed. Note that if the trigger is not specified the calendar will use the displayArea (or inputField as in the first example). The display area can have it"s own format. This is useful if, for instance, we need to store one format in the database (thus pass it in the input field) but we wanna show a friendlier format to the end-user.

<form action="#" method="get" style="visibility: hidden"> <input type="hidden" name="date" id="f_date_d" /> </form>

Your birthday: Click to open date selector.

<script type="text/javascript">

   Calendar.setup({
       inputField     :    "f_date_d",     // id of the input field
       ifFormat       :    "%Y/%d/%m",     // format of the input field (even if hidden, this format will be honored)
       displayArea    :    "show_d",       // ID of the span where the date is to be shown
       daFormat       :    "%A, %B %d, %Y",// format of the displayed date
       align          :    "Tl",           // alignment (defaults to "Bl")
       singleClick    :    true
   });

</script>


Hidden field, display area, trigger image. Very similar to the previous example. The difference is that we also have a trigger image.

<form action="#" method="get" style="visibility: hidden"> <input type="hidden" name="date" id="f_date_e" /> </form>

Your birthday: -- not entered -- <img src="img.gif" id="f_trigger_e" style="cursor: pointer; border: 1px solid red;" title="Date selector" onmouseover="this.style.background="red";" onmouseout="this.style.background=""" />.

<script type="text/javascript">

   Calendar.setup({
       inputField     :    "f_date_e",     // id of the input field
       ifFormat       :    "%Y/%d/%m",     // format of the input field (even if hidden, this format will be honored)
       displayArea    :    "show_e",       // ID of the span where the date is to be shown
       daFormat       :    "%A, %B %d, %Y",// format of the displayed date
       button         :    "f_trigger_e",  // trigger button (well, IMG in our case)
       align          :    "Tl",           // alignment (defaults to "Bl")
       singleClick    :    true
   });

</script>


Hidden field, display area. Very much like the previous examples, but we now disable some dates (all weekends, that is, Saturdays and Sundays).

<form action="#" method="get" style="visibility: hidden"> <input type="hidden" name="date" id="f_date_f" /> </form>

Your birthday: Click to open date selector.

<script type="text/javascript">

   Calendar.setup({
       inputField     :    "f_date_f",     // id of the input field
       ifFormat       :    "%Y/%d/%m",     // format of the input field (even if hidden, this format will be honored)
       displayArea    :    "show_f",       // ID of the span where the date is to be shown
       daFormat       :    "%A, %B %d, %Y",// format of the displayed date
       align          :    "Tl",           // alignment (defaults to "Bl")
       dateStatusFunc :    function (date) { // disable weekend days (Saturdays == 6 and Subdays == 0)
                             return (date.getDay() == 6 || date.getDay() == 0) ? true : false;
                           }
   });

</script>

</body> </html>


 </source>
   
  

<A href="http://www.wbex.ru/Code/JavaScriptDownload/jscalendar-1.0.zip">jscalendar-1.0.zip( 396 k)</a>


Another Calendar

   <source lang="html4strict">

<HTML> <HEAD> <META NAME="GENERATOR" Content="Microsoft Visual Studio 6.0"> <TITLE></TITLE> <script language="JavaScript"> // written by Tan Ling Wee on 2 Dec 2001 // last updated 28 Mar 2002 // email : info@sparrowscripts.ru // url : www.sparrowscripts.ru

 var  fixedX = -1      // x position (-1 if to appear below control)
 var  fixedY = -1      // y position (-1 if to appear below control)
 var startAt = 1      // 0 - sunday ; 1 - monday
 var showWeekNumber = 1  // 0 - don"t show; 1 - show
 var showToday = 1    // 0 - don"t show; 1 - show
 var imgDir = ""      // directory for images ... e.g. var imgDir="/img/"
 var gotoString = "Go To Current Month"
 var todayString = "Today is"
 var weekString = "Wk"
 var scrollLeftMessage = "Click to scroll to previous month. Hold mouse button to scroll automatically."
 var scrollRightMessage = "Click to scroll to next month. Hold mouse button to scroll automatically."
 var selectMonthMessage = "Click to select a month."
 var selectYearMessage = "Click to select a year."
 var selectDateMessage = "Select [date] as date." // do not replace [date], it will be replaced by date.
 var  crossobj, crossMonthObj, crossYearObj, monthSelected, yearSelected, dateSelected, omonthSelected, oyearSelected, odateSelected, monthConstructed, yearConstructed, intervalID1, intervalID2, timeoutID1, timeoutID2, ctlToPlaceValue, ctlNow, dateFormat, nStartingYear
 var  bPageLoaded=false
 var  ie=document.all
 var  dom=document.getElementById
 var  ns4=document.layers
 var  today =  new  Date()
 var  dateNow   = today.getDate()
 var  monthNow = today.getMonth()
 var  yearNow   = today.getYear()
 var  imgsrc = new Array("drop1.gif","drop2.gif","left1.gif","left2.gif","right1.gif","right2.gif")
 var  img  = new Array()
 function HolidayRec (d, m, y, desc)
 {
   this.d = d
   this.m = m
   this.y = y
   this.desc = desc
 }
 var HolidaysCounter = 0
 var Holidays = new Array()
 function addHoliday (d, m, y, desc)
 {
   Holidays[HolidaysCounter++] = new HolidayRec ( d, m, y, desc )
 }
 if (dom)
 {
   for  (i=0;i<imgsrc.length;i++)
   {
     img[i] = new Image
     img[i].src = imgDir + imgsrc[i]
   }
document.write ("");
 }
 var  monthName =  new  Array("January","February","March","April","May","June","July","August","September","October","November","December")
 if (startAt==0)
 {
   dayName = new Array  ("Sun","Mon","Tue","Wed","Thu","Fri","Sat")
 }
 else
 {
   dayName = new Array  ("Mon","Tue","Wed","Thu","Fri","Sat","Sun")
 }
 var  styleAnchor="text-decoration:none;color:black;"
 var  styleLightBorder="border-style:solid;border-width:1px;border-color:#a0a0a0;"
 function swapImage(srcImg, destImg){
   if (ie)  { document.getElementById(srcImg).setAttribute("src",imgDir + destImg) }
 }
 function init()  {
   if (!ns4)
   {
     if (!ie) { yearNow += 1900  }
     crossobj=(dom)?document.getElementById("calendar").style : ie? document.all.calendar : document.calendar
     hideCalendar()
     crossMonthObj=(dom)?document.getElementById("selectMonth").style : ie? document.all.selectMonth  : document.selectMonth
     crossYearObj=(dom)?document.getElementById("selectYear").style : ie? document.all.selectYear : document.selectYear
     monthConstructed=false;
     yearConstructed=false;
     if (showToday==1)
     {
       document.getElementById("lblToday").innerHTML =  todayString + " <a onmousemove="window.status=\""+gotoString+"\"" onmouseout="window.status=\"\"" title=""+gotoString+"" style=""+styleAnchor+"" href="javascript:monthSelected=monthNow;yearSelected=yearNow;constructCalendar();">"+dayName[(today.getDay()-startAt==-1)?6:(today.getDay()-startAt)]+", " + dateNow + " " + monthName[monthNow].substring(0,3)  + "  " +  yearNow  + "</a>"
     }
     sHTML1="&nbsp<IMG id="changeLeft" SRC=""+imgDir+"left1.gif" width=10 height=11 BORDER=0>&nbsp "
     sHTML1+="&nbsp<IMG id="changeRight" SRC=""+imgDir+"right1.gif"  width=10 height=11 BORDER=0>&nbsp&nbsp"
     sHTML1+=" "
     sHTML1+=" "
     
     document.getElementById("caption").innerHTML  =  sHTML1
     bPageLoaded=true
     //Calling a calendar function and passing the name of the text 
     //box which holds the date field. Added by D.T.
     popUpCalendar(this, opener.txtDate, "m/d/yyyy")
   }
 }
 function hideCalendar()  {
   crossobj.visibility="hidden"
   if (crossMonthObj != null){crossMonthObj.visibility="hidden"}
   if (crossYearObj !=  null){crossYearObj.visibility="hidden"}
   //Closing a popup window when user clicked "x", close the calendar. Added by D.T.
   self.closed
 }
 function padZero(num) {
   return (num  < 10)? "0" + num : num ;
 }
 function constructDate(d,m,y)
 {
   sTmp = dateFormat
   sTmp = sTmp.replace  ("dd","<e>")
   sTmp = sTmp.replace  ("d","<d>")
   sTmp = sTmp.replace  ("<e>",padZero(d))
   sTmp = sTmp.replace  ("<d>",d)
   sTmp = sTmp.replace  ("mmm","<o>")
   sTmp = sTmp.replace  ("mm","<n>")
   sTmp = sTmp.replace  ("m","<m>")
   sTmp = sTmp.replace  ("<m>",m+1)
   sTmp = sTmp.replace  ("<n>",padZero(m+1))
   sTmp = sTmp.replace  ("<o>",monthName[m])
   return sTmp.replace ("yyyy",y)
 }
 function closeCalendar() {
   var  sTmp
   hideCalendar();
   ctlToPlaceValue.value =  constructDate(dateSelected,monthSelected,yearSelected)
   //Closing popup window when date is selected. Added By D.T.
   self.close()
 }
 /*** Month Pulldown  ***/
 function StartDecMonth()
 {
   intervalID1=setInterval("decMonth()",80)
 }
 function StartIncMonth()
 {
   intervalID1=setInterval("incMonth()",80)
 }
 function incMonth () {
   monthSelected++
   if (monthSelected>11) {
     monthSelected=0
     yearSelected++
   }
   constructCalendar()
 }
 function decMonth () {
   monthSelected--
   if (monthSelected<0) {
     monthSelected=11
     yearSelected--
   }
   constructCalendar()
 }
 function constructMonth() {
   popDownYear()
   if (!monthConstructed) {
     sHTML =  ""
     for  (i=0; i<12;  i++) {
       sName =  monthName[i];
       if (i==monthSelected){
         sName =  "" +  sName +  ""
       }
       sHTML += "<tr><td id="m" + i + "" onmouseover="this.style.backgroundColor=\"#FFCC99\"" onmouseout="this.style.backgroundColor=\"\"" style="cursor:pointer" onclick="monthConstructed=false;monthSelected=" + i + ";constructCalendar();popDownMonth();event.cancelBubble=true"> " + sName + " </td></tr>"
     }
document.getElementById("selectMonth").innerHTML = "" + sHTML + "
"
     monthConstructed=true
   }
 }
 function popUpMonth() {
   constructMonth()
   crossMonthObj.visibility = (dom||ie)? "visible"  : "show"
   crossMonthObj.left = parseInt(crossobj.left) + 50
   crossMonthObj.top =  parseInt(crossobj.top) + 26
 }
 function popDownMonth()  {
   crossMonthObj.visibility= "hidden"
 }
 /*** Year Pulldown ***/
 function incYear() {
   for  (i=0; i<7; i++){
     newYear  = (i+nStartingYear)+1
     if (newYear==yearSelected)
     { txtYear =  " "  + newYear +  " " }
     else
     { txtYear =  " " + newYear + " " }
     document.getElementById("y"+i).innerHTML = txtYear
   }
   nStartingYear ++;
 }
 function decYear() {
   for  (i=0; i<7; i++){
     newYear  = (i+nStartingYear)-1
     if (newYear==yearSelected)
     { txtYear =  " "  + newYear +  " " }
     else
     { txtYear =  " " + newYear + " " }
     document.getElementById("y"+i).innerHTML = txtYear
   }
   nStartingYear --;
 }
 function selectYear(nYear) {
   yearSelected=parseInt(nYear+nStartingYear);
   yearConstructed=false;
   constructCalendar();
   popDownYear();
 }
 function constructYear() {
   popDownMonth()
   sHTML =  ""
   if (!yearConstructed) {
     sHTML =  "<tr><td align="center"  onmouseover="this.style.backgroundColor=\"#FFCC99\"" onmouseout="clearInterval(intervalID1);this.style.backgroundColor=\"\"" style="cursor:pointer"  onmousedown="clearInterval(intervalID1);intervalID1=setInterval(\"decYear()\",30)" onmouseup="clearInterval(intervalID1)">-</td></tr>"
     j =  0
     nStartingYear =  yearSelected-3
     for  (i=(yearSelected-3); i<=(yearSelected+3); i++) {
       sName =  i;
       if (i==yearSelected){
         sName =  "" +  sName +  ""
       }
       sHTML += "<tr><td id="y" + j + "" onmouseover="this.style.backgroundColor=\"#FFCC99\"" onmouseout="this.style.backgroundColor=\"\"" style="cursor:pointer" onclick="selectYear("+j+");event.cancelBubble=true"> " + sName + " </td></tr>"
       j ++;
     }
     sHTML += "<tr><td align="center" onmouseover="this.style.backgroundColor=\"#FFCC99\"" onmouseout="clearInterval(intervalID2);this.style.backgroundColor=\"\"" style="cursor:pointer" onmousedown="clearInterval(intervalID2);intervalID2=setInterval(\"incYear()\",30)"  onmouseup="clearInterval(intervalID2)">+</td></tr>"
document.getElementById("selectYear").innerHTML = "" + sHTML + "
"
     yearConstructed  = true
   }
 }
 function popDownYear() {
   clearInterval(intervalID1)
   clearTimeout(timeoutID1)
   clearInterval(intervalID2)
   clearTimeout(timeoutID2)
   crossYearObj.visibility= "hidden"
 }
 function popUpYear() {
   var  leftOffset
   constructYear()
   crossYearObj.visibility  = (dom||ie)? "visible" : "show"
   leftOffset = parseInt(crossobj.left) + document.getElementById("spanYear").offsetLeft
   if (ie)
   {
     leftOffset += 6
   }
   crossYearObj.left =  leftOffset
   crossYearObj.top = parseInt(crossobj.top) +  26
 }
 /*** calendar ***/
 function WeekNbr(today)
   {
   Year = takeYear(today);
   Month = today.getMonth();
   Day = today.getDate();
   now = Date.UTC(Year,Month,Day+1,0,0,0);
   var Firstday = new Date();
   Firstday.setYear(Year);
   Firstday.setMonth(0);
   Firstday.setDate(1);
   then = Date.UTC(Year,0,1,0,0,0);
   var Compensation = Firstday.getDay();
   if (Compensation > 3) Compensation -= 4;
   else Compensation += 3;
   NumberOfWeek =  Math.round((((now-then)/86400000)+Compensation)/7);
   return NumberOfWeek;
 }
 function takeYear(theDate)
 {
   x = theDate.getYear();
   var y = x % 100;
   y += (y < 38) ? 2000 : 1900;
   return y;
 }
 function constructCalendar () {
   var aNumDays = Array (31,0,31,30,31,30,31,31,30,31,30,31)
   var dateMessage
   var  startDate =  new  Date (yearSelected,monthSelected,1)
   var endDate
   if (monthSelected==1)
   {
     endDate  = new Date (yearSelected,monthSelected+1,1);
     endDate  = new Date (endDate  - (24*60*60*1000));
     numDaysInMonth = endDate.getDate()
   }
   else
   {
     numDaysInMonth = aNumDays[monthSelected];
   }
   datePointer  = 0
   dayPointer = startDate.getDay() - startAt
   
   if (dayPointer<0)
   {
     dayPointer = 6
   }
sHTML = "" if (showWeekNumber==1) { sHTML += ""
   }
   for  (i=0; i<7; i++)  {
sHTML += ""
   }
sHTML +="" if (showWeekNumber==1) { sHTML += ""
   }
   for  ( var i=1; i<=dayPointer;i++ )
   {
sHTML += ""
   }
 
   for  ( datePointer=1; datePointer<=numDaysInMonth; datePointer++ )
   {
     dayPointer++;
sHTML += "" if ((showWeekNumber==1)&&(datePointer<numDaysInMonth)) { sHTML += ""
       }
     }
   }
   document.getElementById("content").innerHTML   = sHTML
   document.getElementById("spanMonth").innerHTML = " " +  monthName[monthSelected] + " <IMG id="changeMonth" SRC=""+imgDir+"drop1.gif" WIDTH="12" HEIGHT="10" BORDER=0>"
   document.getElementById("spanYear").innerHTML =  " " + yearSelected  + " <IMG id="changeYear" SRC=""+imgDir+"drop1.gif" WIDTH="12" HEIGHT="10" BORDER=0>"
 }
 function popUpCalendar(ctl,  ctl2, format) {
   var  leftpos=0
   var  toppos=0
   if (bPageLoaded)
   {
     if ( crossobj.visibility ==  "hidden" ) {
       ctlToPlaceValue  = ctl2
       dateFormat=format;
       formatChar = " "
       aFormat  = dateFormat.split(formatChar)
       if (aFormat.length<3)
       {
         formatChar = "/"
         aFormat  = dateFormat.split(formatChar)
         if (aFormat.length<3)
         {
           formatChar = "."
           aFormat  = dateFormat.split(formatChar)
           if (aFormat.length<3)
           {
             formatChar = "-"
             aFormat  = dateFormat.split(formatChar)
             if (aFormat.length<3)
             {
               // invalid date  format
               formatChar=""
             }
           }
         }
       }
       tokensChanged =  0
       if ( formatChar  != "" )
       {
         // use user"s date
         aData =  ctl2.value.split(formatChar)
         for  (i=0;i<3;i++)
         {
           if ((aFormat[i]=="d") || (aFormat[i]=="dd"))
           {
             dateSelected = parseInt(aData[i], 10)
             tokensChanged ++
           }
           else if  ((aFormat[i]=="m") || (aFormat[i]=="mm"))
           {
             monthSelected =  parseInt(aData[i], 10) - 1
             tokensChanged ++
           }
           else if  (aFormat[i]=="yyyy")
           {
             yearSelected = parseInt(aData[i], 10)
             tokensChanged ++
           }
           else if  (aFormat[i]=="mmm")
           {
             for  (j=0; j<12;  j++)
             {
               if (aData[i]==monthName[j])
               {
                 monthSelected=j
                 tokensChanged ++
               }
             }
           }
         }
       }
       if ((tokensChanged!=3)||isNaN(dateSelected)||isNaN(monthSelected)||isNaN(yearSelected))
       {
         dateSelected = dateNow
         monthSelected =  monthNow
         yearSelected = yearNow
       }
       odateSelected=dateSelected
       omonthSelected=monthSelected
       oyearSelected=yearSelected
       /* Commented by D.T.  
         aTag = ctl
         do {
           aTag = aTag.offsetParent;
           leftpos  += aTag.offsetLeft;
           toppos += aTag.offsetTop;
         } while(aTag.tagName!="BODY");
         crossobj.left =  fixedX==-1 ? ctl.offsetLeft  + leftpos :  fixedX
         crossobj.top = fixedY==-1 ?  ctl.offsetTop +  toppos + ctl.offsetHeight +  2 :  fixedY
       */
       
       //Setting left and top of the calendar in a popUp window. Added by D.T.
       constructCalendar (1, monthSelected, yearSelected);
       crossobj.visibility=(dom||ie)? "visible" : "show"
     }
     else
     {
       hideCalendar()
       if (ctlNow!=ctl) {popUpCalendar(ctl, ctl2, format)}
     }
     ctlNow = ctl
   }
 }
 window.onload=init
 </script>

</HEAD> <BODY> <script language="javascript"> function window_open() { var newWindow; var urlstring = "calendar.htm" newWindow = window.open(urlstring,"","height=200,width=280,toolbar=no,minimize=no,status=no,memubar=no,location=no,scrollbars=no") } </script> <input type=text name="txtDate"><input type=button onClick="window_open()" value="..."> </BODY> </HTML>


 </source>
   
  

<A href="http://www.wbex.ru/Code/JavaScriptDownload/popwincal.zip">popwincal.zip( 10 k)</a>


Another DHTML Calendar

   <source lang="html4strict">

<!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.01 Transitional//EN"> <html><head><title>The Boring DHTML Date Picker Test</title>


<script type="text/javascript" language="JavaScript1.3"> /*

* The Boring Date Picker, a DTML widget to select a date.
* This code is released under GNU GPL, see file LICENSE for details.
*
* $Id: calendario.js,v 1.9 2003/09/24 16:15:24 neves Exp $
*/

// Initialize arrays. var months = new Array("Janeiro", "Fevereiro", "Marco", "Abril",

                      "Maio", "Junho", "Julho", "Agosto", 
                      "Setembro", "Outubro", "Novembro", "Dezembro");

var days = new Array("D", "S", "T", "Q", "Q", "S", "S"); /**

* id = id of calendar element in the page (unique in page)
* form = associated form of calendar element
*/

Calendar = function(id) {

   this.el = document.getElementById(id);
   this.displayDate = new Date();
   this.cid = id; //calendarId
   this.form = Calendar.getParentForm(this.el);
   this.form[id] = this; //now I can access the calendar from the form
   
   this.specialWeekDays = "06"; //weekend: saturday and sunday
   this.validInterval = [null, null];

};

//Static methods and utility functions Calendar.getParentForm = function(el) {

   var form = el.parentNode;
   while (form.tagName != "FORM") {
       //no error checking
 form = form.parentNode;
   }
   return form;

}

Calendar.monthsSize = new Array(31, 28, 31, 30, 31, 30,

                               31, 31, 30, 31, 30, 31); 

Calendar.daysInMonth = function(dt) {

   if (dt.getMonth() == 1) {
       var year = dt.getFullYear();
 return (((0 == year % 4) && (0 != (year % 100))) ||
               (0 == year % 400)) ? 29 : 28;
   }
   return Calendar.monthsSize[dt.getMonth()];

} Calendar.addEvent = function(el, evname, func) {

   //Using this to add static Calendar functions as events
   if (!func) var func = Calendar["on" + evname];
   evname = evname.toLowerCase();
   if (el.attachEvent) { // IE
       el.attachEvent("on" + evname, func);
   } else if (el.addEventListener) { // Gecko / W3C
       el.addEventListener(evname, func, true);
   } else { // Opera (or old browsers)
       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 { // Opera (or old browsers)
       el["on" + evname] = null;
   }

}; //Change element classes to be sensible to mouse over and click //so it have a feeling of pressed button Calendar.addMouseSensivity = function(el) {

   Calendar.addEvent(el, "MouseOver");
   Calendar.addEvent(el, "MouseOut");
   Calendar.addEvent(el, "MouseDown");
   Calendar.addEvent(el, "MouseUp");

}

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.hasClass = function(el, className) {

   var classes = el.className.split(" ");
   for (var i=0; i<classes.length; i++) {
       if (classes[i] == className) {
           return true;
       }
   }
   return false;

};

//##end of static methods Calendar.prototype.addHidden = function(name) {

   var el = document.createElement("input");
   el.type = "hidden";
   el.name = name;
   this.form.appendChild(el);

}; Calendar.prototype.setValidInterval = function(datesArray) {

   if (datesArray.length == 2) {
       this.validInterval = datesArray;
       if (this.validInterval[0] &&
           this.validInterval[0].valueOf() > this.displayDate.valueOf()) {
           this.displayDate = this.validInterval[0];
       } else if (this.validInterval[1] &&
           this.validInterval[1].valueOf() < this.displayDate.valueOf()) {
           this.displayDate = this.validInterval[1];
       }
   }

} Calendar.prototype.isDisabled = function(dt) {

   if (this.validInterval) {
       if (this.validInterval[0] &&
           this.validInterval[0].getTime() > dt.getTime()) {
           return true;
       } else if (this.validInterval[1] &&
                  this.validInterval[1].getTime() < dt.getTime()) {
           return true;
       }
   }
   return false;            

};

Calendar.prototype.setDisplayDate = function(dt) {

   if (!this.isDisabled(dt)) {
       this.displayDate = dt;
   } else {
       if (this.validInterval[0] &&
           this.displayDate.valueOf() < this.validInterval[0]) {
           this.displayDate = this.validInterval[0];
       } else {
           //so we must have na upper valid date
           this.displayDate = this.validInterval[1];
       }
   }
   this.draw();

}; Calendar.prototype.setDate = function(dt) {

   this.displayDate = dt;
   this.selectedDate = dt;
   var formDay = this.el.id + "Day";
   var formMonth = this.el.id + "Month";
   var formYear = this.el.id + "Year";
   var formDate = this.el.id + "Date";
   if (this.form[formDate] == null) {
 this.addHidden(formDay);
 this.addHidden(formYear);
 this.addHidden(formMonth);
 this.addHidden(formDate);
   }
   var y = dt.getFullYear();
   var m = dt.getMonth(); 
   var d = dt.getDate();
   this.form[formDay].value = d;
   this.form[formMonth].value = m;
   this.form[formYear].value = y;
   var a = this.form[formDate];
   a.value = y + "-" 
   if (m<9) a.value += "0";
   a.value += (m+1) + "-" //month to [1,12]
   if (d<10) a.value += "0";
   a.value += d; //2003-09-07
   this.draw();

}

//returns last day from previous month Calendar.previousMonth = function(dt) {

   var newMonth = dt.getMonth() - 1;
   var year = dt.getFullYear();
   if (newMonth < 0) {
      newMonth = 11;
      year--;
   }
   var previous = new Date(year, newMonth, 1);
   previous.setDate(Calendar.daysInMonth(previous));
   return previous;

} Calendar.prototype.decreaseMonth = function() {

   this.setDisplayDate(Calendar.previousMonth(this.displayDate));
   this.draw();

} //returns next day of next month Calendar.nextMonth = function(dt) {

   var newMonth = dt.getMonth() + 1;
   var year = dt.getFullYear();
   if (newMonth % 12 != newMonth) {
      newMonth = newMonth % 12;
      year++;
   }
   return new Date(year, newMonth, 1);

}

Calendar.prototype.increaseMonth = function() {

   this.setDisplayDate(Calendar.nextMonth(this.displayDate));
   this.draw();

}

Calendar.prototype.selectDay = function(dayCell) {

   var day = parseInt(dayCell.innerHTML);
   if (!isNaN(day)) {
       this.setDate(new Date(this.displayDate.getFullYear(),
                             this.displayDate.getMonth(),
                             day));
   }

}

//Let"s decorate the widget table with the classes we want Calendar.prototype.decorate = function() {

   var tds = this.form.getElementsByTagName("TD");
   for (var i=0; i<tds.length; i++) {
       //to allow access of calendar objects from events
       tds[i].datePicker = this;
       if (Calendar.hasClass(tds[i], "day")  &&
           !Calendar.hasClass(tds[i], "disabled")) {
           Calendar.addMouseSensivity(tds[i]);
           Calendar.addEvent(tds[i], "Click");
           
       } else if (Calendar.hasClass(tds[i], "button")) {
           Calendar.addMouseSensivity(tds[i]);
       }
   }
   

} /**

* Selected weekdays columns will have a different color.
* The default is to select the weekend (saturday and sunday).
*/

Calendar.prototype.setSpecialWeekDays = function(weekDaysArray) {

   if (weekDaysArray.length) {
       this.specialWeekDays = weekDaysArray.join(""); //strings have indexOf
   } else {
       this.specialWeekDays = "";
   }

} Calendar.onMouseOver = function(ev) {

   if (!ev) var ev = window.event;
   var el = ev.target ? ev.target : ev.srcElement;
   Calendar.addClass(el, "hilite");

} Calendar.onMouseOut = function(ev) {

   if (!ev) var ev = window.event;
   var el = ev.target ? ev.target : ev.srcElement;
   
   Calendar.removeClass(el, "hilite");
   Calendar.removeClass(el, "active");

} Calendar.onMouseDown = function(ev) {

   if (!ev) var ev = window.event;
   var el = ev.target ? ev.target : ev.srcElement;
   Calendar.removeClass(el, "hilite");
   Calendar.addClass(el, "active");

} Calendar.onMouseUp = function(ev) {

   if (!ev) var ev = window.event;
   var el = ev.target ? ev.target : ev.srcElement;
   Calendar.removeClass(el, "active");
   Calendar.addClass(el, "hilite");

} Calendar.onClick = function(ev) {

   if (!ev) var ev = window.event;
   var el = ev.target ? ev.target : ev.srcElement;
   Calendar.addClass(el, "selected");
   el.datePicker.selectDay(el);

} Calendar.prototype.getHeader = function () {

var header = "<td"; var lastDayMonthBefore = Calendar.previousMonth(this.displayDate); if (this.isDisabled(lastDayMonthBefore)) { header += "> "; } else { header += " onclick="this.datePicker.decreaseMonth();" class="button" title="Mes anterior">«"; } header += "</td>" + "<td colspan="5" class="title"> " + months[this.displayDate.getMonth()] + " " + this.displayDate.getFullYear() + " </td><td"; var firstDayNextMonth = Calendar.nextMonth(this.displayDate); if (this.isDisabled(firstDayNextMonth)) { header += "> "; } else { header += " onclick="this.datePicker.increaseMonth();" \ class="button" title="Proximo mes">»"; } header += "</td>"; return header; } /** * return weekdays header row */ Calendar.prototype.getWeekdays = function () { var weekDaysHeader = "<tr class="daynames">"; for (var i = 0; i < days.length; i++) { //Nonbreaking spaces to make it look better with coolest dhtml //calendar css weekDaysHeader += "<td class="name"; if (this.specialWeekDays.indexOf(i) != -1) { weekDaysHeader += " weekend" } weekDaysHeader += "">" + days[i] + "</td>"; } weekDaysHeader += "</tr>"; return weekDaysHeader; } Calendar.prototype.getDaysGrid = function () { var firstWeekday = (new Date(this.displayDate.getFullYear(), this.displayDate.getMonth(), 1)).getDay(); var gridSize = 7 * 6; //7 days in week, always with 6 rows var grid = new Array(gridSize); for (var i=0; i<gridSize; i++) { var day = i - firstWeekday + 1; if (day < 1 || day > Calendar.daysInMonth(this.displayDate)) { grid[i] = null; } else { grid [i] = day; } } return grid; } Calendar.prototype.getDays = function () { var daysTable = ""; var grid = this.getDaysGrid(); var weekDay; for (var i=0; i<grid.length; i++) { weekDay = i % 7; if (weekDay == 0) { daysTable += i!=0 ? "</tr>\n" : ""; daysTable += "<tr class="daysrow">\n"; } if (grid[i]) { daysTable += "<td class="day"; if (this.selectedDate && this.selectedDate.getFullYear() == this.displayDate.getFullYear() && this.selectedDate.getMonth() == this.displayDate.getMonth() && this.selectedDate.getDate() == grid[i]) { daysTable += " selected"; } if (this.specialWeekDays.indexOf(weekDay) != -1) { daysTable += " weekend"; } if (this.isDisabled(new Date(this.displayDate.getFullYear(), this.displayDate.getMonth(), grid[i]))) { daysTable += " disabled"; } daysTable += "">"+ grid[i] + "</td>"; } else { daysTable += "<td class="day disabled"> </td>"; } } // alert(daysTable) return daysTable + "</tr>" } Calendar.prototype.draw = function() { this.el.innerHTML = "
" + weekString + "<img src=""+imgDir+"divider.gif" width=1>"+ dayName[i]+"
" + WeekNbr(startDate) + "  "
     sStyle=styleAnchor
     if ((datePointer==odateSelected) &&  (monthSelected==omonthSelected)  && (yearSelected==oyearSelected))
     { sStyle+=styleLightBorder }
     sHint = ""
     for (k=0;k<HolidaysCounter;k++)
     {
       if ((parseInt(Holidays[k].d)==datePointer)&&(parseInt(Holidays[k].m)==(monthSelected+1)))
       {
         if ((parseInt(Holidays[k].y)==0)||((parseInt(Holidays[k].y)==yearSelected)&&(parseInt(Holidays[k].y)!=0)))
         {
           sStyle+="background-color:#FFDDDD;"
           sHint+=sHint==""?Holidays[k].desc:"\n"+Holidays[k].desc
         }
       }
     }
     var regexp= /\"/g
     sHint=sHint.replace(regexp,""")
     dateMessage = "onmousemove="window.status=\""+selectDateMessage.replace("[date]",constructDate(datePointer,monthSelected,yearSelected))+"\"" onmouseout="window.status=\"\"" "
     if ((datePointer==dateNow)&&(monthSelected==monthNow)&&(yearSelected==yearNow))
     { sHTML += "<a "+dateMessage+" title=\"" + sHint + "\" style=""+sStyle+"" href="javascript:dateSelected="+datePointer+";closeCalendar();"> " + datePointer + " </a>"}
     else if  (dayPointer % 7 == (startAt * -1)+1)
     { sHTML += "<a "+dateMessage+" title=\"" + sHint + "\" style=""+sStyle+"" href="javascript:dateSelected="+datePointer + ";closeCalendar();"> " + datePointer + " </a>" }
     else
     { sHTML += "<a "+dateMessage+" title=\"" + sHint + "\" style=""+sStyle+"" href="javascript:dateSelected="+datePointer + ";closeCalendar();"> " + datePointer + " </a>" }
     sHTML += ""
     if ((dayPointer+startAt) % 7 == startAt) { 
sHTML += "
" + (WeekNbr(new Date(yearSelected,monthSelected,datePointer+1))) + " 
<thead>\n" + this.getHeader() + this.getWeekdays() + "\n</thead><tbody>\n" + this.getDays(); + "\n</tbody>
";
   this.decorate();

}

</script>

<script type="text/javascript" language="JavaScript1.3"> /*

* This must run with jsunit from cvs from after 15/9
*
*$Id: calendario_test.js,v 1.7 2003/09/24 16:15:24 neves Exp $
*/

function setUp() {

   c = new Calendar("datePicker");
   form = document.forms[0]

}

function testGetParentForm() {

   assertEquals(document.formulario, c.form);  

}

function testSetDate() {

   var y = 1977;
   var m = 11;
   var d = 10;
   c.setDate(new Date(y, m, d,12));
   assertEquals(y+"", form.datePickerYear.value);
   assertEquals(d+"", form.datePickerDay.value);
   assertEquals(m+"", form.datePickerMonth.value);
   assertEquals(y+"-"+(m+1)+"-"+d, form.datePickerDate.value);

} function testGetHeader() {

   var month = 2;
   var year = 2001;
   c.setDate(new Date(year, month, 1));
   var h = c.getHeader();
   assertNotEquals("Header must have the year",
                   -1, 
                   h.toLowerCase().indexOf(year));
   assertNotEquals("Header must have the month",
                   -1, 
                   h.toLowerCase().indexOf(month));

} function equalArrays(array1, array2) {

   if (array1.length != array2.length) {
       return false;
   }
   for (var i=0; i<array1.length; i++) {
       if (array1[i] != array2[i]) {
           return false;
       }
   }
   return true;

} function testGetDaysGrid() {

   var grid;
   c.setDate(new Date(2003, 8, 1));
   var sep2003 = new Array(null, 1, 2, 3, 4, 5, 6,
                           7, 8, 9, 10, 11, 12, 13,
                           14, 15, 16, 17, 18, 19, 20,
                           21, 22, 23, 24, 25, 26, 27,
                           28, 29, 30, null, null, null, null,
                           null, null, null, null, null, null, null);
   grid = c.getDaysGrid();
   assert("Equal values for grid of september 2003",
          equalArrays(sep2003, grid));
   //starts saturday
   c.setDate(new Date(2003, 10, 1));
   var nov2003 = new Array(null, null, null, null, null, null, 1,
                           2, 3, 4, 5, 6, 7, 8,
                           9, 10, 11, 12, 13, 14, 15,
                           16, 17, 18, 19, 20, 21, 22,
                           23, 24, 25, 26, 27, 28, 29,
                           30, null, null, null, null, null, null);
   grid = c.getDaysGrid();
   assert("Equal values for grid of november 2003",
          equalArrays(nov2003, grid));
   //just 4 rows
   c.setDate(new Date(2009, 1, 1));
   var feb2009 = new Array(1, 2, 3, 4, 5, 6, 7,
                           8, 9, 10, 11, 12, 13, 14,
                           15, 16, 17, 18, 19, 20, 21,
                           22, 23, 24, 25, 26, 27, 28,
                           null, null, null, null, null, null, null,
                           null, null, null, null, null, null, null);
   grid = c.getDaysGrid();
   assert("Equal values for grid offebruary 2003",
          equalArrays(feb2009, grid));
   //bissext
   c.setDate(new Date(2004, 1, 1));
   var feb2004 = new Array(1, 2, 3, 4, 5, 6, 7,
                           8, 9, 10, 11, 12, 13, 14,
                           15, 16, 17, 18, 19, 20, 21,
                           22, 23, 24, 25, 26, 27, 28,
                           29, null, null, null, null, null, null,
                           null, null, null, null, null, null, null);
   grid = c.getDaysGrid();
   assert("Equal values for grid of february 2004",
          equalArrays(feb2004, grid));

}

//aux func to test increase and decrease function getTitleElement() {

   var el = form.getElementsByTagName("thead")[0];
   var childs =  el.getElementsByTagName("td");
   for (var i=0; i<childs.length; i++) {
       if (childs[i].className == "title") {
           el = childs[i];
       }
   }
   return el;

} function testIncreaseMonth() {

   var el;
   for (var i=0; i<11; i++) {
       c.setDate(new Date(2003, i ,1));
 c.increaseMonth();
       el = getTitleElement();
 assert("Increased Month name " + months[i+1] + 
              " isn"t in header cell",
              el.innerHTML.indexOf(months[i+1])!=-1);
   }
   c.increaseMonth();
   el = getTitleElement();
   assert("Increased Month name " + months[0] + " isn"t in header cell",
          el.innerHTML.indexOf(months[0])!=-1);

} function testDecreaseMonth() {

   var el;
   for (var i=11; i>0; i--) {
       c.setDate(new Date(2003, i ,1));
 c.decreaseMonth();
       el = getTitleElement();
 assert("Decreased Month name " + months[i-1] + 
              " isn"t in header cell",
              el.innerHTML.indexOf(months[i-1])!=-1);
   }
   c.decreaseMonth();
   el = getTitleElement();
   assert("Decreased Month name " + months[11] + " isn"t in header cell",
          el.innerHTML.indexOf(months[11])!=-1);

} function testHasClass() {

   var el = document.createElement("p");
   el.className = "abc";
   assert(Calendar.hasClass(el, "abc"));
   el.className = "abcde";
   assert(!Calendar.hasClass(el, "abc"));
   el.className = "abc cde";
   assert(Calendar.hasClass(el, "abc"));
   el.className = "cde abc";
   assert(Calendar.hasClass(el, "abc"));
   el.className = "aaa abc cde";
   assert(Calendar.hasClass(el, "abc"));

} function testAddClass() {

 var el = document.createElement("p");
 Calendar.addClass(el, "abc");
 assert(Calendar.hasClass(el, "abc"));
 Calendar.addClass(el, "abc");
 assert(Calendar.hasClass(el, "abc"));
 Calendar.addClass(el, "cde");
 assert(Calendar.hasClass(el, "abc"));
 assert(Calendar.hasClass(el, "cde"));

} function testRemoveClass() {

   var el = document.createElement("p");
   el.className = "abc";
   Calendar.removeClass(el, "abc");
   assert(!Calendar.hasClass(el, "abc"));
   Calendar.removeClass(el, "abc");
   assert(!Calendar.hasClass(el, "abc"));
   el.className = "abc cde eft";
   Calendar.removeClass(el, "cde");
   assert(Calendar.hasClass(el, "abc"));
   assert(Calendar.hasClass(el, "eft"));
   assert(!Calendar.hasClass(el, "cde"));

} function testSelectDay() {

   var y = 2003;
   var m = 9;
   var d = 15;
   c.setDate(new Date(y, m, d));
   var days = form.getElementsByTagName("TBODY");
   days = form.getElementsByTagName("TD");
   for (var i=0; i<days.length; i++) {
       if (parseInt(days[i].innerHTML) == d) {
           assert(Calendar.hasClass(days[i],"selected"));
       } else {
           assert(!Calendar.hasClass(days[i],"selected"));
       }
   }

} function testInvalidDates() {

   c.setDisplayDate(new Date(2003, 5, 22));
   var dateMin = new Date(2003, 5, 02);
   var dateMax = new Date(2003, 5, 29);
   var dateMiddle = new Date(2003, 5, 15);
   c.setValidInterval([dateMin, 
                       dateMax]);
   assert("Less than min must be disabled",
          c.isDisabled(new Date(2003, 5, 1)));
   assert("Greater than max must be disabled",
          c.isDisabled(new Date(2003, 5, 30)));
   assert("Date in middle must be valid",
          !c.isDisabled(dateMiddle));
   assert("Min interval date must be enabled",
          !c.isDisabled(dateMin));
   assert("Max interval date must be enabled",
          !c.isDisabled(dateMax));
   c.setDisplayDate(new Date(2003, 5, 1));
   assert("Display date can"t be set out of valid interval",
          c.displayDate.valueOf() >= dateMin.valueOf());
   c.setValidInterval([dateMiddle, 
                       dateMax]);
   assert("Display date can"t be set out of valid interval",
          c.displayDate.valueOf() >= dateMiddle.valueOf());
   
   //Days before limit are disabled
   c.setValidInterval([dateMin, 
                       dateMax]);
   var days = form.getElementsByTagName("TBODY")[1].getElementsByTagName("TD");
   
   for (var i=0; i<days.length; i++) {
       var cellDay = parseInt(days[i].innerHTML);
       if (!isNaN(cellDay) &&
           cellDay >= dateMin.getDate() &&
           cellDay <= dateMax.getDate()) {
           assert("Day " + cellDay + " can"t be disabled",
                  !Calendar.hasClass(days[i], "disabled"));
       } else {
           assert("Day " + cellDay + " in pos " + i + " must be disabled",
                  Calendar.hasClass(days[i], "disabled"));
       }
   }

}

function testDisabledArrows() {

   var dateMin = new Date(2003, 5, 02);
   var dateMax = new Date(2003, 6, 29);
   c.setValidInterval([dateMin, dateMax]);
   c.setDisplayDate(dateMin);
   c.draw();
   var header = form.getElementsByTagName("THEAD")[0].getElementsByTagName("TD");
   var leftArrow = header[0];
   var rightArrow = header[2];
   assert("Left arrow can"t be active if month before just has invalid dates",
          !Calendar.hasClass(leftArrow, "button"));
   assert("Right arrow must be active if month after has any valid date",
          Calendar.hasClass(rightArrow, "button"));
   c.setDisplayDate(dateMax);
   c.draw();
   header = form.getElementsByTagName("THEAD")[0].getElementsByTagName("TD");
   leftArrow = header[0];
   rightArrow = header[2];
   assert("Left arrow must be active if month before has any valid date",
          Calendar.hasClass(leftArrow, "button"));
   assert("Right arrow can"t be active if month after just has invalid dates",
          !Calendar.hasClass(rightArrow, "button"));

} </script>

<style rel="STYLESHEET" type="text/css" href=""> /* The main calendar widget. DIV containing a table. */ .calendar {

 position: relative;
 display: none;
 border-top: 2px solid #fff;
 border-right: 2px solid #000;
 border-bottom: 2px solid #000;
 border-left: 2px solid #fff;
 font-size: 11px;
 color: #000;
 cursor: default;
 background: #d4d0c8;
 font-family: tahoma,verdana,sans-serif;

} .calendar table {

 border-top: 1px solid #000;
 border-right: 1px solid #fff;
 border-bottom: 1px solid #fff;
 border-left: 1px solid #000;
 font-size: 11px;
 color: #000;
 cursor: default;
 background: #d4d0c8;
 font-family: tahoma,verdana,sans-serif;

} /* Header part -- contains navigation buttons and day names. */ .calendar .button { /* "<<", "<", ">", ">>" buttons have this class */

 text-align: center;
 padding: 1px;
 border-top: 1px solid #fff;
 border-right: 1px solid #000;
 border-bottom: 1px solid #000;
 border-left: 1px solid #fff;

} .calendar thead .title { /* This holds the current "month, year" */

 font-weight: bold;
 padding: 1px;
 border: 1px solid #000;
 background: #848078;
 color: #fff;
 text-align: center;

} .calendar thead .headrow { /* Row <TR> containing navigation buttons */ } .calendar thead .daynames { /* Row <TR> containing the day names */ } .calendar thead .name { /* Cells <TD> containing the day names */

 border-bottom: 1px solid #000;
 padding: 2px;
 text-align: center;
 background: #f4f0e8;

} .calendar thead .weekend { /* How a weekend day name shows in header */

 color: #f00;

} .calendar thead .hilite { /* How do the buttons in header appear when hover */

 border-top: 2px solid #fff;
 border-right: 2px solid #000;
 border-bottom: 2px solid #000;
 border-left: 2px solid #fff;
 padding: 0px;
 background: #e4e0d8;

} .calendar thead .active { /* Active (pressed) buttons in header */

 padding: 2px 0px 0px 2px;
 border-top: 1px solid #000;
 border-right: 1px solid #fff;
 border-bottom: 1px solid #fff;
 border-left: 1px solid #000;
 background: #c4c0b8;

}

/* The body part -- contains all the days in month. */ .calendar tbody .day { /* Cells <TD> containing month days dates */

 text-align: right;
 padding: 2px 4px 2px 2px;

} .calendar table .wn {

 padding: 2px 3px 2px 2px;
 border-right: 1px solid #000;
 background: #f4f0e8;

} .calendar tbody .rowhilite td {

 background: #e4e0d8;

} .calendar tbody .rowhilite td.wn {

 background: #d4d0c8;

} .calendar tbody td.hilite { /* Hovered cells <TD> */

 padding: 1px 3px 1px 1px;
 border-top: 1px solid #fff;
 border-right: 1px solid #000;
 border-bottom: 1px solid #000;
 border-left: 1px solid #fff;

}

.calendar tbody td.active { /* Active (pressed) cells <TD> */

 padding: 2px 2px 0px 2px;
 border-top: 1px solid #000;
 border-right: 1px solid #fff;
 border-bottom: 1px solid #fff;
 border-left: 1px solid #000;

} .calendar tbody td.selected { /* Cell showing selected date */

 font-weight: bold;
 border-top: 1px solid #000;
 border-right: 1px solid #fff;
 border-bottom: 1px solid #fff;
 border-left: 1px solid #000;
 padding: 2px 2px 0px 2px;
 background: #e4e0d8;

} .calendar tbody td.weekend { /* Cells showing weekend days */

 color: #f00;

} .calendar tbody td.today { /* Cell showing today date */

 font-weight: bold;
 color: #00f;

} .calendar tbody .disabled { color: #999; } .calendar tbody .emptycell { /* Empty cells (the best is to hide them) */

 visibility: hidden;

} .calendar tbody .emptyrow { /* Empty row (some months need less than 6 rows) */

 display: none;

} /* The footer part -- status bar and "Close" button */ .calendar tfoot .footrow { /* The <TR> in footer (only one right now) */ } .calendar tfoot .ttip { /* Tooltip (status bar) cell <TD> */

 background: #f4f0e8;
 padding: 1px;
 border: 1px solid #000;
 background: #848078;
 color: #fff;
 text-align: center;

} .calendar tfoot .hilite { /* Hover style for buttons in footer */

 border-top: 1px solid #fff;
 border-right: 1px solid #000;
 border-bottom: 1px solid #000;
 border-left: 1px solid #fff;
 padding: 1px;
 background: #e4e0d8;

} .calendar tfoot .active { /* Active (pressed) style for buttons in footer */

 padding: 2px 0px 0px 2px;
 border-top: 1px solid #000;
 border-right: 1px solid #fff;
 border-bottom: 1px solid #fff;
 border-left: 1px solid #000;

} /* Combo boxes (menus that display months/years for direct selection) */ .rubo {

 position: absolute;
 display: none;
 width: 4em;
 top: 0px;
 left: 0px;
 cursor: default;
 border-top: 1px solid #fff;
 border-right: 1px solid #000;
 border-bottom: 1px solid #000;
 border-left: 1px solid #fff;
 background: #e4e0d8;
 font-size: smaller;
 padding: 1px;

} .rubo .label {

 text-align: center;
 padding: 1px;

} .rubo .active {

 background: #c4c0b8;
 padding: 0px;
 border-top: 1px solid #000;
 border-right: 1px solid #fff;
 border-bottom: 1px solid #fff;
 border-left: 1px solid #000;

} .rubo .hilite {

 background: #048;
 color: #fea;

} </style> <style> .calendar tbody .day {

       width: 1em;

} .calendar thead .hilite {

       cursor: pointer;

} .calendar tbody td.hilite {

       cursor: pointer;

} .calendar tbody td.selected {

       font-weight: normal;
       color: blue;
       background: #FFA;

} .calendar thead .name {

       font-weight: bold;
/*       text-align: left;*/

}

.calendar tbody td.disabled.weekend {

 color: #f99;    

}

</style></head>

 <body onload="c=new Calendar("datePicker"); c.setValidInterval([new Date(2003, 7, 15), new Date(2005, 10, 25)]); c.draw()" bgcolor="#ffffff">

The Boring DHTML Date Picker Widget

</p>

Try it

Below is the sample of the Boring Date Picker Widget with valid dates from "2003-08-15" to "2005-11-25". Select a date.

<form action="" method="post" name="formulario">
<thead>

</thead><tbody>

</tbody>
-- Agosto 2005 --
D S T Q Q S S
 123456
78910111213
14151617181920
21222324252627
28293031   
       
         

       </form>
 </body></html>
          
        
 </source>
   
  


A Static Calendar by JavaScript

   <source lang="html4strict">

/* JavaScript Bible, Fourth Edition by Danny Goodman John Wiley & Sons CopyRight 2001

  • /

<HTML> <HEAD> <TITLE>JavaScripted Static Table</TITLE> <SCRIPT LANGUAGE="JavaScript"> // function becomes a method for each month object function getFirstDay(theYear, theMonth){

   var firstDate = new Date(theYear,theMonth,1)
   return firstDate.getDay() + 1

} // number of days in the month function getMonthLen(theYear, theMonth) {

   var oneDay = 1000 * 60 * 60 * 24
   var thisMonth = new Date(theYear, theMonth, 1)
   var nextMonth = new Date(theYear, theMonth + 1, 1)
   var len = Math.ceil((nextMonth.getTime() - 
       thisMonth.getTime())/oneDay)
   return len

} // correct for Y2K anomalies function getY2KYear(today) {

   var yr = today.getYear()
   return ((yr < 1900) ? yr+1900 : yr)

} // create basic array theMonths = new MakeArray(12) // load array with English month names function MakeArray(n) {

   this[0] = "January"
   this[1] = "February"
   this[2] = "March"
   this[3] = "April"
   this[4] = "May"
   this[5] = "June"
   this[6] = "July"
   this[7] = "August"
   this[8] = "September"
   this[9] = "October"
   this[10] = "November"
   this[11] = "December"
   this.length = n
   return this

} // end --> </SCRIPT> </HEAD> <BODY>

Month at a Glance (Static)


<SCRIPT LANGUAGE="JavaScript">

</SCRIPT> </BODY> </HTML>


 </source>
   
  


Building a Calculator

   <source lang="html4strict">

/* Mastering JavaScript, Premium Edition by James Jaworski ISBN:078212819X Publisher Sybex CopyRight 2001

  • /

<HTML> <HEAD> <TITLE>Calculator</TITLE> <SCRIPT LANGUAGE="JavaScript"></SCRIPT> </HEAD> <BODY> <SCRIPT LANGUAGE="JavaScript"></SCRIPT> <FORM NAME="calculator">

<INPUT TYPE="TEXT" NAME="total" VALUE="0" SIZE="15">
<INPUT TYPE="BUTTON" NAME="n0" VALUE=" 0 " ONCLICK="addDigit(0)"> <INPUT TYPE="BUTTON" NAME="n1" VALUE=" 1 " ONCLICK="addDigit(1)"> <INPUT TYPE="BUTTON" NAME="n2" VALUE=" 2 " ONCLICK="addDigit(2)">
<INPUT TYPE="BUTTON" NAME="n3" VALUE=" 3 " ONCLICK="addDigit(3)"> <INPUT TYPE="BUTTON" NAME="n4" VALUE=" 4 " ONCLICK="addDigit(4)"> <INPUT TYPE="BUTTON" NAME="n5" VALUE=" 5 " ONCLICK="addDigit(5)">
<INPUT TYPE="BUTTON" NAME="n6" VALUE=" 6 " ONCLICK="addDigit(6)"> <INPUT TYPE="BUTTON" NAME="n7" VALUE=" 7 " ONCLICK="addDigit(7)"> <INPUT TYPE="BUTTON" NAME="n8" VALUE=" 8 " ONCLICK="addDigit(8)">
<INPUT TYPE="BUTTON" NAME="n9" VALUE=" 9 " ONCLICK="addDigit(9)"> <INPUT TYPE="BUTTON" NAME="decimal" VALUE=" . " ONCLICK="addDecimalPoint()"> <INPUT TYPE="BUTTON" NAME="plus" VALUE=" + " ONCLICK="performOp("+")">
<INPUT TYPE="BUTTON" NAME="minus" VALUE=" - " ONCLICK="performOp("-")"> <INPUT TYPE="BUTTON" NAME="multiply" VALUE=" * " ONCLICK="performOp("*")"> <INPUT TYPE="BUTTON" NAME="divide" VALUE=" / " ONCLICK="performOp("/")">
<INPUT TYPE="BUTTON" NAME="equals" VALUE=" = " ONCLICK="calc()"> <INPUT TYPE="BUTTON" NAME="sign" VALUE=" +/- " ONCLICK="changeSign()"> <INPUT TYPE="BUTTON" NAME="clearField" VALUE=" C " ONCLICK="clearDisplay()">

</FORM> </BODY> </HTML>


 </source>
   
  


Calendar Control - 2-Up Implementation

   <source lang="html4strict">

<!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.01//EN" "http://www.w3.org/TR/html4/strict.dtd"> <html> <head>

 <title>Yahoo! Calendar Control - 2-Up Implementation</title>
 
 <script type="text/javascript" src="./build/yahoo/yahoo.js"></script>
 <script type="text/javascript" src="./build/event/event.js" ></script>
 <script type="text/javascript" src="./build/dom/dom.js" ></script>
 
 <link type="text/css" rel="stylesheet" href="./build/fonts/fonts.css">
 <link type="text/css" rel="stylesheet" href="./build/reset/reset.css">  
 <link rel="stylesheet" type="text/css" href="./docs/assets/dpSyntaxHighlighter.css" />
 <script type="text/javascript" src="./build/calendar/calendar.js"></script>
 <link type="text/css" rel="stylesheet" href="./build/calendar/assets/calendar.css">  
 
 <script language="javascript">
   YAHOO.namespace("example.calendar");
   function init() {
     this.today = new Date();
     var thisMonth = this.today.getMonth();
     var thisDay = this.today.getDate();
     var thisYear = this.today.getFullYear();
     this.link1 = document.getElementById("dateLink1");
     this.link2 = document.getElementById("dateLink2");
     this.selMonth1 = document.getElementById("selMonth1");
     this.selDay1 = document.getElementById("selDay1");
     this.selMonth1.selectedIndex = thisMonth;
     this.selDay1.selectedIndex = thisDay-1;
     this.selMonth2 = document.getElementById("selMonth2");
     this.selDay2 = document.getElementById("selDay2");
     this.selMonth2.selectedIndex = thisMonth;
     this.selDay2.selectedIndex = thisDay-1;
     YAHOO.example.calendar.cal1 = new YAHOO.widget.Calendar2up("YAHOO.example.calendar.cal1","container1",(thisMonth+1)+"/"+thisYear,(thisMonth+1)+"/"+thisDay+"/"+thisYear);
     YAHOO.example.calendar.cal1.title = "Select your desired departure date:";
     YAHOO.example.calendar.cal1.setChildFunction("onSelect",setDate1);
     YAHOO.example.calendar.cal1.render();
     
     YAHOO.example.calendar.cal2 = new YAHOO.widget.Calendar2up("YAHOO.example.calendar.cal2","container2",(thisMonth+1)+"/"+thisYear,(thisMonth+1)+"/"+thisDay+"/"+thisYear);
     YAHOO.example.calendar.cal2.title = "Select your desired return date:";
     YAHOO.example.calendar.cal2.setChildFunction("onSelect",setDate2);
     YAHOO.example.calendar.cal2.render();
   }
   function showCalendar1() {
     YAHOO.example.calendar.cal2.hide();
     
     var pos = YAHOO.util.Dom.getXY(link1);
     YAHOO.example.calendar.cal1.outerContainer.style.display="block";
     YAHOO.util.Dom.setXY(YAHOO.example.calendar.cal1.outerContainer, [pos[0],pos[1]+link1.offsetHeight+1]);
   }
   function showCalendar2() {
     YAHOO.example.calendar.cal1.hide();
     var pos = YAHOO.util.Dom.getXY(link2);
     YAHOO.example.calendar.cal2.outerContainer.style.display="block";
     YAHOO.util.Dom.setXY(YAHOO.example.calendar.cal2.outerContainer, [pos[0],pos[1]+link2.offsetHeight+1]);
   }
   function setDate1() {
     var date1 = YAHOO.example.calendar.cal1.getSelectedDates()[0];
     selMonth1.selectedIndex=date1.getMonth();
     selDay1.selectedIndex=date1.getDate()-1;
     YAHOO.example.calendar.cal1.hide();
   }
   function setDate2() {
     var date2 = YAHOO.example.calendar.cal2.getSelectedDates()[0];
     selMonth2.selectedIndex=date2.getMonth();
     selDay2.selectedIndex=date2.getDate()-1;
     YAHOO.example.calendar.cal2.hide();
   }
   function changeDate1() {
     var month = this.selMonth1.selectedIndex;
     var day = this.selDay1.selectedIndex + 1;
     var year = this.today.getFullYear();
     YAHOO.example.calendar.cal1.select((month+1) + "/" + day + "/" + year);
     YAHOO.example.calendar.cal1.setMonth(month);
     YAHOO.example.calendar.cal1.render();
   }
   function changeDate2() {
     var month = this.selMonth2.selectedIndex;
     var day = this.selDay2.selectedIndex + 1;
     var year = this.today.getFullYear();
     
     YAHOO.example.calendar.cal2.select((month+1) + "/" + day + "/" + year);
     YAHOO.example.calendar.cal2.setMonth(month);
     YAHOO.example.calendar.cal2.render();
   }  
   YAHOO.util.Event.addListener(window, "load", init);    
 </script>

</head> <body style="margin:0px"> <img src="./examples/calendar/default_2up/img/ytravel.gif" id="bgImg">

 <select id="selMonth1" name="selMonth1" onchange="changeDate1()" style="vertical-align:middle">
 <option value="Jan">
 Jan
 </option>
 <option value="Feb">
 Feb
 </option>
 <option value="Mar">
 Mar
 </option>
 <option value="Apr">
 Apr
 </option>
 <option value="May">
 May
 </option>
 <option value="Jun">
 Jun
 </option>
 <option value="Jul">
 Jul
 </option>
 <option value="Aug">
 Aug
 </option>
 <option value="Sep">
 Sep
 </option>
 <option value="Oct">
 Oct
 </option>
 <option value="Nov">
 Nov
 </option>
 <option value="Dec">
 Dec
 </option>
 </select>
 <select name="selDay1" id="selDay1" onchange="changeDate1()" style="vertical-align:middle">
 <option value="1">
 1
 </option>
 <option value="2">
 2
 </option>
 <option value="3">
 3
 </option>
 <option value="4">
 4
 </option>
 <option value="5">
 5
 </option>
 <option value="6">
 6
 </option>
 <option value="7">
 7
 </option>
 <option value="8">
 8
 </option>
 <option value="9">
 9
 </option>
 <option value="10">
 10
 </option>
 <option value="11">
 11
 </option>
 <option value="12">
 12
 </option>
 <option value="13">
 13
 </option>
 <option value="14">
 14
 </option>
 <option value="15">
 15
 </option>
 <option value="16">
 16
 </option>
 <option value="17">
 17
 </option>
 <option value="18">
 18
 </option>
 <option value="19">
 19
 </option>
 <option value="20">
 20
 </option>
 <option value="21">
 21
 </option>
 <option value="22">
 22
 </option>
 <option value="23">
 23
 </option>
 <option value="24">
 24
 </option>
 <option value="25">
 25
 </option>
 <option value="26">
 26
 </option>
 <option value="27">
 27
 </option>
 <option value="28">
 28
 </option>
 <option value="29">
 29
 </option>
 <option value="30">
 30
 </option>
 <option value="31">
 31
 </option>
 </select><a href="javascript:void(null)" onclick="showCalendar1()"><img id="dateLink1" src="./examples/calendar/img/pdate.gif" border="0" style="vertical-align:middle;margin:5px"/></a>
 <select id="selMonth2" name="selMonth2" onchange="changeDate2()" style="vertical-align:middle">
 <option value="Jan">
 Jan
 </option>
 <option value="Feb">
 Feb
 </option>
 <option value="Mar">
 Mar
 </option>
 <option value="Apr">
 Apr
 </option>
 <option value="May">
 May
 </option>
 <option value="Jun">
 Jun
 </option>
 <option value="Jul">
 Jul
 </option>
 <option value="Aug">
 Aug
 </option>
 <option value="Sep">
 Sep
 </option>
 <option value="Oct">
 Oct
 </option>
 <option value="Nov">
 Nov
 </option>
 <option value="Dec">
 Dec
 </option>
 </select>
 <select name="selDay2" id="selDay2" onchange="changeDate2()" style="vertical-align:middle">
 <option value="1">
 1
 </option>
 <option value="2">
 2
 </option>
 <option value="3">
 3
 </option>
 <option value="4">
 4
 </option>
 <option value="5">
 5
 </option>
 <option value="6">
 6
 </option>
 <option value="7">
 7
 </option>
 <option value="8">
 8
 </option>
 <option value="9">
 9
 </option>
 <option value="10">
 10
 </option>
 <option value="11">
 11
 </option>
 <option value="12">
 12
 </option>
 <option value="13">
 13
 </option>
 <option value="14">
 14
 </option>
 <option value="15">
 15
 </option>
 <option value="16">
 16
 </option>
 <option value="17">
 17
 </option>
 <option value="18">
 18
 </option>
 <option value="19">
 19
 </option>
 <option value="20">
 20
 </option>
 <option value="21">
 21
 </option>
 <option value="22">
 22
 </option>
 <option value="23">
 23
 </option>
 <option value="24">
 24
 </option>
 <option value="25">
 25
 </option>
 <option value="26">
 26
 </option>
 <option value="27">
 27
 </option>
 <option value="28">
 28
 </option>
 <option value="29">
 29
 </option>
 <option value="30">
 30
 </option>
 <option value="31">
 31
 </option>
 </select><a href="javascript:void(null)" onclick="showCalendar2()"><img id="dateLink2" src="./examples/calendar/img/pdate.gif" border="0" style="vertical-align:middle;margin:5px"/></a>

<script src="./docs/assets/dpSyntaxHighlighter.js"></script> <script language="javascript"> dp.SyntaxHighlighter.HighlightAll("code"); </script> </body> </html>


 </source>
   
  

<A href="http://www.wbex.ru/Code/JavaScriptDownload/yui.zip">yui.zip( 3,714 k)</a>


Calendar Control - Custom Renderer Example (Holiday Renderer Implementation)

   <source lang="html4strict">

<!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.01//EN" "http://www.w3.org/TR/html4/strict.dtd"> <html> <head>

 <title>Yahoo! Calendar Control - Custom Renderer Example</title>
 
 <link rel="stylesheet" href="./examples/calendar/css/examples.css" type="text/css">
 
 <script type="text/javascript" src="./build/yahoo/yahoo.js"></script>
 <script type="text/javascript" src="./build/event/event.js" ></script>
 <script type="text/javascript" src="./build/dom/dom.js" ></script>
 
 <link type="text/css" rel="stylesheet" href="./build/fonts/fonts.css">
 <link type="text/css" rel="stylesheet" href="./build/reset/reset.css">
 <link rel="stylesheet" type="text/css" href="./docs/assets/dpSyntaxHighlighter.css" />
 <script type="text/javascript" src="./build/calendar/calendar.js"></script>
 <link type="text/css" rel="stylesheet" href="./build/calendar/assets/calendar.css">  
 
 <style>
   .yui-calendar td.holiday {
     background-color:yellow;
     font-weight:bold;
   }
 </style>
 <script language="javascript">
   YAHOO.namespace("example.calendar");
   YAHOO.example.calendar.renderHoliday = function(workingDate, cell) {
     YAHOO.util.Dom.addClass(cell, "holiday");
   }
   function init() {
     YAHOO.example.calendar.cal1 = new YAHOO.widget.Calendar("YAHOO.example.calendar.cal1","cal1Container","1/2006");
     YAHOO.example.calendar.cal1.addRenderer("12/25,1/1", YAHOO.example.calendar.renderHoliday);
     YAHOO.example.calendar.cal1.render();
   }
   YAHOO.util.Event.addListener(window, "load", init);
 </script>

</head> <body>

 <img id="logo" src="../img/logo.gif"/>
 

Calendar Control

Holiday Renderer Implementation

Here is an example of how to create renderers to format specific holidays with a special style:

<textarea name="code" class="JScript" cols="60" rows="1"> var cal1; var renderHoliday = function(workingDate, cell) {

 YAHOO.util.Dom.addClass(cell, "holiday");

} function init() {

 cal1 = new YAHOO.widget.Calendar("cal1","cal1Container");
 cal1.addRenderer("12/25,1/1", renderHoliday);
 cal1.render();

} </textarea>

       <a href="javascript:YAHOO.example.calendar.cal1.reset()" class="navLink" style="font-size:12px;text-decoration:underline">reset</a>|
       <a href="javascript:alert(YAHOO.example.calendar.cal1.getSelectedDates())" class="navLink" style="font-size:12px;text-decoration:underline">what"s selected?</a>

<script src="./docs/assets/dpSyntaxHighlighter.js"></script> <script language="javascript"> dp.SyntaxHighlighter.HighlightAll("code"); </script> </body> </html>


 </source>
   
  

<A href="http://www.wbex.ru/Code/JavaScriptDownload/yui.zip">yui.zip( 3,714 k)</a>


Calendar Control - Date Restriction Example (Date Restriction Implementation)

   <source lang="html4strict">

<!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.01//EN" "http://www.w3.org/TR/html4/strict.dtd"> <html> <head>

 <title>Yahoo! Calendar Control - Date Restriction Example</title>
 
 <link rel="stylesheet" href="./examples/calendar/css/examples.css" type="text/css">
 
 <script type="text/javascript" src="./build/yahoo/yahoo.js"></script>
 <script type="text/javascript" src="./build/event/event.js" ></script>
 <script type="text/javascript" src="./build/dom/dom.js" ></script>
 <link type="text/css" rel="stylesheet" href="./build/fonts/fonts.css">
 <link type="text/css" rel="stylesheet" href="./build/reset/reset.css">
 <link rel="stylesheet" type="text/css" href="./docs/assets/dpSyntaxHighlighter.css" />
 <script type="text/javascript" src="./build/calendar/calendar.js"></script>
 <link type="text/css" rel="stylesheet" href="./build/calendar/assets/calendar.css">
 
 <script language="javascript">
   YAHOO.namespace("example.calendar");
   function init() {
     YAHOO.example.calendar.cal1 = new YAHOO.widget.Calendar("YAHOO.example.calendar.cal1","cal1Container","2/2006");
     YAHOO.example.calendar.cal1.addRenderer("2/28/2006",YAHOO.example.calendar.cal1.renderBodyCellRestricted);
     YAHOO.example.calendar.cal1.render();
   }
 </script>
 

</head> <body onload="init()">

 <img id="logo" src="../img/logo.gif"/>
 

Calendar Control

Date Restriction Implementation

This example shows how to restrict selection of a specific date:

<textarea name="code" class="JScript" cols="60" rows="1"> var cal1; function init() {

 cal1 = new YAHOO.widget.Calendar("cal1","cal1Container");
 cal1.addRenderer("2/28/2006",cal1.renderBodyCellRestricted);
 cal1.render();

} </textarea>

       <a href="javascript:YAHOO.example.calendar.cal1.reset()" class="navLink" style="font-size:12px;text-decoration:underline">reset</a>|
       <a href="javascript:alert(YAHOO.example.calendar.cal1.getSelectedDates())" class="navLink" style="font-size:12px;text-decoration:underline">what"s selected?</a>

<script src="./docs/assets/dpSyntaxHighlighter.js"></script> <script language="javascript"> dp.SyntaxHighlighter.HighlightAll("code"); </script> </body> </html>


 </source>
   
  

<A href="http://www.wbex.ru/Code/JavaScriptDownload/yui.zip">yui.zip( 3,714 k)</a>


Calendar Control - Handling onSelect / onDeselect

   <source lang="html4strict">

<!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.01//EN" "http://www.w3.org/TR/html4/strict.dtd"> <html> <head>

 <title>Yahoo! Calendar Control - Handling onSelect / onDeselect</title>
 
 <link rel="stylesheet" href="./examples/calendar/css/examples.css" type="text/css">
 
 <script type="text/javascript" src="./build/yahoo/yahoo.js"></script>
 <script type="text/javascript" src="./build/event/event.js" ></script>
 <script type="text/javascript" src="./build/dom/dom.js" ></script>
 <link type="text/css" rel="stylesheet" href="./build/fonts/fonts.css">
 <link type="text/css" rel="stylesheet" href="./build/reset/reset.css">  
 <link rel="stylesheet" type="text/css" href="./docs/assets/dpSyntaxHighlighter.css" />
 <script type="text/javascript" src="./build/calendar/calendar.js"></script>
 <link type="text/css" rel="stylesheet" href="./build/calendar/assets/calendar.css">  
 
 <script language="javascript">
   YAHOO.namespace("example.calendar");
   function init() {
     YAHOO.example.calendar.cal1 = new YAHOO.widget.Calendar("YAHOO.example.calendar.cal1", "cal1Container");
     YAHOO.example.calendar.cal1.Options.MULTI_SELECT = true;
     YAHOO.example.calendar.cal1.onSelect = function(selected) {
       alert("selected: " + selected);
     }
     YAHOO.example.calendar.cal1.onDeselect = function(deselected) {
       alert("deselected: " + deselected);
     }
     YAHOO.example.calendar.cal1.render();
   }
 </script>
 

</head> <body onload="init()">

Calendar Control

Handling onSelect / onDeselect

Dates are passed as an array of date field arrays, in the format: [YYYY, M, D]. For instance, if two dates are selected at once (8/6/2006 and 8/7/2006), the argument passed to onSelect would be: [ [2006,8,6], [2006,8,7] ].

<textarea name="code" class="JScript" cols="60" rows="1"> function init() {

 cal1 = new YAHOO.widget.Calendar("cal1", "cal1Container");
 cal1.Options.MULTI_SELECT = true;
 cal1.onSelect = function(selected) {
   alert("selected: " + selected);
 }
 cal1.onDeselect = function(deselected) {
   alert("deselected: " + deselected);
 }
 cal1.render();

} </textarea>

     <a href="javascript:YAHOO.example.calendar.cal1.reset()" class="navLink" style="font-size:12px;text-decoration:underline">reset</a>|
     <a href="javascript:alert(YAHOO.example.calendar.cal1.getSelectedDates())" class="navLink" style="font-size:12px;text-decoration:underline">what"s selected?</a>

<script src="./docs/assets/dpSyntaxHighlighter.js"></script> <script language="javascript"> dp.SyntaxHighlighter.HighlightAll("code"); </script> </body> </html>


 </source>
   
  

<A href="http://www.wbex.ru/Code/JavaScriptDownload/yui.zip">yui.zip( 3,714 k)</a>


Calendar Control - Mix/Max Implementation

   <source lang="html4strict">

<!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.01//EN" "http://www.w3.org/TR/html4/strict.dtd"> <html> <head>

 <title>Yahoo! Calendar Control - Mix/Max Implementation</title>
 
 <link rel="stylesheet" href="./examples/calendar/css/examples.css" type="text/css">
 
 <script type="text/javascript" src="./build/yahoo/yahoo.js"></script>
 <script type="text/javascript" src="./build/event/event.js" ></script>
 <script type="text/javascript" src="./build/dom/dom.js" ></script>
 
 <link type="text/css" rel="stylesheet" href="./build/fonts/fonts.css">
 <link type="text/css" rel="stylesheet" href="./build/reset/reset.css">
 <link rel="stylesheet" type="text/css" href="./docs/assets/dpSyntaxHighlighter.css" />
 <script type="text/javascript" src="./build/calendar/calendar.js"></script>
 <link type="text/css" rel="stylesheet" href="./build/calendar/assets/calendar.css">  
 <script language="javascript">
   YAHOO.namespace("example.calendar");
   function init() {
     YAHOO.example.calendar.cal1 = new YAHOO.widget.Calendar("YAHOO.example.calendar.cal1","cal1Container");
     YAHOO.example.calendar.cal1.minDate = YAHOO.widget.DateMath.add(new Date(), YAHOO.widget.DateMath.DAY, 1);
     YAHOO.example.calendar.cal1.render();
   }
 </script>

</head> <body onload="init()">

Calendar Control

Future-Only Single-Select Implementation

To construct a calendar where the user can only select future dates, the code would read as follows:

<textarea name="code" class="JScript" cols="60" rows="1"> var cal1; function init() {

  cal1 = new YAHOO.widget.Calendar("cal1", "cal1Container");
  cal1.minDate = YAHOO.widget.DateMath.add(new Date(), YAHOO.widget.DateMath.DAY, 1);
  cal1.render();

} </textarea>

Notice that we"re setting the minimum date to tomorrow"s date by adding one day to a newly instantiated date (using the DateMath helper class) and setting it into the calendar"s minDate property. cal1.maxDate remains null since there is no restriction on how far into the future the user can make selections.


     <a href="javascript:YAHOO.example.calendar.cal1.reset()" class="navLink" style="font-size:12px;text-decoration:underline">reset</a>|
     <a href="javascript:alert(YAHOO.example.calendar.cal1.getSelectedDates())" class="navLink" style="font-size:12px;text-decoration:underline">what"s selected?</a>

<script src="./docs/assets/dpSyntaxHighlighter.js"></script> <script language="javascript"> dp.SyntaxHighlighter.HighlightAll("code"); </script> </body> </html>


 </source>
   
  

<A href="http://www.wbex.ru/Code/JavaScriptDownload/yui.zip">yui.zip( 3,714 k)</a>


Calendar Control - Multi-Select 2-up Implementation

   <source lang="html4strict">

<!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.01//EN" "http://www.w3.org/TR/html4/strict.dtd"> <html> <head>

 <title>Yahoo! Calendar Control - Multi-Select 2-up Implementation</title>
 
 <link rel="stylesheet" href="./examples/calendar/css/examples.css" type="text/css">
 
 <script type="text/javascript" src="./build/yahoo/yahoo.js"></script>
 <script type="text/javascript" src="./build/event/event.js" ></script>
 <script type="text/javascript" src="./build/dom/dom.js" ></script>
 
 <link type="text/css" rel="stylesheet" href="./build/fonts/fonts.css">
 <link type="text/css" rel="stylesheet" href="./build/reset/reset.css">  
 <link rel="stylesheet" type="text/css" href="./docs/assets/dpSyntaxHighlighter.css" />
 <script type="text/javascript" src="./build/calendar/calendar.js"></script>
 <link type="text/css" rel="stylesheet" href="./build/calendar/assets/calendar.css">  
 <script language="javascript">
   YAHOO.namespace("example.calendar");
   function init() {
     YAHOO.example.calendar.cal1 = new YAHOO.widget.Calendar2up("YAHOO.example.calendar.cal1","cal1Container");
     var customConfig = function() {
       this.Options.MULTI_SELECT = true;
     }
     
     YAHOO.example.calendar.cal1.setChildFunction("customConfig", customConfig);
     YAHOO.example.calendar.cal1.callChildFunction("customConfig");
     YAHOO.example.calendar.cal1.render();
   }
   YAHOO.util.Event.addListener(window, "load", init);
 </script>
 

</head> <body>

 <img id="logo" src="../img/logo.gif"/>
 

Calendar Control

Multi-Select 2-up Implementation

To allow for multiple selections on a 2-up Calendar, use the following code:

   <textarea name="code" class="JScript" cols="60" rows="1">
   var cal1;
   function init() {
     cal1 = new YAHOO.widget.Calendar2up("cal1","cal1Container");
     var customConfig = function() {
       this.Options.MULTI_SELECT = true;
     }
     
     cal1.setChildFunction("customConfig", customConfig);
     cal1.callChildFunction("customConfig");
     cal1.render();
   }
   </textarea>
<textarea name="code" class="HTML" cols="60" rows="1">
</textarea>

</body> <script src="./docs/assets/dpSyntaxHighlighter.js"></script> <script language="javascript"> dp.SyntaxHighlighter.HighlightAll("code"); </script> </html>


 </source>
   
  

<A href="http://www.wbex.ru/Code/JavaScriptDownload/yui.zip">yui.zip( 3,714 k)</a>


Calendar Control - Multi-Select Implementation

   <source lang="html4strict">

<!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.01//EN" "http://www.w3.org/TR/html4/strict.dtd"> <html> <head>

 <title>Yahoo! Calendar Control - Multi-Select Implementation</title>
 <link rel="stylesheet" href="./examples/calendar/css/examples.css" type="text/css">
 
 <script type="text/javascript" src="./build/yahoo/yahoo.js"></script>
 <script type="text/javascript" src="./build/event/event.js" ></script>
 <script type="text/javascript" src="./build/dom/dom.js" ></script>
 <link type="text/css" rel="stylesheet" href="./build/fonts/fonts.css">
 <link type="text/css" rel="stylesheet" href="./build/reset/reset.css">  
 <link rel="stylesheet" type="text/css" href="./docs/assets/dpSyntaxHighlighter.css" />
 <script type="text/javascript" src="./build/calendar/calendar.js"></script>
 <link type="text/css" rel="stylesheet" href="./build/calendar/assets/calendar.css">  
 
 <script language="javascript">
   YAHOO.namespace("example.calendar");
   function init() {
     YAHOO.example.calendar.cal1 = new YAHOO.widget.Calendar("YAHOO.example.calendar.cal1", "cal1Container");
     YAHOO.example.calendar.cal1.Options.MULTI_SELECT = true;
     YAHOO.example.calendar.cal1.render();
   }
 </script>
 

</head> <body onload="init()">

Calendar Control

Simple Multi-Select Implementation

This implementation allows for selection of multiple values. This is accomplished by simply changing an option in the calendar configuration options:

<textarea name="code" class="JScript" cols="60" rows="1"> var cal1; function init() {

  cal1 = new YAHOO.widget.Calendar("cal1", "cal1Container");
  cal1.Options.MULTI_SELECT = true;
  cal1.render();

} </textarea>

     <a href="javascript:YAHOO.example.calendar.cal1.reset()" class="navLink" style="font-size:12px;text-decoration:underline">reset</a>|
     <a href="javascript:alert(YAHOO.example.calendar.cal1.getSelectedDates())" class="navLink" style="font-size:12px;text-decoration:underline">what"s selected?</a>

<script src="./docs/assets/dpSyntaxHighlighter.js"></script> <script language="javascript"> dp.SyntaxHighlighter.HighlightAll("code"); </script> </body> </html>


 </source>
   
  

<A href="http://www.wbex.ru/Code/JavaScriptDownload/yui.zip">yui.zip( 3,714 k)</a>


Calendar Control - Row Highlight Example (Row Highlight Implementation)

   <source lang="html4strict">

<!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.01//EN" "http://www.w3.org/TR/html4/strict.dtd"> <html> <head>

 <title>Yahoo! Calendar Control - Row Highlight Example</title>
 
 <link rel="stylesheet" href="./examples/calendar/css/examples.css" type="text/css">
 
 <script type="text/javascript" src="./build/yahoo/yahoo.js"></script>
 <script type="text/javascript" src="./build/event/event.js" ></script>
 <script type="text/javascript" src="./build/dom/dom.js" ></script>
 <link type="text/css" rel="stylesheet" href="./build/fonts/fonts.css">
 <link type="text/css" rel="stylesheet" href="./build/reset/reset.css">
 <link rel="stylesheet" type="text/css" href="./docs/assets/dpSyntaxHighlighter.css" />
 <script type="text/javascript" src="./build/calendar/calendar.js"></script>
 <link type="text/css" rel="stylesheet" href="./build/calendar/assets/calendar.css">
 
 <style> 
   /* highlight the whole row */
   .yui-calendar tr.hilite-row td.calcell {
     background-color:yellow;
   }
   /* highlight the current cell in the standard highlight color */
   .yui-calendar tr.hilite-row td.calcellhover {
     cursor:pointer;
     color:#FFF;
     background-color:#FF9900;
     border:1px solid #FF9900;
   }
   /* make sure out of month cells don"t highlight too */
   .yui-calendar tr.hilite-row td.calcell.oom {
     cursor:default;
     color:#999;
     background-color:#EEE;
     border:1px solid #E0E0E0;
   }
 </style>
 <script language="javascript">
   YAHOO.namespace("example.calendar");
   function init() {
     YAHOO.example.calendar.cal1 = new YAHOO.widget.Calendar("YAHOO.example.calendar.cal1","cal1Container");
     
     /* Override the doCellMouseOver function (used for IE) to add row highlighting) */
     YAHOO.example.calendar.cal1.doCellMouseOver = function(e, cal) {
       var cell = this;
       var row = cell.parentNode;
       YAHOO.util.Dom.addClass(this, cal.Style.CSS_CELL_HOVER);
       YAHOO.util.Dom.addClass(row, "hilite-row");
     }
     /* Override the doCellMouseOut function (used for IE) to remove row highlighting) */
     YAHOO.example.calendar.cal1.doCellMouseOut = function(e, cal) {
       var cell = this;
       var row = cell.parentNode;
       YAHOO.util.Dom.removeClass(this, cal.Style.CSS_CELL_HOVER);
       YAHOO.util.Dom.removeClass(row, "hilite-row");
     }
     YAHOO.example.calendar.cal1.render();
   }
 </script>
 

</head> <body onload="init()">

 <img id="logo" src="../img/logo.gif"/>
 

Calendar Control

Row Highlight Implementation

This example shows how to highlight the row of the current hover date, using CSS and some minor JavaScript event changes:

<textarea name="code" class="JScript" cols="60" rows="1">

 <style> 
   /* highlight the whole row */
   .yui-calendar tr.hilite-row td.calcell {
     background-color:yellow;
   }
   /* highlight the current cell in the standard highlight color */
   .yui-calendar tr.hilite-row td.calcellhover {
     cursor:pointer;
     color:#FFF;
     background-color:#FF9900;
     border:1px solid #FF9900;
   }
   /* make sure out of month cells don"t highlight too */
   .yui-calendar tr.hilite-row td.calcell.oom {
     cursor:default;
     color:#999;
     background-color:#EEE;
     border:1px solid #E0E0E0;
   }
 </style>

<script language="javascript">

 var cal1;
 function init() {
   cal1 = new YAHOO.widget.Calendar("cal1","cal1Container");
   
   /* Override the doCellMouseOver function (used for IE) to add row highlighting) */
   cal1.doCellMouseOver = function(e, cal) {
     var cell = this;
     var row = cell.parentNode;
     YAHOO.widget.Calendar_Core.prependCssClass(this, cal.Style.CSS_CELL_HOVER);
     YAHOO.widget.Calendar_Core.prependCssClass(row, "hilite-row");
   }
   /* Override the doCellMouseOut function (used for IE) to remove row highlighting) */
   cal1.doCellMouseOut = function(e, cal) {
     var cell = this;
     var row = cell.parentNode;
     YAHOO.widget.Calendar_Core.removeCssClass(this, cal.Style.CSS_CELL_HOVER);
     YAHOO.widget.Calendar_Core.removeCssClass(row, "hilite-row");
   }
   cal1.render();
 }

</script> </textarea>

       <a href="javascript:YAHOO.example.calendar.cal1.reset()" class="navLink" style="font-size:12px;text-decoration:underline">reset</a>|
       <a href="javascript:alert(YAHOO.example.calendar.cal1.getSelectedDates())" class="navLink" style="font-size:12px;text-decoration:underline">what"s selected?</a>

<script src="./docs/assets/dpSyntaxHighlighter.js"></script> <script language="javascript"> dp.SyntaxHighlighter.HighlightAll("code"); </script> </body> </html>


 </source>
   
  

<A href="http://www.wbex.ru/Code/JavaScriptDownload/yui.zip">yui.zip( 3,714 k)</a>


Calendar Control - Single-Select Implementation

   <source lang="html4strict">

<!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.01//EN" "http://www.w3.org/TR/html4/strict.dtd"> <html> <head>

 <title>Yahoo! Calendar Control - Single-Select Implementation</title>
 
 <link rel="stylesheet" href="./examples/calendar/css/examples.css" type="text/css">
 
 <script type="text/javascript" src="./build/yahoo/yahoo.js"></script>
 <script type="text/javascript" src="./build/event/event.js" ></script>
 <script type="text/javascript" src="./build/dom/dom.js" ></script>
 <link type="text/css" rel="stylesheet" href="./build/fonts/fonts.css">
 <link type="text/css" rel="stylesheet" href="./build/reset/reset.css">  
 <script type="text/javascript" src="./build/calendar/calendar.js"></script>
 <link type="text/css" rel="stylesheet" href="./build/calendar/assets/calendar.css">  
 <link rel="stylesheet" type="text/css" href="./docs/assets/dpSyntaxHighlighter.css" />
 
 <script language="javascript">
   YAHOO.namespace("example.calendar");
   function init() {
     YAHOO.example.calendar.cal1 = new YAHOO.widget.Calendar("YAHOO.example.calendar.cal1","cal1Container");
     YAHOO.example.calendar.cal1.render();
   }
   YAHOO.util.Event.addListener(window, "load", init);
 </script>

</head> <body>

Calendar Control

Default Single-Select Implementation

The default Calendar implementation is a single-select 1-up calendar view that defaults to the current month and year. The basic calendar can be implemented by declaring a variable to represent the calendar, and passing the calendar"s ID to the Calendar constructor:

<textarea name="code" class="JScript" cols="60" rows="1"> var cal1; function init() {

  cal1 = new YAHOO.widget.Calendar("cal1", "cal1Container");
  cal1.render();

} </textarea>

The Calendar object should be instantiated after the body has been rendered, so that a reference to the container element that will contain the calendar can be obtained. The container element can reside anywhere within the body.

<textarea name="code" class="HTML" cols="60" rows="1">

</textarea>

       <a href="javascript:YAHOO.example.calendar.cal1.reset()" class="navLink" style="font-size:12px;text-decoration:underline">reset</a>|
       <a href="javascript:alert(YAHOO.example.calendar.cal1.getSelectedDates())" class="navLink" style="font-size:12px;text-decoration:underline">what"s selected?</a>

<script src="./docs/assets/dpSyntaxHighlighter.js"></script> <script language="javascript"> dp.SyntaxHighlighter.HighlightAll("code"); </script> </body> </html>


 </source>
   
  

<A href="http://www.wbex.ru/Code/JavaScriptDownload/yui.zip">yui.zip( 3,714 k)</a>


Calendar: day info

   <source lang="html4strict">

<!DOCTYPE HTML PUBLIC "-//IETF//DTD HTML//EN">

<html> <head> <title>How to include additional info in day cells</title>

 <style rel="stylesheet" type="text/css" media="all" title="win2k-cold-1">

/* The main calendar widget. DIV containing a table. */ .calendar {

 position: relative;
 display: none;
 border-top: 2px solid #fff;
 border-right: 2px solid #000;
 border-bottom: 2px solid #000;
 border-left: 2px solid #fff;
 font-size: 11px;
 color: #000;
 cursor: default;
 background: #c8d0d4;
 font-family: tahoma,verdana,sans-serif;

} .calendar table {

 border-top: 1px solid #000;
 border-right: 1px solid #fff;
 border-bottom: 1px solid #fff;
 border-left: 1px solid #000;
 font-size: 11px;
 color: #000;
 cursor: default;
 background: #c8d0d4;
 font-family: tahoma,verdana,sans-serif;

} /* Header part -- contains navigation buttons and day names. */ .calendar .button { /* "<<", "<", ">", ">>" buttons have this class */

 text-align: center;
 padding: 1px;
 border-top: 1px solid #fff;
 border-right: 1px solid #000;
 border-bottom: 1px solid #000;
 border-left: 1px solid #fff;

} .calendar .nav {

 background: transparent url(menuarrow.gif) no-repeat 100% 100%;

} .calendar thead .title { /* This holds the current "month, year" */

 font-weight: bold;
 padding: 1px;
 border: 1px solid #000;
 background: #788084;
 color: #fff;
 text-align: center;

} .calendar thead .headrow { /* Row <TR> containing navigation buttons */ } .calendar thead .daynames { /* Row <TR> containing the day names */ } .calendar thead .name { /* Cells <TD> containing the day names */

 border-bottom: 1px solid #000;
 padding: 2px;
 text-align: center;
 background: #e8f0f4;

} .calendar thead .weekend { /* How a weekend day name shows in header */

 color: #f00;

} .calendar thead .hilite { /* How do the buttons in header appear when hover */

 border-top: 2px solid #fff;
 border-right: 2px solid #000;
 border-bottom: 2px solid #000;
 border-left: 2px solid #fff;
 padding: 0px;
 background-color: #d8e0e4;

} .calendar thead .active { /* Active (pressed) buttons in header */

 padding: 2px 0px 0px 2px;
 border-top: 1px solid #000;
 border-right: 1px solid #fff;
 border-bottom: 1px solid #fff;
 border-left: 1px solid #000;
 background-color: #b8c0c4;

} /* The body part -- contains all the days in month. */ .calendar tbody .day { /* Cells <TD> containing month days dates */

 width: 2em;
 text-align: right;
 padding: 2px 4px 2px 2px;

} .calendar tbody .day.othermonth {

 font-size: 80%;
 color: #aaa;

} .calendar tbody .day.othermonth.oweekend {

 color: #faa;

} .calendar table .wn {

 padding: 2px 3px 2px 2px;
 border-right: 1px solid #000;
 background: #e8f4f0;

} .calendar tbody .rowhilite td {

 background: #d8e4e0;

} .calendar tbody .rowhilite td.wn {

 background: #c8d4d0;

} .calendar tbody td.hilite { /* Hovered cells <TD> */

 padding: 1px 3px 1px 1px;
 border: 1px solid;
 border-color: #fff #000 #000 #fff;

} .calendar tbody td.active { /* Active (pressed) cells <TD> */

 padding: 2px 2px 0px 2px;
 border: 1px solid;
 border-color: #000 #fff #fff #000;

} .calendar tbody td.selected { /* Cell showing selected date */

 font-weight: bold;
 padding: 2px 2px 0px 2px;
 border: 1px solid;
 border-color: #000 #fff #fff #000;
 background: #d8e0e4;

} .calendar tbody td.weekend { /* Cells showing weekend days */

 color: #f00;

} .calendar tbody td.today { /* Cell showing today date */

 font-weight: bold;
 color: #00f;

} .calendar tbody .disabled { color: #999; } .calendar tbody .emptycell { /* Empty cells (the best is to hide them) */

 visibility: hidden;

} .calendar tbody .emptyrow { /* Empty row (some months need less than 6 rows) */

 display: none;

} /* The footer part -- status bar and "Close" button */ .calendar tfoot .footrow { /* The <TR> in footer (only one right now) */ } .calendar tfoot .ttip { /* Tooltip (status bar) cell <TD> */

 background: #e8f0f4;
 padding: 1px;
 border: 1px solid #000;
 background: #788084;
 color: #fff;
 text-align: center;

} .calendar tfoot .hilite { /* Hover style for buttons in footer */

 border-top: 1px solid #fff;
 border-right: 1px solid #000;
 border-bottom: 1px solid #000;
 border-left: 1px solid #fff;
 padding: 1px;
 background: #d8e0e4;

} .calendar tfoot .active { /* Active (pressed) style for buttons in footer */

 padding: 2px 0px 0px 2px;
 border-top: 1px solid #000;
 border-right: 1px solid #fff;
 border-bottom: 1px solid #fff;
 border-left: 1px solid #000;

} /* Combo boxes (menus that display months/years for direct selection) */ .calendar .rubo {

 position: absolute;
 display: none;
 width: 4em;
 top: 0px;
 left: 0px;
 cursor: default;
 border-top: 1px solid #fff;
 border-right: 1px solid #000;
 border-bottom: 1px solid #000;
 border-left: 1px solid #fff;
 background: #d8e0e4;
 font-size: 90%;
 padding: 1px;
 z-index: 100;

} .calendar .rubo .label, .calendar .rubo .label-IEfix {

 text-align: center;
 padding: 1px;

} .calendar .rubo .label-IEfix {

 width: 4em;

} .calendar .rubo .active {

 background: #c8d0d4;
 padding: 0px;
 border-top: 1px solid #000;
 border-right: 1px solid #fff;
 border-bottom: 1px solid #fff;
 border-left: 1px solid #000;

} .calendar .rubo .hilite {

 background: #048;
 color: #aef;

} .calendar td.time {

 border-top: 1px solid #000;
 padding: 1px 0px;
 text-align: center;
 background-color: #e8f0f4;

} .calendar td.time .hour, .calendar td.time .minute, .calendar td.time .ampm {

 padding: 0px 3px 0px 4px;
 border: 1px solid #889;
 font-weight: bold;
 background-color: #fff;

} .calendar td.time .ampm {

 text-align: center;

} .calendar td.time .colon {

 padding: 0px 2px 0px 3px;
 font-weight: bold;

} .calendar td.time span.hilite {

 border-color: #000;
 background-color: #667;
 color: #fff;

} .calendar td.time span.active {

 border-color: #f00;
 background-color: #000;
 color: #0f0;

}

 </style>
 
 <script type="text/javascript">

/* Copyright Mihai Bazon, 2002-2005 | www.bazon.net/mishoo

* -----------------------------------------------------------
*
* The DHTML Calendar, version 1.0 "It is happening again"
*
* Details and latest version at:
* www.dynarch.ru/projects/calendar
*
* This script is developed by Dynarch.ru.  Visit us at www.dynarch.ru.
*
* This script is distributed under the GNU Lesser General Public License.
* Read the entire license text here: http://www.gnu.org/licenses/lgpl.html
*/

// $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;
 // HTML elements
 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;
 // Information
 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;
   // 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;
 }

}; // ** constants /// "static", needed for event handlers. Calendar._C = null; /// detect a special case of "web browser" Calendar.is_ie = ( /msie/i.test(navigator.userAgent) &&

      !/opera/i.test(navigator.userAgent) );

Calendar.is_ie5 = ( Calendar.is_ie && /msie 5\.0/i.test(navigator.userAgent) ); /// detect Opera browser Calendar.is_opera = /opera/i.test(navigator.userAgent); /// detect KHTML-based browsers Calendar.is_khtml = /Konqueror|Safari|KHTML/i.test(navigator.userAgent); // 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;

}; // 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;

}; // END: UTILITY FUNCTIONS // 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";
 }

}; // 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);
 }

}; /**

*  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;
   // 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 <mihai_bazon@yahoo.ru> to get it into the distribution  ;-)\n\n" +
         "Thank you!\n" +
         "http://dynarch.ru/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 // BEGIN: CALENDAR OBJECT FUNCTIONS /**

*  This function creates the calendar inside the given parent.  If _par is
*  null than it creates a popup calendar inside the BODY element.  If _par is
*  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 = "
" + text + "
";
   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("×", 1, 200).ttip = Calendar._TT["CLOSE"];
 }
 row = Calendar.createElement("tr", thead);
 row.className = "headrow";
 this._nav_py = hh("«", 1, -2);
 this._nav_py.ttip = Calendar._TT["PREV_YEAR"];
 this._nav_pm = hh("‹", 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_nm = hh("›", 1, 1);
 this._nav_nm.ttip = Calendar._TT["NEXT_MONTH"];
 this._nav_ny = hh("»", 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"] || " ";
   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 = " ";
     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);

}; /** 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);

}; /**

*  (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 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 = " ";
         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";

}; 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);
 }

}; /**

*  Refreshes the calendar.  Useful if the "disabledHandler" function is
*  dynamic, meaning that the list of disabled date can change at runtime.
*  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);

}; /** Modifies the "firstDayOfWeek" parameter (pass 0 for Synday, 1 for Monday, etc.). */ Calendar.prototype.setFirstDayOfWeek = function (firstDayOfWeek) {

 this._init(firstDayOfWeek, this.date);
 this._displayWeekdays();

}; /**

*  Allows customization of what dates are enabled.  The "unaryFunction"
*  parameter must be a function object that receives the date (as a JS Date
*  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;

}; /** Customization of allowed year range for the calendar. */ 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));
 }

}; /** Calls the second user handler (closeHandler). */ 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;

}; /**

*  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);

}; // 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);
 }

}; /** 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();

}; /**

*  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();

}; /**

*  Shows the calendar at a given absolute position (beware that, depending on
*  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();

}; /** 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);
   }
   // 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
   }
   // 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();

}; /** Customizes the date format. */ Calendar.prototype.setDateFormat = function (str) {

 this.dateFormat = str;

}; /** Customizes the tooltip date format. */ 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";
     }
   }
 }

}; /** Internal function; it displays the bar with the names of the weekday. */ Calendar.prototype._displayWeekdays = function () {

 var fdow = this.firstDayOfWeek;
 var cell = this.firstdayname;
 var weekend = Calendar._TT["WEEKEND"];
 for (var i = 0; i < 7; ++i) {
   cell.className = "day name";
   var realday = (i + fdow) % 7;
   if (i) {
     cell.ttip = Calendar._TT["DAY_FIRST"].replace("%s", Calendar._DN[realday]);
     cell.navtype = 100;
     cell.calendar = this;
     cell.fdow = realday;
     Calendar._add_evs(cell);
   }
   if (weekend.indexOf(realday.toString()) != -1) {
     Calendar.addClass(cell, "weekend");
   }
   cell.innerHTML = Calendar._SDN[(i + fdow) % 7];
   cell = cell.nextSibling;
 }

}; /** Internal function. Hides all combo boxes that might be displayed. */ Calendar.prototype._hideCombos = function () {

 this.monthsCombo.style.display = "none";
 this.yearsCombo.style.display = "none";

}; /** Internal function. Starts dragging the element. */ Calendar.prototype._dragStart = function (ev) {

 if (this.dragging) {
   return;
 }
 this.dragging = true;
 var posX;
 var posY;
 if (Calendar.is_ie) {
   posY = window.event.clientY + document.body.scrollTop;
   posX = window.event.clientX + document.body.scrollLeft;
 } else {
   posY = ev.clientY + window.scrollY;
   posX = ev.clientX + window.scrollX;
 }
 var st = this.element.style;
 this.xOffs = posX - parseInt(st.left);
 this.yOffs = posY - parseInt(st.top);
 with (Calendar) {
   addEvent(document, "mousemove", calDragIt);
   addEvent(document, "mouseup", calDragEnd);
 }

}; // BEGIN: DATE OBJECT PATCHES /** Adds the number of days array to the Date object. */ Date._MD = new Array(31,28,31,30,31,30,31,31,30,31,30,31); /** Constants used for time computations */ Date.SECOND = 1000 /* milliseconds */; Date.MINUTE = 60 * Date.SECOND; Date.HOUR = 60 * Date.MINUTE; Date.DAY = 24 * Date.HOUR; Date.WEEK = 7 * Date.DAY; Date.parseDate = function(str, fmt) {

 var today = new Date();
 var y = 0;
 var m = -1;
 var d = 0;
 var a = str.split(/\W+/);
 var b = fmt.match(/%./g);
 var i = 0, j = 0;
 var hr = 0;
 var min = 0;
 for (i = 0; i < a.length; ++i) {
   if (!a[i])
     continue;
   switch (b[i]) {
       case "%d":
       case "%e":
     d = parseInt(a[i], 10);
     break;
       case "%m":
     m = parseInt(a[i], 10) - 1;
     break;
       case "%Y":
       case "%y":
     y = parseInt(a[i], 10);
     (y < 100) && (y += (y > 29) ? 1900 : 2000);
     break;
       case "%b":
       case "%B":
     for (j = 0; j < 12; ++j) {
       if (Calendar._MN[j].substr(0, a[i].length).toLowerCase() == a[i].toLowerCase()) { m = j; break; }
     }
     break;
       case "%H":
       case "%I":
       case "%k":
       case "%l":
     hr = parseInt(a[i], 10);
     break;
       case "%P":
       case "%p":
     if (/pm/i.test(a[i]) && hr < 12)
       hr += 12;
     else if (/am/i.test(a[i]) && hr >= 12)
       hr -= 12;
     break;
       case "%M":
     min = parseInt(a[i], 10);
     break;
   }
 }
 if (isNaN(y)) y = today.getFullYear();
 if (isNaN(m)) m = today.getMonth();
 if (isNaN(d)) d = today.getDate();
 if (isNaN(hr)) hr = today.getHours();
 if (isNaN(min)) min = today.getMinutes();
 if (y != 0 && m != -1 && d != 0)
   return new Date(y, m, d, hr, min, 0);
 y = 0; m = -1; d = 0;
 for (i = 0; i < a.length; ++i) {
   if (a[i].search(/[a-zA-Z]+/) != -1) {
     var t = -1;
     for (j = 0; j < 12; ++j) {
       if (Calendar._MN[j].substr(0, a[i].length).toLowerCase() == a[i].toLowerCase()) { t = j; break; }
     }
     if (t != -1) {
       if (m != -1) {
         d = m+1;
       }
       m = t;
     }
   } else if (parseInt(a[i], 10) <= 12 && m == -1) {
     m = a[i]-1;
   } else if (parseInt(a[i], 10) > 31 && y == 0) {
     y = parseInt(a[i], 10);
     (y < 100) && (y += (y > 29) ? 1900 : 2000);
   } else if (d == 0) {
     d = a[i];
   }
 }
 if (y == 0)
   y = today.getFullYear();
 if (m != -1 && d != 0)
   return new Date(y, m, d, hr, min, 0);
 return today;

}; /** Returns the number of days in the current month */ Date.prototype.getMonthDays = function(month) {

 var year = this.getFullYear();
 if (typeof month == "undefined") {
   month = this.getMonth();
 }
 if (((0 == (year%4)) && ( (0 != (year%100)) || (0 == (year%400)))) && month == 1) {
   return 29;
 } else {
   return Date._MD[month];
 }

}; /** Returns the number of day in the year. */ Date.prototype.getDayOfYear = function() {

 var now = new Date(this.getFullYear(), this.getMonth(), this.getDate(), 0, 0, 0);
 var then = new Date(this.getFullYear(), 0, 0, 0, 0, 0);
 var time = now - then;
 return Math.floor(time / Date.DAY);

}; /** Returns the number of the week in year, as defined in ISO 8601. */ Date.prototype.getWeekNumber = function() {

 var d = new Date(this.getFullYear(), this.getMonth(), this.getDate(), 0, 0, 0);
 var DoW = d.getDay();
 d.setDate(d.getDate() - (DoW + 6) % 7 + 3); // Nearest Thu
 var ms = d.valueOf(); // GMT
 d.setMonth(0);
 d.setDate(4); // Thu in Week 1
 return Math.round((ms - d.valueOf()) / (7 * 864e5)) + 1;

}; /** Checks date and time equality */ Date.prototype.equalsTo = function(date) {

 return ((this.getFullYear() == date.getFullYear()) &&
   (this.getMonth() == date.getMonth()) &&
   (this.getDate() == date.getDate()) &&
   (this.getHours() == date.getHours()) &&
   (this.getMinutes() == date.getMinutes()));

}; /** Set only the year, month, date parts (keep existing time) */ Date.prototype.setDateOnly = function(date) {

 var tmp = new Date(date);
 this.setDate(1);
 this.setFullYear(tmp.getFullYear());
 this.setMonth(tmp.getMonth());
 this.setDate(tmp.getDate());

}; /** Prints the date in a string according to the given format. */ Date.prototype.print = function (str) {

 var m = this.getMonth();
 var d = this.getDate();
 var y = this.getFullYear();
 var wn = this.getWeekNumber();
 var w = this.getDay();
 var s = {};
 var hr = this.getHours();
 var pm = (hr >= 12);
 var ir = (pm) ? (hr - 12) : hr;
 var dy = this.getDayOfYear();
 if (ir == 0)
   ir = 12;
 var min = this.getMinutes();
 var sec = this.getSeconds();
 s["%a"] = Calendar._SDN[w]; // abbreviated weekday name [FIXME: I18N]
 s["%A"] = Calendar._DN[w]; // full weekday name
 s["%b"] = Calendar._SMN[m]; // abbreviated month name [FIXME: I18N]
 s["%B"] = Calendar._MN[m]; // full month name
 // FIXME: %c : preferred date and time representation for the current locale
 s["%C"] = 1 + Math.floor(y / 100); // the century number
 s["%d"] = (d < 10) ? ("0" + d) : d; // the day of the month (range 01 to 31)
 s["%e"] = d; // the day of the month (range 1 to 31)
 // FIXME: %D : american date style: %m/%d/%y
 // FIXME: %E, %F, %G, %g, %h (man strftime)
 s["%H"] = (hr < 10) ? ("0" + hr) : hr; // hour, range 00 to 23 (24h format)
 s["%I"] = (ir < 10) ? ("0" + ir) : ir; // hour, range 01 to 12 (12h format)
 s["%j"] = (dy < 100) ? ((dy < 10) ? ("00" + dy) : ("0" + dy)) : dy; // day of the year (range 001 to 366)
 s["%k"] = hr;    // hour, range 0 to 23 (24h format)
 s["%l"] = ir;    // hour, range 1 to 12 (12h format)
 s["%m"] = (m < 9) ? ("0" + (1+m)) : (1+m); // month, range 01 to 12
 s["%M"] = (min < 10) ? ("0" + min) : min; // minute, range 00 to 59
 s["%n"] = "\n";    // a newline character
 s["%p"] = pm ? "PM" : "AM";
 s["%P"] = pm ? "pm" : "am";
 // FIXME: %r : the time in am/pm notation %I:%M:%S %p
 // FIXME: %R : the time in 24-hour notation %H:%M
 s["%s"] = Math.floor(this.getTime() / 1000);
 s["%S"] = (sec < 10) ? ("0" + sec) : sec; // seconds, range 00 to 59
 s["%t"] = "\t";    // a tab character
 // FIXME: %T : the time in 24-hour notation (%H:%M:%S)
 s["%U"] = s["%W"] = s["%V"] = (wn < 10) ? ("0" + wn) : wn;
 s["%u"] = w + 1;  // the day of the week (range 1 to 7, 1 = MON)
 s["%w"] = w;    // the day of the week (range 0 to 6, 0 = SUN)
 // FIXME: %x : preferred date representation for the current locale without the time
 // FIXME: %X : preferred time representation for the current locale without the date
 s["%y"] = ("" + y).substr(2, 2); // year without the century (range 00 to 99)
 s["%Y"] = y;    // year with the century
 s["%%"] = "%";    // a literal "%" character
 var re = /%./g;
 if (!Calendar.is_ie5 && !Calendar.is_khtml)
   return str.replace(re, function (par) { return s[par] || par; });
 var a = str.match(re);
 for (var i = 0; i < a.length; i++) {
   var tmp = s[a[i]];
   if (tmp) {
     re = new RegExp(a[i], "g");
     str = str.replace(re, tmp);
   }
 }
 return str;

}; Date.prototype.__msh_oldSetFullYear = Date.prototype.setFullYear; Date.prototype.setFullYear = function(y) {

 var d = new Date(this);
 d.__msh_oldSetFullYear(y);
 if (d.getMonth() != this.getMonth())
   this.setDate(28);
 this.__msh_oldSetFullYear(y);

}; // END: DATE OBJECT PATCHES

// global object that remembers the calendar window._dynarch_popupCalendar = null;

 </script>
 
 <script type="text/javascript">

// ** I18N // Calendar EN language // Author: Mihai Bazon, <mihai_bazon@yahoo.ru> // Encoding: any // Distributed under the same terms as the calendar itself. // For translators: please use UTF-8 if possible. We strongly believe that // Unicode is the answer to a real internationalized world. Also please // include your contact information in the header, as can be seen above. // full day names Calendar._DN = new Array ("Sunday",

"Monday",
"Tuesday",
"Wednesday",
"Thursday",
"Friday",
"Saturday",
"Sunday");

// Please note that the following array of short day names (and the same goes // for short month names, _SMN) isn"t absolutely necessary. We give it here // for exemplification on how one can customize the short day names, but if // they are simply the first N letters of the full name you can simply say: // // Calendar._SDN_len = N; // short day name length // Calendar._SMN_len = N; // short month name length // // If N = 3 then this is not needed either since we assume a value of 3 if not // present, to be compatible with translation files that were written before // this feature. // short day names Calendar._SDN = new Array ("Sun",

"Mon",
"Tue",
"Wed",
"Thu",
"Fri",
"Sat",
"Sun");

// First day of the week. "0" means display Sunday first, "1" means display // Monday first, etc. Calendar._FD = 0; // full month names Calendar._MN = new Array ("January",

"February",
"March",
"April",
"May",
"June",
"July",
"August",
"September",
"October",
"November",
"December");

// short month names Calendar._SMN = new Array ("Jan",

"Feb",
"Mar",
"Apr",
"May",
"Jun",
"Jul",
"Aug",
"Sep",
"Oct",
"Nov",
"Dec");

// tooltips Calendar._TT = {}; Calendar._TT["INFO"] = "About the calendar"; Calendar._TT["ABOUT"] = "DHTML Date/Time Selector\n" + "(c) dynarch.ru 2002-2005 / Author: Mihai Bazon\n" + // don"t translate this this ;-) "For latest version visit: http://www.dynarch.ru/projects/calendar/\n" + "Distributed under GNU LGPL. See http://gnu.org/licenses/lgpl.html for details." + "\n\n" + "Date selection:\n" + "- Use the \xab, \xbb buttons to select year\n" + "- Use the " + String.fromCharCode(0x2039) + ", " + String.fromCharCode(0x203a) + " buttons to select month\n" + "- Hold mouse button on any of the above buttons for faster selection."; Calendar._TT["ABOUT_TIME"] = "\n\n" + "Time selection:\n" + "- Click on any of the time parts to increase it\n" + "- or Shift-click to decrease it\n" + "- or click and drag for faster selection."; Calendar._TT["PREV_YEAR"] = "Prev. year (hold for menu)"; Calendar._TT["PREV_MONTH"] = "Prev. month (hold for menu)"; Calendar._TT["GO_TODAY"] = "Go Today"; Calendar._TT["NEXT_MONTH"] = "Next month (hold for menu)"; Calendar._TT["NEXT_YEAR"] = "Next year (hold for menu)"; Calendar._TT["SEL_DATE"] = "Select date"; Calendar._TT["DRAG_TO_MOVE"] = "Drag to move"; Calendar._TT["PART_TODAY"] = " (today)"; // the following is to inform that "%s" is to be the first day of week // %s will be replaced with the day name. Calendar._TT["DAY_FIRST"] = "Display %s first"; // This may be locale-dependent. It specifies the week-end days, as an array // of comma-separated numbers. The numbers are from 0 to 6: 0 means Sunday, 1 // means Monday, etc. Calendar._TT["WEEKEND"] = "0,6"; Calendar._TT["CLOSE"] = "Close"; Calendar._TT["TODAY"] = "Today"; Calendar._TT["TIME_PART"] = "(Shift-)Click or drag to change value"; // date formats Calendar._TT["DEF_DATE_FORMAT"] = "%Y-%m-%d"; Calendar._TT["TT_DATE_FORMAT"] = "%a, %b %e"; Calendar._TT["WK"] = "wk"; Calendar._TT["TIME"] = "Time:";

 </script>
 
 <script type="text/javascript">

/* Copyright Mihai Bazon, 2002, 2003 | http://dynarch.ru/mishoo/

* ---------------------------------------------------------------------------
*
* The DHTML Calendar
*
* Details and latest version at:
* http://dynarch.ru/mishoo/calendar.epl
*
* This script is distributed under the GNU Lesser General Public License.
* Read the entire license text here: http://www.gnu.org/licenses/lgpl.html
*
* This file defines helper functions for setting up the calendar.  They are
* intended to help non-programmers get a working calendar on their site
* quickly.  This script should not be seen as part of the calendar.  It just
* shows you what one can do with the calendar, while in the same time
* providing a quick and simple method for setting it up.  If you need
* exhaustive customization of the calendar creation process feel free to
* modify this code to suit your needs (this is recommended and much better
* than modifying calendar.js itself).
*/

// $Id: calendar-setup.js,v 1.25 2005/03/07 09:51:33 mishoo Exp $ /**

*  This function "patches" an input field (or other element) to use a calendar
*  widget for date selection.
*
*  The "params" is a single object that can have the following properties:
*
*    prop. name   | description
*  -------------------------------------------------------------------------------------------------
*   inputField    | the ID of an input field to store the date
*   displayArea   | the ID of a DIV or other element to show the date
*   button        | ID of a button or other element that will trigger the calendar
*   eventName     | event that will trigger the calendar, without the "on" prefix (default: "click")
*   ifFormat      | date format that will be stored in the input field
*   daFormat      | the date format that will be used to display the date in displayArea
*   singleClick   | (true/false) wether the calendar is in single click mode or not (default: true)
*   firstDay      | numeric: 0 to 6.  "0" means display Sunday first, "1" means display Monday first, etc.
*   align         | alignment (default: "Br"); if you don"t know what"s this see the calendar documentation
*   range         | array with 2 elements.  Default: [1900, 2999] -- the range of years available
*   weekNumbers   | (true/false) if it"s true (default) the calendar will display week numbers
*   flat          | null or element ID; if not null the calendar will be a flat calendar having the parent with the given ID
*   flatCallback  | function that receives a JS Date object and returns an URL to point the browser to (for flat calendar)
*   disableFunc   | function that receives a JS Date object and should return true if that date has to be disabled in the calendar
*   onSelect      | function that gets called when a date is selected.  You don"t _have_ to supply this (the default is generally okay)
*   onClose       | function that gets called when the calendar is closed.  [default]
*   onUpdate      | function that gets called after the date is updated in the input field.  Receives a reference to the calendar.
*   date          | the date that the calendar will be initially displayed to
*   showsTime     | default: false; if true the calendar will include a time selector
*   timeFormat    | the time format; can be "12" or "24", default is "12"
*   electric      | if true (default) then given fields/date areas are updated for each move; otherwise they"re updated only on close
*   step          | configures the step of the years in drop-down boxes; default: 2
*   position      | configures the calendar absolute position; default: null
*   cache         | if "true" (but default: "false") it will reuse the same calendar object, where possible
*   showOthers    | if "true" (but default: "false") it will show days from other months too
*
*  None of them is required, they all have default values.  However, if you
*  pass none of "inputField", "displayArea" or "button" you"ll get a warning
*  saying "nothing to setup".
*/

Calendar.setup = function (params) {

 function param_default(pname, def) { if (typeof params[pname] == "undefined") { params[pname] = def; } };
 param_default("inputField",     null);
 param_default("displayArea",    null);
 param_default("button",         null);
 param_default("eventName",      "click");
 param_default("ifFormat",       "%Y/%m/%d");
 param_default("daFormat",       "%Y/%m/%d");
 param_default("singleClick",    true);
 param_default("disableFunc",    null);
 param_default("dateStatusFunc", params["disableFunc"]);  // takes precedence if both are defined
 param_default("dateText",       null);
 param_default("firstDay",       null);
 param_default("align",          "Br");
 param_default("range",          [1900, 2999]);
 param_default("weekNumbers",    true);
 param_default("flat",           null);
 param_default("flatCallback",   null);
 param_default("onSelect",       null);
 param_default("onClose",        null);
 param_default("onUpdate",       null);
 param_default("date",           null);
 param_default("showsTime",      false);
 param_default("timeFormat",     "24");
 param_default("electric",       true);
 param_default("step",           2);
 param_default("position",       null);
 param_default("cache",          false);
 param_default("showOthers",     false);
 param_default("multiple",       null);
 var tmp = ["inputField", "displayArea", "button"];
 for (var i in tmp) {
   if (typeof params[tmp[i]] == "string") {
     params[tmp[i]] = document.getElementById(params[tmp[i]]);
   }
 }
 if (!(params.flat || params.multiple || params.inputField || params.displayArea || params.button)) {
   alert("Calendar.setup:\n  Nothing to setup (no fields found).  Please check your code");
   return false;
 }
 function onSelect(cal) {
   var p = cal.params;
   var update = (cal.dateClicked || p.electric);
   if (update && p.inputField) {
     p.inputField.value = cal.date.print(p.ifFormat);
     if (typeof p.inputField.onchange == "function")
       p.inputField.onchange();
   }
   if (update && p.displayArea)
     p.displayArea.innerHTML = cal.date.print(p.daFormat);
   if (update && typeof p.onUpdate == "function")
     p.onUpdate(cal);
   if (update && p.flat) {
     if (typeof p.flatCallback == "function")
       p.flatCallback(cal);
   }
   if (update && p.singleClick && cal.dateClicked)
     cal.callCloseHandler();
 };
 if (params.flat != null) {
   if (typeof params.flat == "string")
     params.flat = document.getElementById(params.flat);
   if (!params.flat) {
     alert("Calendar.setup:\n  Flat specified but can"t find parent.");
     return false;
   }
   var cal = new Calendar(params.firstDay, params.date, params.onSelect || onSelect);
   cal.showsOtherMonths = params.showOthers;
   cal.showsTime = params.showsTime;
   cal.time24 = (params.timeFormat == "24");
   cal.params = params;
   cal.weekNumbers = params.weekNumbers;
   cal.setRange(params.range[0], params.range[1]);
   cal.setDateStatusHandler(params.dateStatusFunc);
   cal.getDateText = params.dateText;
   if (params.ifFormat) {
     cal.setDateFormat(params.ifFormat);
   }
   if (params.inputField && typeof params.inputField.value == "string") {
     cal.parseDate(params.inputField.value);
   }
   cal.create(params.flat);
   cal.show();
   return false;
 }
 var triggerEl = params.button || params.displayArea || params.inputField;
 triggerEl["on" + params.eventName] = function() {
   var dateEl = params.inputField || params.displayArea;
   var dateFmt = params.inputField ? params.ifFormat : params.daFormat;
   var mustCreate = false;
   var cal = window.calendar;
   if (dateEl)
     params.date = Date.parseDate(dateEl.value || dateEl.innerHTML, dateFmt);
   if (!(cal && params.cache)) {
     window.calendar = cal = new Calendar(params.firstDay,
                  params.date,
                  params.onSelect || onSelect,
                  params.onClose || function(cal) { cal.hide(); });
     cal.showsTime = params.showsTime;
     cal.time24 = (params.timeFormat == "24");
     cal.weekNumbers = params.weekNumbers;
     mustCreate = true;
   } else {
     if (params.date)
       cal.setDate(params.date);
     cal.hide();
   }
   if (params.multiple) {
     cal.multiple = {};
     for (var i = params.multiple.length; --i >= 0;) {
       var d = params.multiple[i];
       var ds = d.print("%Y%m%d");
       cal.multiple[ds] = d;
     }
   }
   cal.showsOtherMonths = params.showOthers;
   cal.yearStep = params.step;
   cal.setRange(params.range[0], params.range[1]);
   cal.params = params;
   cal.setDateStatusHandler(params.dateStatusFunc);
   cal.getDateText = params.dateText;
   cal.setDateFormat(dateFmt);
   if (mustCreate)
     cal.create();
   cal.refresh();
   if (!params.position)
     cal.showAtElement(params.button || params.displayArea || params.inputField, params.align);
   else
     cal.showAt(params.position[0], params.position[1]);
   return false;
 };
 return cal;

};

 </script>

<script type="text/javascript">

 // define info for dates in this table:
 var dateInfo = {
   "20050308" : "Mishoo"s birthday",
   "20050310" : "foo",
   "20050315" : "bar",
   "20050318" : "25$",
   "20050324" : "60$"
 };

</script> <style type="text/css">

 @import url(calendar-win2k-1.css);
 .calendar .inf { font-size: 80%; color: #444; }
 .calendar .wn { font-weight: bold; vertical-align: top; }

</style> </head> <body>

How to include additional info in day cells

<script type="text/javascript">

 function getDateText(date, d) {
   var inf = dateInfo[date.print("%Y%m%d")];
   if (!inf) {
return d + "
 
";
   } else {
return d + "
" + inf + "
";
   }
 };
 function flatCallback(cal) {
   if (cal.dateClicked) {
     // do something here
     window.status = "Selected: " + cal.date;
     var inf = dateInfo[cal.date.print("%Y%m%d")];
     if (inf) {
       window.status += ".  Additional info: " + inf;
     }
   }
 };
 Calendar.setup({
    flat: "flatcal",
    dateText: getDateText,
    flatCallback: flatCallback
 });

</script>

The idea is simple:

  1. Define a callback that takes two parameters like this:

    function getDateText(date, d)

    This function will receive the date object as the first parameter and the current date number (1..31) as the second (you can get it as well by calling date.getDate() but since it"s very probably useful I thought I"d pass it too so that we can avoid a function call).

    This function must return the text to be inserted in the cell of the passed date. That is, one should at least "return d;".

  2. Pass the above function as the "dateText" parameter to Calendar.setup.

The function could simply look like:

  
  function getDateText(date, d) {
    if (d == 12) {
      return "12th";
    } else if (d == 13) {
      return "bad luck";
    } /* ... etc ... */
  }

but it"s easy to imagine that this approach sucks. For a better way, see the source of this page and note the usage of an externally defined "dateText" object which maps "date" to "date info", also taking into account the year and month. This object can be easily generated from a database, and the getDateText function becomes extremely simple (and static).

Cheers!


<address><a href="http://dynarch.ru/mishoo/">mishoo</a></address>

Last modified: Sat Mar  5 17:18:06 EET 2005 

</body> </html>


 </source>
   
  

<A href="http://www.wbex.ru/Code/JavaScriptDownload/jscalendar-1.0.zip">jscalendar-1.0.zip( 396 k)</a>


Calendar (IE only)

   <source lang="html4strict">


<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Strict//EN"

       "http://www.w3.org/TR/xhtml1/DTD/xhtml1-strict.dtd">

<html> <head> <title>JavaScript Date Picker</title> <style rel="stylesheet" id="mainStyle" type="text/css" > html {background-color:#cccccc} body {background-color:#eeeeee; font-family:Tahoma,Arial,Helvetica,sans-serif; font-size:12px;

   margin-left:15%; margin-right:15%; border:3px groove darkred; padding:15px}

h1 {text-align:right; font-size:1.5em; font-weight:bold} h2 {text-align:left; font-size:1.1em; font-weight:bold; text-decoration:underline} .buttons {margin-top:10px} </style> <style type="text/css">

  1. calendar {position:absolute;
          left:0px; 
          top:0px; 
          visibility:hidden
         }

table {font-family:Verdana, Arial, Helvetica, sans-serif;

      background-color:#999999
     }

th {background-color:#ccffcc;

   text-align:center; 
   font-size:10px; 
   width:26px
  }
  1. tableHeader {background-color:#ffcccc;
             width:100%
            }

td {background-color:#ffffcc;

   text-align:center; 
   font-size:10px
  }
  1. tableBody tr td {width:26px}
  2. today {background-color:#ffcc33}

a:link {color:#000000; text-decoration:none} a:active {color:#000000; text-decoration:none} a:visited {color:#000000; text-decoration:none} a:hover {color:#990033; text-decoration:underline} </style> <script type="text/javascript"> /* *********************************************************** Example 4-3 (DHTMLAPI.js) "Dynamic HTML:The Definitive Reference" 2nd Edition by Danny Goodman Published by O"Reilly & Associates ISBN 1-56592-494-0 http://www.oreilly.ru Copyright 2002 Danny Goodman. All Rights Reserved.

                                                                                                                        • */

// DHTMLapi.js custom API for cross-platform // object positioning by Danny Goodman (http://www.dannyg.ru). // Release 2.0. Supports NN4, IE, and W3C DOMs. // Global variables var isCSS, isW3C, isIE4, isNN4, isIE6CSS; // Initialize upon load to let all browsers establish content objects function initDHTMLAPI() {

   if (document.images) {
       isCSS = (document.body && document.body.style) ? true : false;
       isW3C = (isCSS && document.getElementById) ? true : false;
       isIE4 = (isCSS && document.all) ? true : false;
       isNN4 = (document.layers) ? true : false;
       isIE6CSS = (document.rupatMode && document.rupatMode.indexOf("CSS1") >= 0) ? true : false;
   }

} // Set event handler to initialize API window.onload = initDHTMLAPI; // Seek nested NN4 layer from string name function seekLayer(doc, name) {

   var theObj;
   for (var i = 0; i < doc.layers.length; i++) {
       if (doc.layers[i].name == name) {
           theObj = doc.layers[i];
           break;
       }
       // dive into nested layers if necessary
       if (doc.layers[i].document.layers.length > 0) {
           theObj = seekLayer(document.layers[i].document, name);
       }
   }
   return theObj;

} // Convert object name string or object reference // into a valid element object reference function getRawObject(obj) {

   var theObj;
   if (typeof obj == "string") {
       if (isW3C) {
           theObj = document.getElementById(obj);
       } else if (isIE4) {
           theObj = document.all(obj);
       } else if (isNN4) {
           theObj = seekLayer(document, obj);
       }
   } else {
       // pass through object reference
       theObj = obj;
   }
   return theObj;

} // Convert object name string or object reference // into a valid style (or NN4 layer) reference function getObject(obj) {

   var theObj = getRawObject(obj);
   if (theObj && isCSS) {
       theObj = theObj.style;
   }
   return theObj;

} // Position an object at a specific pixel coordinate function shiftTo(obj, x, y) {

   var theObj = getObject(obj);
   if (theObj) {
       if (isCSS) {
           // equalize incorrect numeric value type
           var units = (typeof theObj.left == "string") ? "px" : 0 
           theObj.left = x + units;
           theObj.top = y + units;
       } else if (isNN4) {
           theObj.moveTo(x,y)
       }
   }

} // Move an object by x and/or y pixels function shiftBy(obj, deltaX, deltaY) {

   var theObj = getObject(obj);
   if (theObj) {
       if (isCSS) {
           // equalize incorrect numeric value type
           var units = (typeof theObj.left == "string") ? "px" : 0 
           theObj.left = getObjectLeft(obj) + deltaX + units;
           theObj.top = getObjectTop(obj) + deltaY + units;
       } else if (isNN4) {
           theObj.moveBy(deltaX, deltaY);
       }
   }

} // Set the z-order of an object function setZIndex(obj, zOrder) {

   var theObj = getObject(obj);
   if (theObj) {
       theObj.zIndex = zOrder;
   }

} // Set the background color of an object function setBGColor(obj, color) {

   var theObj = getObject(obj);
   if (theObj) {
       if (isNN4) {
           theObj.bgColor = color;
       } else if (isCSS) {
           theObj.backgroundColor = color;
       }
   }

} // Set the visibility of an object to visible function show(obj) {

   var theObj = getObject(obj);
   if (theObj) {
       theObj.visibility = "visible";
   }

} // Set the visibility of an object to hidden function hide(obj) {

   var theObj = getObject(obj);
   if (theObj) {
       theObj.visibility = "hidden";
   }

} // Retrieve the x coordinate of a positionable object function getObjectLeft(obj) {

   var elem = getRawObject(obj);
   var result = 0;
   if (document.defaultView) {
       var style = document.defaultView;
       var cssDecl = style.getComputedStyle(elem, "");
       result = cssDecl.getPropertyValue("left");
   } else if (elem.currentStyle) {
       result = elem.currentStyle.left;
   } else if (elem.style) {
       result = elem.style.left;
   } else if (isNN4) {
       result = elem.left;
   }
   return parseInt(result);

} // Retrieve the y coordinate of a positionable object function getObjectTop(obj) {

   var elem = getRawObject(obj);
   var result = 0;
   if (document.defaultView) {
       var style = document.defaultView;
       var cssDecl = style.getComputedStyle(elem, "");
       result = cssDecl.getPropertyValue("top");
   } else if (elem.currentStyle) {
       result = elem.currentStyle.top;
   } else if (elem.style) {
       result = elem.style.top;
   } else if (isNN4) {
       result = elem.top;
   }
   return parseInt(result);

} // Retrieve the rendered width of an element function getObjectWidth(obj) {

   var elem = getRawObject(obj);
   var result = 0;
   if (elem.offsetWidth) {
       result = elem.offsetWidth;
   } else if (elem.clip && elem.clip.width) {
       result = elem.clip.width;
   } else if (elem.style && elem.style.pixelWidth) {
       result = elem.style.pixelWidth;
   }
   return parseInt(result);

} // Retrieve the rendered height of an element function getObjectHeight(obj) {

   var elem = getRawObject(obj);
   var result = 0;
   if (elem.offsetHeight) {
       result = elem.offsetHeight;
   } else if (elem.clip && elem.clip.height) {
       result = elem.clip.height;
   } else if (elem.style && elem.style.pixelHeight) {
       result = elem.style.pixelHeight;
   }
   return parseInt(result);

} // Return the available content width space in browser window function getInsideWindowWidth() {

   if (window.innerWidth) {
       return window.innerWidth;
   } else if (isIE6CSS) {
       // measure the html element"s clientWidth
       return document.body.parentElement.clientWidth
   } else if (document.body && document.body.clientWidth) {
       return document.body.clientWidth;
   }
   return 0;

} // Return the available content height space in browser window function getInsideWindowHeight() {

   if (window.innerHeight) {
       return window.innerHeight;
   } else if (isIE6CSS) {
       // measure the html element"s clientHeight
       return document.body.parentElement.clientHeight
   } else if (document.body && document.body.clientHeight) {
       return document.body.clientHeight;
   }
   return 0;

}

</script> <script type="text/javascript"> /*******************

 UTILITY FUNCTIONS
                                        • /

// day of week of month"s first day function getFirstDay(theYear, theMonth){

   var firstDate = new Date(theYear,theMonth,1);
   return firstDate.getDay();

} // number of days in the month function getMonthLen(theYear, theMonth) {

   var nextMonth = new Date(theYear, theMonth + 1, 1);
   nextMonth.setHours(nextMonth.getHours() - 3);
   return nextMonth.getDate();

} function getElementPosition(elemID) {

 var offsetTrail = document.getElementById(elemID);
   var offsetLeft = 0;
   var offsetTop = 0;
   while (offsetTrail) {
       offsetLeft += offsetTrail.offsetLeft;
       offsetTop += offsetTrail.offsetTop;
       offsetTrail = offsetTrail.offsetParent;
   }
   if (navigator.userAgent.indexOf("Mac") != -1 && 
       typeof document.body.leftMargin != "undefined") {
       offsetLeft += document.body.leftMargin;
       offsetTop += document.body.topMargin;
   }
   return {left:offsetLeft, top:offsetTop};

} // position and show calendar function showCalendar(evt) {

   evt = (evt) ? evt : event;
   if (evt) {
     if (document.getElementById("calendar").style.visibility != "visible") {
         var elem = (evt.target) ? evt.target : evt.srcElement;
         var position = getElementPosition(elem.id);
           shiftTo("calendar", position.left + elem.offsetWidth, position.top);
           show("calendar");
       } else {
           hide("calendar");
       }
   }

} /************************

 DRAW CALENDAR CONTENTS
                                                  • /

// clear and re-populate table based on form"s selections function populateTable(form) {

   // pick up date form choices
   var theMonth = form.chooseMonth.selectedIndex;
   var theYear = parseInt(form.chooseYear.options[form.chooseYear.selectedIndex].text);
   // initialize date-dependent variables
   var firstDay = getFirstDay(theYear, theMonth);
   var howMany = getMonthLen(theYear, theMonth);
   var today = new Date();
   
   // fill in month/year in table header
   document.getElementById("tableHeader").innerHTML = 
       form.chooseMonth.options[theMonth].text + " " + theYear;
   
   // initialize vars for table creation
   var dayCounter = 1;
   var TBody = document.getElementById("tableBody");
   // clear any existing rows
   while (TBody.rows.length > 0) {
       TBody.deleteRow(0);
   }
   var newR, newC, dateNum;
   var done=false;
   while (!done) {
       // create new row at end
       newR = TBody.insertRow(TBody.rows.length);
       if (newR) {
           for (var i = 0; i < 7; i++) {
               // create new cell at end of row
               newC = newR.insertCell(newR.cells.length);
               if (TBody.rows.length == 1 && i < firstDay) {
                   // empty boxes before first day
                   newC.innerHTML = " ";
                   continue;
               }
               if (dayCounter == howMany) {
                   // no more rows after this one
                   done = true;
               }
               // plug in link/date (or empty for boxes after last day)
               if (dayCounter <= howMany) {
                   if (today.getFullYear() == theYear &&
                       today.getMonth() == form.chooseMonth.selectedIndex &&
                       today.getDate() == dayCounter) {
                       newC.id = "today";
                   }
                   newC.innerHTML = "<a href="#"onclick="chooseDate(" +
                       dayCounter + "," + theMonth + "," + theYear + 
                       "); return false;">" + dayCounter + "</a>";
                    dayCounter++;
              } else {
                   newC.innerHTML = " ";
               }
           }
       } else {
           done = true;
       }
   }

} /*******************

 INITIALIZATIONS
                                        • /

// create dynamic list of year choices function fillYears() {

   var today = new Date();
   var thisYear = today.getFullYear();
   var yearChooser = document.dateChooser.chooseYear;
   for (i = thisYear; i < thisYear + 5; i++) {
       yearChooser.options[yearChooser.options.length] = new Option(i, i);
   }
   setCurrMonth(today);

} // set month choice to current month function setCurrMonth(today) {

   document.dateChooser.chooseMonth.selectedIndex = today.getMonth();

} /*******************

  PROCESS CHOICE
                                        • /

function chooseDate(date, month, year) {

   document.mainForm.date.value = date;
   document.mainForm.month.value = month + 1;
   document.mainForm.year.value = year;
   hide("calendar");

} </script> </head> <body onload="fillYears(); populateTable(document.dateChooser); initDHTMLAPI()">

Date Picker


<form name="mainForm" id="mainForm" method="POST" action="">

Enter a date:

mm:<input type="text" name="month" id="month" size="3" maxlength="2" value="1"> dd:<input type="text" name="date" id="date" size="3" maxlength="2" value="1"> yyyy:<input type="text" name="year" id="year" size="5" maxlength="4" value="2003"> <input type="button" id="showit" value="Pick Date >>" onclick="showCalendar(event)">

</form>

<tbody id="tableBody"></tbody>

SunMonTueWed ThuFriSat

<form name="dateChooser"> <select name="chooseMonth" onchange="populateTable(this.form)"> <option selected>January<option>February <option>March<option>April<option>May <option>June<option>July<option>August <option>September<option>October <option>November<option>December </select> <select name="chooseYear" onchange="populateTable(this.form)"> </select> </form>

</body> </html>


 </source>
   
  


Calendar in slide tab

   <source lang="html4strict">

<html><head><title>DHTML Calendar</title>

<meta name="author" content="Eric Pretorious"> <meta name="subject" content="DHTML Calendar"> <meta name="keywords" content="DHTML, dynamic HTML, crossbrowser, cross-browser, cross browser, javascript, calendar script">

<style rel="stylesheet" type="text/css">

  1. banner {
 position:absolute;
 top:0px;left:0px;
 width:740px;height:110px;
 padding:10px;margin:10px;
 border-bottom:1px solid gray;

}

  1. buttons {
 position:absolute;
 z-index:0;
 top:141px;left:10px;

} .button {

 position:relative;
 width:140px;
 background:#ccffcc;
 border:1px solid #99ff99;
 padding:9px;margin:10px;
 font-family:sans-serif;font-size:10px;

} .badge {

 position:relative;
 width:140px;
 background:transparent;
 padding:10px;margin:10px;
 text-align:center;

} .badge a img {

 border:1px solid white;

}

  1. cover {
 position:absolute;
 z-index:2;
 top:141px;left:191px;
 width:570px;height:450px;
 background:#ccccff;
 border:1px solid #ff9999;
 padding:0;margin:10 8 10 0;
 font-family:sans-serif;font-size:10px;

}

  1. page {
 position:absolute;
 z-index:1;
 top:141px;left:191px;
 width:570px;height:450px;
 background:#ccccff;
 border:1px solid #9999ff;
 padding:0;margin:10 8 10 0;
 font-family:sans-serif;font-size:10px;

} .container {

 position:absolute;
 width:550px;
 background:transparent;
 border-bottom:1px solid gray;
 padding-bottom:10px;margin:10px;

} .container .title {

 font-weight:600;
 font-size:11px;
 padding:0;margin:0;

} .container .content {

 font-weight:400;
 font-size:10px;
 line-height:18px;

} .code_ref {

 position:relative;
 display:block;
 border:1px solid #9999ff;
 background:white;
 padding:10px;
 margin:5 0 5 0;

} </style>

<style rel="stylesheet" type="text/css">

  1. DHTMLC {
 position:relative;
 margin:0 0 10 10;
 height:180px;width:230px;
 visibility:hidden;
 font-family:verdana, arial, sans-serif;font-size:10px;
 line-height:18px;
 background-color:white;border:1px solid #9999ff;

} .months {

 position:absolute;
 height :18px;width:45px;
 text-align:center;background-color:#ccccff;

} .dotw {

 position:absolute;
 height :18px;width:28px;
 text-align:center;background-color:#ccccff;

} .days {

 position:absolute;
 height :18px;width:28px;
 text-align:center;background-color:white;

} .days a:link {

 text-decoration:none;

}

  1. moniker {
 height:18px;width:210px;
 text-align:center;color:#ccc;
 font-family:verdana, arial, sans-serif;font-size:7px;
 line-height:9px;

}

  1. moniker a:link {
 color:gray;

} </style>

<script type="text/javascript" > /* cbe_core.js $Revision: 0.22 $

* CBE v4.19, Cross-Browser DHTML API from Cross-Browser.ru
* Copyright (c) 2002 Michael Foster (mike@cross-browser.ru)
* Distributed under the terms of the GNU LGPL from gnu.org
  • /

var cbeVersion="4.19", cbeDocumentId="idDocument", cbeWindowId="idWindow", cbeAll=new Array(); window.onload=function(){cbeInitialize("DIV", "SPAN"); if (window.windowOnload) window.windowOnload();} window.onunload=function(){if(window.windowOnunload){window.windowOnunload();}if(window.cbeDebugObj){window.cbeDebugObj=null;}for(var i=0; i<cbeAll.length; i++){if(cbeAll[i]){if(cbeAll[i].ele){if(cbeAll[i].ele.cbe){cbeAll[i].ele.cbe=null;}cbeAll[i].ele=null;}cbeAll[i]=null;}}} function CrossBrowserNode(){this.parentNode=null; this.childNodes=0; this.firstChild=null; this.lastChild=null; this.previousSibling=null; this.nextSibling=null;} CrossBrowserNode.prototype.appendNode=function(cbeChild){if (cbeChild){if (!this.firstChild){this.firstChild=cbeChild;} else{cbeChild.previousSibling=this.lastChild; this.lastChild.nextSibling=cbeChild;}cbeChild.parentNode=this; this.lastChild=cbeChild; ++this.childNodes;}return cbeChild;} CrossBrowserElement.prototype=new CrossBrowserNode; function CrossBrowserElement(){

 this.contains=this.left=this.top=this.offsetLeft=this.offsetTop=this.pageX=this.pageY=this.zIndex=_retZero;
 this.show=this.hide=this.moveTo=this.moveBy=this.sizeTo=this.sizeBy=this.resizeTo=this.resizeBy=_retVoid;
 this.visibility=this.color=this.background=this.clip=this.innerHtml=_retEStr;
 if (cbeAll.length < 2){this.width=cbeInnerWidth; this.height=cbeInnerHeight; this.scrollLeft=cbePageXOffset; this.scrollTop=cbePageYOffset;}
 else{this.width=this.height=this.scrollLeft=this.scrollTop=_retZero;}
 this.id=""; this.index=cbeAll.length; cbeAll[this.index]=this; this.w=this.h=0; this.x=this.y=0;
 if (window.cbeEventJsLoaded) this.listeners=new Array();

} function cbeBindElement(cbe, ele){

 if (!cbe || !ele) return;
 cbe.ele=ele; cbe.ele.cbe=cbe; cbe.parentElement=cbeGetParentElement(ele);
 if (ele==window){cbe.id=ele.id=cbeWindowId; return;} else if (ele==document){cbe.id=ele.id=cbeDocumentId; return;} else{cbe.id=ele.id;}
 if (_def(ele.clip)){cbe.w=ele.clip.width; cbe.h=ele.clip.height;}
 var css=_def(ele.style);
 // left, top
 cbe.moveTo=_cbeMoveTo; cbe.moveBy=_cbeMoveBy; if (css && _def(ele.style.left, ele.style.top) && typeof(ele.style.left)=="string"){cbe.left=_domLeft; cbe.top=_domTop;}else if (css && _def(ele.style.pixelLeft, ele.style.pixelTop)){cbe.left=_ieLeft; cbe.top=_ieTop;}else if (_def(ele.left, ele.top)){cbe.left=_nnLeft; cbe.top=_nnTop;}else{_sup(false,"left","top","moveTo","moveBy");}
 // width, height
 cbe.sizeTo=_cbeSizeTo; cbe.sizeBy=_cbeSizeBy; cbe.resizeTo=_cbeResizeTo; cbe.resizeBy=_cbeResizeBy; if (css && _def(ele.style.width, ele.style.height, ele.offsetWidth, ele.offsetHeight) && typeof(ele.style.width)=="string"){cbe.width=_domWidth; cbe.height=_domHeight;}else if (css && _def(ele.style.pixelWidth, ele.style.pixelHeight)){cbe.width=_ieWidth; cbe.height=_ieHeight;}else if (_def(ele.clip) && _def(ele.clip.width, ele.clip.height)){cbe.width=_nnWidth; cbe.height=_nnHeight;}else{_sup(false, "width","height","sizeTo","sizeBy","resizeTo","resizeBy");}
 // zIndex
 if (css && _def(ele.style.zIndex)){cbe.zIndex=_domZIndex;} else if (_def(ele.zIndex)){cbe.zIndex=_nnZIndex;} else{_sup(false,"zIndex");}
 // visibility
 cbe.show=_cbeShow; cbe.hide=_cbeHide; if (css && _def(ele.style.visibility)){cbe.visibility=_domVisibility;} else if (_def(ele.visibility)){cbe.visibility=_nnVisibility;} else{_sup(false,"visibility","show","hide");}
 // background
 if (css && _def(ele.style.backgroundColor, ele.style.backgroundImage)){cbe.background=_domBackground;} else if (_def(ele.bgColor, ele.background)){cbe.background=_nnBackground;} else{_sup(false,"background");}
 // color
 if (css && _def(ele.style.color)){cbe.color=_domColor;} else{_sup(false,"color");}
 // clip
 if (css && _def(ele.style.clip)){cbe.clip=_domClip;} else if (_def(ele.clip)){cbe.clip=_nnClip;} else{_sup(false,"clip");}
 // offsetLeft, offsetTop
 if (_def(ele.offsetLeft, ele.offsetTop, ele.offsetParent)){cbe.offsetLeft=_ieOffsetLeft; cbe.offsetTop=_ieOffsetTop;}else if (_def(ele.pageX, ele.pageY)){cbe.offsetLeft=_nnOffsetLeft; cbe.offsetTop=_nnOffsetTop;}else{_sup(false,"offsetLeft","offsetTop");}
 // pageX, pageY
 cbe.contains=_cbeContains; if (_def(ele.pageX, ele.pageY)){cbe.pageX=_nnPageX; cbe.pageY=_nnPageY;}else if (document.cbe.isSupported("offsetLeft")){cbe.pageX=_cbePageX; cbe.pageY=_cbePageY;}else{_sup(false,"pageX","pageY","contains");}
 // innerHtml
 if (_def(ele.innerHTML)){cbe.innerHtml=_ieInnerHtml;} else if (_def(ele.document) && _def(ele.document.write)){cbe.innerHtml=_nnInnerHtml;} else{_sup(false,"innerHtml");}
 // scrollLeft, scrollTop
 if (_def(ele.scrollLeft, ele.scrollTop)){cbe.scrollLeft=_cbeScrollLeft; cbe.scrollTop=_cbeScrollTop;}else{_sup(false,"scrollLeft","scrollTop");}
 // createElement, appendChild, removeChild (these need more work)
 if (!_def(document.createElement) && !document.layers){_sup(false,"createElement","appendChild","removeChild");}else{if (!_def(ele.appendChild)){_sup(false,"appendChild");} if (!_def(ele.removeChild)){_sup(false,"removeChild");}}

} function cbeInitialize(sTagNames){

 var t,i,ele,eleList,cbe;
 cbe=new CrossBrowserElement(window);
 cbeBindElement(cbe, window);
 cbe=new CrossBrowserElement(document);
 cbeBindElement(cbe, document);
 if (!document.getElementById) document.getElementById=cbeGetElementById;
 if (document.createElement || document.layers) document.cbe.createElement=_cbeCreateElement;
 document.cbe.isSupported=_cbeIsSupported;
 document.cbe.supported=new Array();
 _sup(true,"left","top","width","height","zIndex","show","hide","visibility","background","color","clip","offsetLeft","offsetTop","pageX","pageY","innerHtml","scrollLeft","scrollTop","createElement","appendChild","removeChild","moveTo","moveBy","sizeTo","sizeBy","resizeTo","resizeBy","contains");
 for (t=0; t < arguments.length; ++t){
   eleList=cbeGetElementsByTagName(arguments[t]);
   for (i=0; i < eleList.length; ++i){
     ele=eleList[i];
     if ( ele.id && ele.id !=""){
       cbe=new CrossBrowserElement();
       cbeBindElement(cbe, ele);
    }
  }
   if (document.layers) break;
}
 _cbeCreateTree();
 if (window.cbeEventJsLoaded && (document.layers || is.opera5or6)){window.cbe.addEventListener("resize", cbeDefaultResizeListener);}

} function _cbeIsSupported(sMethods){var i; for (i=0; i<arguments.length; ++i){if (!document.cbe.supported[arguments[i]]) return false;}return true;} function _sup(bValue, sMethods){var i; for (i=1; i<arguments.length; ++i) document.cbe.supported[arguments[i]]=bValue;} function _cbeCreateTree(){var parent; for (var i=1; i < cbeAll.length; ++i){parent=cbeAll[i].parentElement; if (!parent.cbe){while (parent && !parent.cbe){parent=cbeGetParentElement(parent);}if (!parent) parent=document;}parent.cbe.appendNode(cbeAll[i]);}} function cbeGetElementById(sId){var ele=null; if (sId==window.cbeWindowId) ele=window; else if (sId==window.cbeDocumentId) ele=document; else if (is.dom1getbyid) ele=document.getElementById(sId); else if (document.all) ele=document.all[sId]; else if (document.layers) ele=nnGetElementById(sId); if (!ele && window.cbeUtilJsLoaded){ele=cbeGetImageByName(sId); if (!ele){ele=cbeGetFormByName(sId);}} return ele;} function nnGetElementById(sId){for (var i=0; i < cbeAll.length; i++){if ( cbeAll[i].id==sId ) return cbeAll[i].ele;}return null;} function cbeGetElementsByTagName(sTagName){

 var eleList;
 if (document.getElementsByTagName) eleList=document.getElementsByTagName(sTagName); // standard
 else if (document.body && document.body.getElementsByTagName) eleList=document.body.getElementsByTagName(sTagName); // opera5or6
 else if (document.all && document.all.tags) eleList=document.all.tags(sTagName); // ie4
 else if (document.layers){eleList=new Array(); nnGetAllLayers(window, eleList, 0);}// nn4
 return eleList;

} function nnGetAllLayers(parent, layerArray, nextIndex){

 var i, layer;
 for (i=0; i < parent.document.layers.length; i++){
   layer=parent.document.layers[i]; layerArray[nextIndex++]=layer;
   if (layer.document.layers.length) nextIndex=nnGetAllLayers(layer, layerArray, nextIndex);
}
 return nextIndex;

} function cbeGetParentElement(child){

 var parent=document;
 if (child==window) parent=null;
 else if (child==document) parent=window;
 else if (child.parentLayer){if (child.parentLayer !=window) parent=child.parentLayer;}
 else{
   if (child.parentNode) parent=child.parentNode;
   else if (child.offsetParent) parent=child.offsetParent;
   else if (child.parentElement) parent=child.parentElement;
}
 return parent;

} function _def(){var i; for (i=0; i<arguments.length; ++i){if (typeof(arguments[i])=="" || typeof(arguments[i])=="undefined") return false;}return true;} function _retZero(){return 0;} function _retNull(){return null;} function _retEStr(){return "";} function _retVoid(){} ////// when optimizing, don"t remove anything above this comment ////// function _cbeCreateElement(sEleType){// returns an Element object

 var ele=null;
 if (document.createElement && sEleType.length){
   ele=document.createElement(sEleType);
   if (ele && ele.style){ele.style.position="absolute";}
}
 else if (document.layers){
   ele=new Object();
}
 return ele;

} CrossBrowserNode.prototype.appendChild=function(eleChild){// returns the appended Element object on success

 var cbe, ele, rv=null;
 if (document.layers){
   var thisEle;
   if (this.index < 2) thisEle=window;
   else thisEle=this.ele;
   ele=new Layer(this.width(), thisEle);
   if (ele){
     if (eleChild.id) ele.id=ele.name=eleChild.id;
     cbe=new CrossBrowserElement();
     cbeBindElement(cbe, ele);
     this.appendNode(ele.cbe);
     eleChild.cbe=cbe;
     ++this.childNodes;
     rv=ele;
  }
}
 else{
   if (this.index < 2) ele=document.body;
   else ele=this.ele;
   if (ele.appendChild){
     ele.appendChild(eleChild);
     cbe=new CrossBrowserElement();
     cbeBindElement(cbe, eleChild);
     this.appendNode(eleChild.cbe);
     ++this.childNodes;
     rv=eleChild;
  }
}
 return rv;

} CrossBrowserNode.prototype.removeChild=function(eleChild){

 var ele, rv=null;
 if (this.index < 2) ele=document.body;
 else ele=this.ele;
 if (ele.removeChild || document.layers){
   --this.childNodes;
   var prevSib=eleChild.cbe.previousSibling;
   var nextSib=eleChild.cbe.nextSibling;
   with (eleChild.cbe){
     parentNode=null;
     previousSibling=null;
     nextSibling=null;
  }
   if (prevSib) prevSib.nextSibling=nextSib;
   else this.firstChild=nextSib;
   if (nextSib) nextSib.previousSibling=prevSib;
   else this.lastChild=prevSib;
   if (document.layers){
     //// working on it
  }
   else{
     ele.removeChild(eleChild);
  }
   rv=eleChild;
}
 return rv;

} function _cbeContains(iLeft, iTop, iClipTop, iClipRight, iClipBottom, iClipLeft){if (arguments.length==2){iClipTop=iClipRight=iClipBottom=iClipLeft=0;} else if (arguments.length==3){iClipRight=iClipBottom=iClipLeft=iClipTop;} else if (arguments.length==4){iClipLeft=iClipRight; iClipBottom=iClipTop;} var thisX=this.pageX(), thisY=this.pageY(); return ( iLeft >=thisX + iClipLeft && iLeft <=thisX + this.width() - iClipRight && iTop >=thisY + iClipTop && iTop <=thisY + this.height() - iClipBottom );} function _cbeMoveTo(x_cr, y_mar, outside, xEndL){if (isFinite(x_cr)){this.left(x_cr); this.top(y_mar);}else{this.cardinalPosition(x_cr, y_mar, outside); this.left(this.x); this.top(this.y);}if (xEndL) cbeEval(xEndL, this);} function _cbeMoveBy(uDX, uDY, xEndL){if (uDX){this.left(this.left() + uDX);} if (uDY){this.top(this.top() + uDY);} if (xEndL){cbeEval(xEndL, this);}} function _domLeft(iX){if (arguments.length){this.ele.style.left=iX + "px";} else{iX=parseInt(this.ele.style.left); if (isNaN(iX)) iX=0;}return iX;} function _ieLeft(iX){if (arguments.length){this.ele.style.pixelLeft=iX;} else{iX=this.ele.style.pixelLeft;} return iX;} function _nnLeft(iX){if (arguments.length){this.ele.left=iX;} else{iX=this.ele.left;} return iX;} function _domTop(iY){if (arguments.length){this.ele.style.top=iY + "px";} else{iY=parseInt(this.ele.style.top); if (isNaN(iY)) iY=0;}return iY;} function _ieTop(iY){if (arguments.length){this.ele.style.pixelTop=iY;} else{iY=this.ele.style.pixelTop;} return iY;} function _nnTop(iY){if (arguments.length){this.ele.top=iY;} else{iY=this.ele.top;} return iY;} function _nnOffsetLeft(){var ol=this.ele.pageX - this.parentElement.pageX; if (isNaN(ol)){ol=this.ele.pageX;} return ol;} function _nnOffsetTop(){var ot=this.ele.pageY - this.parentElement.pageY; if (isNaN(ot)){ot=this.ele.pageY;} return ot;} function _ieOffsetLeft(){var x=this.ele.offsetLeft, parent=this.ele.offsetParent; while(parent && !parent.cbe){x +=parent.offsetLeft; parent=parent.offsetParent;}return x;} function _ieOffsetTop(){var y=this.ele.offsetTop, parent=this.ele.offsetParent; while(parent && !parent.cbe){y +=parent.offsetTop; parent=parent.offsetParent;}return y;} function _nnPageX(){return this.ele.pageX;} function _nnPageY(){return this.ele.pageY;} function _cbePageX(){var x=this.offsetLeft(), parent=this.parentNode; if (parent){while(parent.index > 1){x +=parent.offsetLeft(); parent=parent.parentNode;}} return x;} function _cbePageY(){var y=this.offsetTop(), parent=this.parentNode; if (parent){while(parent.index > 1){y +=parent.offsetTop(); parent=parent.parentNode;}} return y;} function _cbeSizeTo(uW, uH){this.width(uW); this.height(uH);} function _cbeSizeBy(iDW, iDH){this.width(this.width() + iDW); this.height(this.height() + iDH);} function _cbeResizeTo(uW, uH, xEndListener){this.sizeTo(uW, uH); this.clip("auto"); cbeEval(xEndListener, this);} function _cbeResizeBy(iDW, iDH, xEndListener){this.sizeBy(iDW, iDH); this.clip("auto"); cbeEval(xEndListener, this);} function _domWidth(uW){if (arguments.length){uW=Math.round(uW); _domSetWidth(this.ele, uW);}return this.ele.offsetWidth;} function _ieWidth(uW){if (arguments.length){uW=Math.round(uW); this.ele.style.pixelWidth=uW;}return this.ele.style.pixelWidth;} function _nnWidth(uW){if (arguments.length){this.w=Math.round(uW); this.ele.clip.right=this.w;}return this.w;} function _domHeight(uH){if (arguments.length){uH=Math.round(uH); _domSetHeight(this.ele, uH);}return this.ele.offsetHeight;} function _ieHeight(uH){if (arguments.length){uH=Math.round(uH); this.ele.style.pixelHeight=uH;}return this.ele.style.pixelHeight;} function _nnHeight(uH){if (arguments.length){this.h=Math.round(uH); this.ele.clip.bottom=this.h;}return this.h;} function _domSetWidth(ele,uW){

 if (uW < 0) return;
 var pl=0,pr=0,bl=0,br=0;
 if (_def(document.defaultView) && _def(document.defaultView.getComputedStyle)){// gecko and standard
   pl=parseInt(document.defaultView.getComputedStyle(ele, "").getPropertyValue("padding-left"));
   pr=parseInt(document.defaultView.getComputedStyle(ele, "").getPropertyValue("padding-right"));
   bl=parseInt(document.defaultView.getComputedStyle(ele, "").getPropertyValue("border-left-width"));
   br=parseInt(document.defaultView.getComputedStyle(ele, "").getPropertyValue("border-right-width"));
}
 else if (_def(ele.currentStyle, document.rupatMode)){
   if (document.rupatMode=="CSS1Compat"){// ie6up in css1compat mode
     pl=parseInt(ele.currentStyle.paddingLeft);
     pr=parseInt(ele.currentStyle.paddingRight);
     bl=parseInt(ele.currentStyle.borderLeftWidth);
     br=parseInt(ele.currentStyle.borderRightWidth);
  }
}
 if (isNaN(pl)) pl=0; if (isNaN(pr)) pr=0; if (isNaN(bl)) bl=0; if (isNaN(br)) br=0;
 var cssW=uW-(pl+pr+bl+br);
 if (isNaN(cssW) || cssW < 0) return;
 ele.style.width=cssW + "px";

} function _domSetHeight(ele,uH){

 if (uH < 0) return;
 var pt=0,pb=0,bt=0,bb=0;
 if (_def(document.defaultView) && _def(document.defaultView.getComputedStyle)){
   pt=parseInt(document.defaultView.getComputedStyle(ele, "").getPropertyValue("padding-top"));
   pb=parseInt(document.defaultView.getComputedStyle(ele, "").getPropertyValue("padding-bottom"));
   bt=parseInt(document.defaultView.getComputedStyle(ele, "").getPropertyValue("border-top-width"));
   bb=parseInt(document.defaultView.getComputedStyle(ele, "").getPropertyValue("border-bottom-width"));
}
 else if (_def(ele.currentStyle, document.rupatMode)){
   if (document.rupatMode=="CSS1Compat"){
     pt=parseInt(ele.currentStyle.paddingTop);
     pb=parseInt(ele.currentStyle.paddingBottom);
     bt=parseInt(ele.currentStyle.borderTopWidth);
     bb=parseInt(ele.currentStyle.borderBottomWidth);
  }
}
 if (isNaN(pt)) pt=0; if (isNaN(pb)) pb=0; if (isNaN(bt)) bt=0; if (isNaN(bb)) bb=0;
 var cssH=uH-(pt+pb+bt+bb);
 if (isNaN(cssH) || cssH < 0) return;
 ele.style.height=cssH + "px";

} function _cbeScrollLeft(){return this.ele.scrollLeft;} function _cbeScrollTop(){return this.ele.scrollTop;} function _cbeShow(){this.visibility(1);} function _cbeHide(){this.visibility(0);} function _domVisibility(vis){if (arguments.length){if (vis){this.ele.style.visibility="inherit";} else{this.ele.style.visibility="hidden";}}else return (this.ele.style.visibility=="visible" || this.ele.style.visibility=="inherit" || this.ele.style.visibility=="");} function _nnVisibility(vis){if (arguments.length){if (vis){this.ele.visibility="inherit";} else{this.ele.visibility="hide";}}else return (this.ele.visibility=="show" || this.ele.visibility=="inherit" || this.ele.visibility=="");} function _domZIndex(uZ){if (arguments.length){this.ele.style.zIndex=uZ;} else{uZ=parseInt(this.ele.style.zIndex); if (isNaN(uZ)) uZ=0;}return uZ;} function _nnZIndex(uZ){if (arguments.length) this.ele.zIndex=uZ; return this.ele.zIndex;} function _domBackground(sColor, sImage){if (arguments.length){if (!sColor){sColor="transparent";} this.ele.style.backgroundColor=sColor; if (arguments.length==2){this.ele.style.backgroundImage="url(" + sImage + ")";}}else return this.ele.style.backgroundColor;} function _nnBackground(sColor, sImage){if (arguments.length){if (sColor=="transparent"){sColor=null;} this.ele.bgColor=sColor; if (arguments.length==2){this.ele.background.src=sImage || null;}}else{var bg=this.ele.bgColor; if (window.cbeUtilJsLoaded){bg=cbeHexString(bg,6,"#");} return bg;}} function _domColor(newColor){if (arguments.length){this.ele.style.color=newColor;}else return this.ele.style.color;} function _domClip(iTop, iRight, iBottom, iLeft){if (arguments.length==4){var clipRect="rect(" + iTop + "px " + iRight + "px " + iBottom + "px " + iLeft + "px" + ")"; this.ele.style.clip=clipRect;}else{this.clip(0, this.ele.offsetWidth, this.ele.offsetHeight, 0);}} function _nnClip(iTop, iRight, iBottom, iLeft){if (arguments.length==4){this.ele.clip.top=iTop; this.ele.clip.right=iRight; this.ele.clip.bottom=iBottom; this.ele.clip.left=iLeft;}else{this.clip(0, this.width(), this.height(), 0);}} function _ieInnerHtml(sHtml){if (arguments.length){this.ele.innerHTML=sHtml;}else return this.ele.innerHTML;} function _nnInnerHtml(sHtml){if (arguments.length){if (sHtml==""){sHtml=" ";} this.ele.document.open(); this.ele.document.write(sHtml); this.ele.document.close();}else return "";} CrossBrowserElement.prototype.cardinalPosition=function(cp, margin, outside){

 if (typeof(cp) !="string"){window.status="cardinalPosition() error: cp=" + cp + ", id=" + this.id; return;}
 var x=this.left(), y=this.top(), w=this.width(), h=this.height();
 var pw=this.parentNode.width(), ph=this.parentNode.height();
 var sx=this.parentNode.scrollLeft(), sy=this.parentNode.scrollTop();
 var right=sx + pw, bottom=sy + ph;
 var cenLeft=sx + Math.floor((pw-w)/2), cenTop=sy + Math.floor((ph-h)/2);
 if (!margin) margin=0;
 else{
   if (outside) margin=-margin;
   sx +=margin; sy +=margin; right -=margin; bottom -=margin;
}
 switch (cp.toLowerCase()){
   case "n": x=cenLeft; if (outside) y=sy - h; else y=sy; break;
   case "ne": if (outside){x=right; y=sy - h;}else{x=right - w; y=sy;}break;
   case "e": y=cenTop; if (outside) x=right; else x=right - w; break;
   case "se": if (outside){x=right; y=bottom;}else{x=right - w; y=bottom - h}break;
   case "s": x=cenLeft; if (outside) y=sy - h; else y=bottom - h; break;
   case "sw": if (outside){x=sx - w; y=bottom;}else{x=sx; y=bottom - h;}break;
   case "w": y=cenTop; if (outside) x=sx - w; else x=sx; break;
   case "nw": if (outside){x=sx - w; y=sy - h;}else{x=sx; y=sy;}break;
   case "cen": case "center": x=cenLeft; y=cenTop; break;
   case "cenh": x=cenLeft; break;
   case "cenv": y=cenTop; break;
}
 this.x=x; this.y=y;

} function cbeInnerWidth(){

 var w=0;
 if (is.opera5or6){w=window.innerWidth;}
 else if (is.ie && document.documentElement && document.documentElement.clientWidth) w=document.documentElement.clientWidth; // ie6 compat mode
 else if (document.body && document.body.clientWidth) w=document.body.clientWidth; // ie4up and gecko
 else if (_def(window.innerWidth,window.innerHeight,document.height)){// nn4
   w=window.innerWidth;
   if (document.height > window.innerHeight) w -=16;
}
 return w;

} function cbeInnerHeight(){

 var h=0;
 if (is.opera5or6){h=window.innerHeight;}
 else if (is.ie && document.documentElement && document.documentElement.clientHeight) h=document.documentElement.clientHeight;
 else if (document.body && document.body.clientHeight) h=document.body.clientHeight;
 else if (_def(window.innerWidth,window.innerHeight,document.width)){
   h=window.innerHeight;
   if (document.width > window.innerWidth) h -=16;
}
 return h;

} function cbePageXOffset(){

 var offset=0;
 if (_def(window.pageXOffset)) offset=window.pageXOffset; // gecko, nn4, opera
 else if (document.documentElement && document.documentElement.scrollLeft) offset=document.documentElement.scrollLeft; // ie6 compat mode
 else if (document.body && _def(document.body.scrollLeft)) offset=document.body.scrollLeft; // ie4up
 return offset;

} function cbePageYOffset(){

 var offset=0;
 if (_def(window.pageYOffset)) offset=window.pageYOffset;
 else if (document.documentElement && document.documentElement.scrollTop) offset=document.documentElement.scrollTop;
 else if (document.body && _def(document.body.scrollTop)) offset=document.body.scrollTop;
 return offset;

} function cbeEval(exp, arg1, arg2, arg3, arg4, arg5, arg6){

 if (typeof(exp)=="function") exp(arg1, arg2, arg3, arg4, arg5, arg6);
 else if (typeof(exp)=="object" && typeof(arg1)=="function") {
   exp._cbeEval_ = arg1;
   exp._cbeEval_(arg2, arg3, arg4, arg5, arg6);
 }  
 else if (typeof(exp)=="string") eval(exp);

} function ClientSnifferJr(){

 this.ua=navigator.userAgent.toLowerCase();
 this.major=parseInt(navigator.appVersion);
 this.minor=parseFloat(navigator.appVersion);
 if (document.addEventListener && document.removeEventListener) this.dom2events=true;
 if (document.getElementById) this.dom1getbyid=true;
 if (window.opera){
   this.opera=true;
   this.opera5=(this.ua.indexOf("opera 5") !=-1 || this.ua.indexOf("opera/5") !=-1);
   this.opera6=(this.ua.indexOf("opera 6") !=-1 || this.ua.indexOf("opera/6") !=-1);
   this.opera5or6=this.opera5 || this.opera6;
   this.opera7=(this.ua.indexOf("opera 7") !=-1 || this.ua.indexOf("opera/7") !=-1);
   return;
}
 this.konq=this.ua.indexOf("konqueror") !=-1;
 this.ie=this.ua.indexOf("msie") !=-1;
 if (this.ie){
   this.ie3=this.major < 4;
   this.ie4=(this.major==4 && this.ua.indexOf("msie 5")==-1 && this.ua.indexOf("msie 6")==-1);
   this.ie4up=this.major >=4;
   this.ie5=(this.major==4 && this.ua.indexOf("msie 5.0") !=-1);
   this.ie5up=!this.ie3 && !this.ie4;
   this.ie6=(this.major==4 && this.ua.indexOf("msie 6.0") !=-1);
   this.ie6up=(!this.ie3 && !this.ie4 && !this.ie5 && this.ua.indexOf("msie 5.5")==-1);
   return;
}
 this.hotjava=this.ua.indexOf("hotjava") !=-1;
 this.webtv=this.ua.indexOf("webtv") !=-1;
 this.aol=this.ua.indexOf("aol") !=-1;
 if (this.hotjava || this.webtv || this.aol) return;
 // Gecko, NN4, and NS6
 this.gecko=this.ua.indexOf("gecko") !=-1;
 this.nav=(this.ua.indexOf("mozilla") !=-1 && this.ua.indexOf("spoofer")==-1 && this.ua.indexOf("compatible")==-1);
 if (this.nav){
   this.nav4=this.major==4;
   this.nav4up=this.major >=4;
   this.nav5up=this.major >=5;
   this.nav6=this.major==5;
   this.nav6up=this.nav5up;
}

} window.is=new ClientSnifferJr(); // End cbe_core.js </script>

<script type="text/javascript" > /* cbe_event.js $Revision: 0.15 $

* CBE v4.19, Cross-Browser DHTML API from Cross-Browser.ru
* Copyright (c) 2002 Michael Foster (mike@cross-browser.ru)
* Distributed under the terms of the GNU LGPL from gnu.org
  • /

function cbeELReg(eventType, eventListener, eventCapture, listenerObject) { // event listener registration object constructor

 this.type = eventType; this.listener = eventListener; this.capture = eventCapture; this.obj = listenerObject;

} function CrossBrowserEvent(e) { // Object constructor

 // from DOM2 Interface Event
 this.type = "";
 this.target = null;
 this.currentTarget = null;
 this.eventPhase = 0;
 this.bubbles = true;
 this.cancelable = true;
 this.timeStamp = 0;
 this.AT_TARGET = 1; this.BUBBLING_PHASE = 2; this.CAPTURING_PHASE = 3; // eventPhase masks
 // from DOM2 Interface MouseEvent : UIEvent
 this.screenX = 0;
 this.screenY = 0;
 this.clientX = 0;
 this.clientY = 0;
 this.ctrlKey = false;
 this.shiftKey = false;
 this.altKey = false;
 this.metaKey = false;
 this.button = 3; // 3 == undefined
 this.relatedTarget = null;
 this.LEFT = 0; this.MIDDLE = 1; this.RIGHT = 2; // button masks
 // from IE4 Object Model
 this.keyCode = 0;
 this.offsetX = 0;
 this.offsetY = 0;
 // from NN4 Object Model
 this.pageX = 0;
 this.pageY = 0;
 // CBE
 this.stopPropagationFlag = false;
 this.preventDefaultFlag = false;
 this.cbeTarget = window.cbe;
 this.cbeCurrentTarget = window.cbe;
 if (!e) return;
 
 if (e.type) { this.type = e.type; }
 if (e.target) { this.target = e.target; }
 else if (e.srcElement) { this.target = e.srcElement; }
 if (e.currentTarget) { this.currentTarget = e.currentTarget; }
 else if (e.toElement) { this.currentTarget = e.toElement; }
 if (e.eventPhase) { this.eventPhase = e.eventPhase; }
 if (e.bubbles) { this.bubbles = e.bubbles; }
 if (e.cancelable) { this.cancelable = e.cancelable; }
 if (e.timeStamp) { this.timeStamp = e.timeStamp; }
 if (e.screenX) { this.screenX = e.screenX; }
 if (e.screenY) { this.screenY = e.screenY; }
 if (is.opera5or6) { this.clientX = e.clientX - document.cbe.scrollLeft(); }
 else if (e.clientX) { this.clientX = e.clientX; }
 else if (e.pageX) { this.clientX = e.pageX - document.cbe.scrollLeft(); }
 if (is.opera5or6) { this.clientY = e.clientY - document.cbe.scrollLeft(); }
 else if (e.clientY) { this.clientY = e.clientY; }
 else if (e.pageY) { this.clientY = e.pageY - document.cbe.scrollLeft(); }
 if (is.opera5or6) { this.ctrlKey = e.type=="mousemove" ? e.shiftKey : e.ctrlKey; }
 else if (_def(e.ctrlKey)) { this.ctrlKey = e.ctrlKey; }
 else if (_def(e.modifiers) && window.Event) { this.ctrlKey = (e.modifiers & window.Event.CONTROL_MASK) != 0; }
 if (is.opera5or6) { this.shiftKey = e.type=="mousemove" ? e.ctrlKey : e.shiftKey; }
 else if (_def(e.shiftKey)) { this.shiftKey = e.shiftKey; }
 else if (_def(e.modifiers) && window.Event) { this.shiftKey = (e.modifiers & Event.SHIFT_MASK) != 0; }
 if (e.altKey) { this.altKey = e.altKey; }
 else if (_def(e.modifiers) && window.Event) { this.altKey = (e.modifiers & Event.ALT_MASK) != 0; }
 if (e.metaKey) { this.metaKey = e.metaKey; }
 // button (?)
 if (is.ie) { 
   if (this.type.indexOf("mouse") != -1) {
     if (e.button == 1) this.button = this.LEFT;
     else if (e.button == 4) this.button = this.MIDDLE;
     else if (e.button == 2) this.button = this.RIGHT;
   }
   else if (this.type == "click") this.button = this.LEFT;
   else this.button = 4; // non-mouse event
 }
 else if (_def(e.button)) { // standard
   if (this.type.indexOf("mouse") != -1) { this.button = e.button; if (this.button < 0 || this.button > 2) {this.button = 3;} }
   else if (this.type == "click") this.button = this.LEFT;
   else this.button = 4; // non-mouse event
 }  
 else if (_def(e.which)) {
   if (document.layers) { // nn4
     if (this.type.indexOf("mouse") != -1) { this.button = e.which - 1; if (this.button < 0 || this.button > 2) {this.button = 3;} }
     else if (this.type == "click") this.button = this.LEFT;
     else this.button = 4; // non-mouse event
   }
   else { // opera5or6
     if ((e.type == "click" && e.which == 0) || ((e.type == "mousedown" || e.type == "mouseup") && e.which == 1)) {this.button = this.LEFT;}
   }
 }
 if (e.relatedTarget) { this.relatedTarget = e.relatedTarget; }
 else if (e.fromElement) { this.relatedTarget = e.fromElement; } // ? may need to be toElement in some cases ?
 if (_def(e.which)) { this.keyCode = e.which; }
 else if (_def(e.keyCode)) { this.keyCode = e.keyCode; }
 var calcOfs = false;
 if (_def(e.layerX,e.layerY)) { this.offsetX = e.layerX; this.offsetY = e.layerY; }
 else calcOfs = true; // calculate it below
 if (is.opera5or6) { this.pageX = e.clientX; this.pageY = e.clientY; }
 else if (_def(e.pageX,e.pageY)) { this.pageX = e.pageX; this.pageY = e.pageY; }
 else {
   this.pageX = this.clientX + document.cbe.scrollLeft();
   this.pageY = this.clientY + document.cbe.scrollTop();
 }
 
 // Find the CBE event target
 if (document.layers) {
   this.cbeTarget = cbeGetNodeFromPoint(this.pageX, this.pageY);
   // NN4 note: mouseout works only if mouseover and mouseout are both added to the same object
   if (this.type == "mouseover") cbeMOT = this.cbeTarget;
   else if (this.type == "mouseout") this.cbeTarget = cbeMOT || document.cbe;
 }
 else { var target = this.target; while (!target.cbe) {target = cbeGetParentElement(target);} this.cbeTarget = target.cbe; }
 this.cbeCurrentTarget = this.cbeTarget;
 if (calcOfs) { this.offsetX = this.pageX - this.cbeTarget.pageX(); this.offsetY = this.pageY - this.cbeTarget.pageY(); }

} CrossBrowserElement.prototype.addEventListener = function(eventType, eventListener, useCapture, listenerObject) {

 if (!useCapture) useCapture = false;
 eventType = eventType.toLowerCase();
 if (
   (eventType.indexOf("mouse") != -1)
   || eventType == "click"
   || (eventType.indexOf("key") != -1)

/* || (eventType.indexOf("resize") != -1 && !is.nav4 && !is.opera)

   || (eventType.indexOf("scroll") != -1 && !is.nav && !is.opera) */
 ) {
   var add=true;
   for (var i=0; i < this.listeners.length; ++i) { if (eventType == this.listeners[i].type) {add=false; break;} }
   if (add) {
     cbeNativeAddEventListener(this.ele, eventType, cbePropagateEvent, false);
   }
   this.listeners[this.listeners.length] = new cbeELReg(eventType, eventListener, useCapture, listenerObject);
   return;
 }
 switch(eventType) {
   case "slidestart": this.onslidestart = eventListener; return;
   case "slide": this.onslide = eventListener; return;
   case "slideend": this.onslideend = eventListener; return;
   case "dragstart": this.ondragstart = eventListener; return;
   case "drag":
     this.ondragCapture = useCapture;
     this.ondrag = eventListener;
     this.addEventListener("mousedown", cbeDragStartEvent, useCapture);
     return;
   case "dragend": this.ondragend = eventListener; return;
   case "dragresize": if (window.cbeUtilJsLoaded) cbeAddDragResizeListener(this); return;
   case "scroll":
     if (is.nav || is.opera) {
       window.cbeOldScrollTop = cbePageYOffset();
       window.cbeOnScrollListener = eventListener;
       cbeScrollEvent();
       return;
     }
     break;
   case "resize":
     if (is.nav4 || is.opera) {
       window.cbeOldWidth = cbeInnerWidth();
       window.cbeOldHeight = cbeInnerHeight();
       window.cbeOnResizeListener = eventListener;
       cbeResizeEvent();
       return;
     }
     break;
 } // end switch
 cbeNativeAddEventListener(this.ele, eventType, eventListener, useCapture);

} function cbeNativeAddEventListener(ele, eventType, eventListener, useCapture) {

 if (!useCapture) useCapture = false;
 eventType = eventType.toLowerCase();
 var eh = "ele.on" + eventType + "=eventListener";
 if (ele.addEventListener) {
   ele.addEventListener(eventType, eventListener, useCapture);
 }
 else if (ele.captureEvents) {

// if (useCapture || (eventType.indexOf("mousemove")!=-1)) // ???

     ele.captureEvents(eval("Event." + eventType.toUpperCase()));
   eval(eh);
 }
 else { eval(eh); }

} function cbeNativeRemoveEventListener(ele, eventType, eventListener, useCapture) {

 if (!useCapture) useCapture = false;
 eventType = eventType.toLowerCase();
 var eh = "ele.on" + eventType + "=null";
 if (ele.removeEventListener) {
   ele.removeEventListener(eventType, eventListener, useCapture);
 }
 else if (ele.releaseEvents) {

// if (useCapture || (eventType.indexOf("mousemove")!=-1)) // ???

     ele.releaseEvents(eval("Event." + eventType.toUpperCase()));
   eval(eh);
 }
 else { eval(eh); }

} CrossBrowserElement.prototype.removeEventListener = function(eventType, eventListener, useCapture) {

 eventType = eventType.toLowerCase();
 if (!useCapture) useCapture = false;
 if ((eventType.indexOf("mouse") != -1) || eventType == "click" || (eventType.indexOf("key") != -1)) {
   var i;
   for (i = 0; i < this.listeners.length; ++i) {
     if (this.listeners[i].type == eventType && this.listeners[i].listener == eventListener && this.listeners[i].capture == useCapture) {
       if (this.listeners.splice) this.listeners.splice(i, 1);
       else this.listeners[i].type = "*";
       break;
     }
   }
   var remove=true;
   for (i = 0; i < this.listeners.length; ++i) { if (eventType == this.listeners[i].type) { remove = false; break; } }
   if (remove) cbeNativeRemoveEventListener(this.ele, eventType, cbePropagateEvent, false);
   return;
 }
 switch(eventType) {
   case "slidestart": this.onslidestart = null; return;
   case "slide": this.onslide = null; return;
   case "slideend": this.onslideend = null; return;
   case "dragstart": this.ondragstart = null; return;
   case "drag":
     this.removeEventListener("mousedown", cbeDragStartEvent, this.ondragCapture);
     this.ondrag = null;
     return;
   case "dragend": this.ondragend = null; return;
   case "dragresize": if (window.cbeUtilJsLoaded) cbeRemoveDragResizeListener(this); return;
   case "scroll":
     if (is.nav || is.opera) {
       window.cbeOnScrollListener = null;
       return;
     }
     break;
   case "resize":
     if (is.nav4 || is.opera) {
       window.cbeOnResizeListener = null;
       return;
     }
     break;
 } // end switch
 cbeNativeRemoveEventListener(this.ele, eventType, eventListener, useCapture);

} CrossBrowserEvent.prototype.stopPropagation = function() { this.stopPropagationFlag = true; } CrossBrowserEvent.prototype.preventDefault = function() { this.preventDefaultFlag = true; } CrossBrowserElement.prototype.dispatchEvent= function(e) {

 var dispatch;
 e.cbeCurrentTarget = this;
 for (var i=0; i < this.listeners.length; ++i) {
   dispatch = false;
   if (e.type == this.listeners[i].type) {
     if (e.eventPhase == e.CAPTURING_PHASE) {
       if (this.listeners[i].capture) dispatch = true;
     }
     else if (!this.listeners[i].capture) dispatch = true;
   }
   if (dispatch) {
     if (this.listeners[i].obj) cbeEval(this.listeners[i].obj, this.listeners[i].listener, e);
     else cbeEval(this.listeners[i].listener, e);
   }
 }

} function cbePropagateEvent(evt) {

 var i=0, e=null, a=new Array();
 if (evt) e = new CrossBrowserEvent(evt);
 else if (window.event) e = new CrossBrowserEvent(window.event);
 else return;
 // Create an array of EventTargets, following the parent chain up (does not include cbeTarget)
 var node = e.cbeTarget.parentNode;
 while(node) {
   a[i++] = node;
   node = node.parentNode;
 }
 // The capturing phase
 e.eventPhase = e.CAPTURING_PHASE;
 for (i = a.length-1; i>=0; --i) {
   a[i].dispatchEvent(e);
   if (e.stopPropagationFlag) break;
 }
 // The at-target phase
 if (!e.stopPropagationFlag) {
   e.eventPhase = e.AT_TARGET;
   e.cbeTarget.dispatchEvent(e);
   // The bubbling phase
   if (!e.stopPropagationFlag && e.bubbles) {
     e.eventPhase = e.BUBBLING_PHASE;
     for (i = 0; i < a.length; ++i) {
       a[i].dispatchEvent(e);
       if (e.stopPropagationFlag) break;
     }
   }
 }
 //  Don"t allow native bubbling
 if (is.ie) window.event.cancelBubble = true;
 else if (is.gecko) evt.stopPropagation();
 // Allow listener to cancel default action
 if (e.cancelable && e.preventDefaultFlag) {
   if (is.gecko || is.opera) evt.preventDefault();
   return false;
 }
 else return true;

} function cbeGetNodeFromPoint(x, y) {

 var hn /* highNode */, hz=0 /* highZ */, cn /* currentNode */, cz /* currentZ */;
 hn = document.cbe;
 while (hn.firstChild && hz >= 0) {
   hz = -1;
   cn = hn.firstChild;
   while (cn) {
     if (cn.contains(x, y)) {
       cz = cn.zIndex();
       if (cz >= hz) {
         hn = cn;
         hz = cz;
       }
     }
     cn = cn.nextSibling;
   }
 }
 return hn;

} function cbeScrollEvent() {

 if (!window.cbeOnScrollListener) { return; }
 if (cbePageYOffset() != window.cbeOldScrollTop) {
   cbeEval(window.cbeOnScrollListener);
   window.cbeOldScrollTop = cbePageYOffset();
 }
 setTimeout("cbeScrollEvent()", 250);

} function cbeResizeEvent() {

 if (!window.cbeOnResizeListener) { return; }
 var dw = window.cbeOldWidth - cbeInnerWidth();
 var dh = window.cbeOldHeight - cbeInnerHeight();
 if (dw != 0 || dh != 0) {
   if (window.cbeOnResizeListener) cbeEval(window.cbeOnResizeListener, dw, dh);
   window.cbeOldWidth = cbeInnerWidth();
   window.cbeOldHeight = cbeInnerHeight();
 }
 setTimeout("cbeResizeEvent()", 250);

} function cbeDefaultResizeListener() {

 if (is.opera) location.replace(location.href);
 else history.go(0);

} var cbeDragObj, cbeDragTarget, cbeDragPhase; function cbeDragStartEvent(e) {

 if (is.opera) { var tn = e.target.tagName.toLowerCase(); if (tn == "a") return; }
 else if (is.nav4) { if (e.target.href) return; }
 cbeDragObj = e.cbeCurrentTarget;
 cbeDragTarget = e.cbeTarget;
 if (cbeDragTarget.id == cbeDragObj.id) cbeDragPhase = e.AT_TARGET;
 else if (cbeDragObj.ondragCapture) cbeDragPhase = e.CAPTURING_PHASE;
 else cbeDragPhase = e.BUBBLING_PHASE;
 if (cbeDragObj) {
   if (cbeDragObj.ondragstart) { e.type = "dragstart"; cbeEval(cbeDragObj.ondragstart, e); e.type = "mousedown"; }
   cbeDragObj.x = e.pageX;
   cbeDragObj.y = e.pageY;
   document.cbe.addEventListener("mousemove", cbeDragEvent, cbeDragObj.ondragCapture);
   document.cbe.addEventListener("mouseup", cbeDragEndEvent, false);
 }
 e.stopPropagation();
 e.preventDefault();

} function cbeDragEndEvent(e) {

 document.cbe.removeEventListener("mousemove", cbeDragEvent, cbeDragObj.ondragCapture);
 document.cbe.removeEventListener("mouseup", cbeDragEndEvent, false);
 if (cbeDragObj.ondragend) {
   e.type = "dragend";
   e.cbeCurrentTarget = cbeDragObj;
   e.cbeTarget = cbeDragTarget;
   cbeEval(cbeDragObj.ondragend, e);
   e.type = "mouseup";
 }
 //e.stopPropagation();
 e.preventDefault();

} function cbeDragEvent(e) {

 if (cbeDragObj) {
   e.dx = e.pageX - cbeDragObj.x;
   e.dy = e.pageY - cbeDragObj.y;
   cbeDragObj.x = e.pageX;
   cbeDragObj.y = e.pageY;
   e.type = "drag";
   e.cbeTarget = cbeDragTarget;
   e.cbeCurrentTarget = cbeDragObj;
   e.eventPhase = cbeDragPhase;
   if (cbeDragObj.ondrag) cbeEval(cbeDragObj.ondrag, e);
   else cbeDragObj.moveBy(e.dx,e.dy);
   e.type = "mousemove";
 }
 //e.stopPropagation();
 e.preventDefault();

} var cbeEventPhase = new Array("", "AT_TARGET", "BUBBLING_PHASE", "CAPTURING_PHASE"); var cbeButton = new Array("LEFT", "MIDDLE", "RIGHT", "undefined", "non-mouse event"); CrossBrowserElement.prototype.ondragstart = null; CrossBrowserElement.prototype.ondrag = null; CrossBrowserElement.prototype.ondragend = null; var cbeEventJsLoaded = true; // End cbe_event.js </script>

<script type="text/javascript" > /* cbe_slide.js $Revision: 0.12 $

* CBE v4.19, Cross-Browser DHTML API from Cross-Browser.ru
* Copyright (c) 2002 Michael Foster (mike@cross-browser.ru)
* Distributed under the terms of the GNU LGPL from gnu.org
  • /

CrossBrowserElement.prototype.slideBy = function(dX, dY, totalTime, endListener) {

 var targetX, targetY;
 dX = parseInt(dX); dY = parseInt(dY); targetX = this.left() + dX; targetY = this.top() + dY;
 this.slideTo(targetX, targetY, totalTime, endListener)

} CrossBrowserElement.prototype.slideTo = function(x, y, totalTime, endListener) {

 if (this.onslidestart) cbeEval(this.onslidestart, this);
 this.xTarget = parseInt(x); this.yTarget = parseInt(y);
 this.slideTime = parseInt(totalTime);
 if (isNaN(this.xTarget)) {
   var outside=false;
   if (isNaN(this.yTarget)) { y = 0; outside = true; }
   this.cardinalPosition(x, y, outside); this.xTarget = this.x; this.yTarget = this.y;
 }
 if (endListener && window.cbeEventJsLoaded) { this.autoRemoveListener = true; this.addEventListener("slideend", endListener); }
 this.stop = false;
 this.yA = this.yTarget - this.top(); this.xA = this.xTarget - this.left(); // A = distance
 this.B = Math.PI / (2 * this.slideTime); // B = period
 this.yD = this.top(); this.xD = this.left(); // D = initial position
 if (this.slideRate == cbeSlideRateLinear) { this.B = 1/this.slideTime; }
 else if (this.slideRate == cbeSlideRateCosine) {
   this.yA = -this.yA; this.xA = -this.xA; this.yD = this.yTarget; this.xD = this.xTarget;
 }
 var d = new Date(); this.C = d.getTime();
 if (!this.moving) this.slide();

} CrossBrowserElement.prototype.slide = function() {

 var now, s, t, newY, newX;
 now = new Date();
 t = now.getTime() - this.C;
 if (this.stop) { this.moving = false; }
 else if (t < this.slideTime) {
   setTimeout("window.cbeAll["+this.index+"].slide()", this.timeout);
   if (this.slideRate == cbeSlideRateLinear) s = this.B * t;
   else if (this.slideRate == cbeSlideRateSine) s = Math.sin(this.B * t);
   else s = Math.cos(this.B * t); // this.slideRate == cbeSlideRateCosine
   newX = Math.round(this.xA * s + this.xD);
   newY = Math.round(this.yA * s + this.yD);
   if (this.onslide) cbeEval(this.onslide, this, newX, newY, t);
   this.moveTo(newX, newY);
   this.moving = true;
 }  
 else {
   this.moveTo(this.xTarget, this.yTarget);
   this.moving = false;
   if (this.onslideend) {
     var tmp = this.onslideend;
     if (this.autoRemoveListener && window.cbeEventJsLoaded) {
       this.autoRemoveListener = false;
       this.removeEventListener("slideend");
     }
     cbeEval(tmp, this);
   }
 }  

} CrossBrowserElement.prototype.ellipse = function(xRadius, yRadius, radiusInc, totalTime, startAngle, stopAngle, endListener) {

 if (this.onslidestart) cbeEval(this.onslidestart, this);
 this.stop = false;
 this.xA = parseInt(xRadius);
 this.yA = parseInt(yRadius);
 this.radiusInc = parseInt(radiusInc);
 this.slideTime = parseInt(totalTime);
 startAngle = cbeRadians(parseFloat(startAngle));
 stopAngle = cbeRadians(parseFloat(stopAngle));
 if (endListener && window.cbeEventJsLoaded) {
   this.autoRemoveListener = true;
   this.addEventListener("slideend", endListener);
 }
 var startTime = (startAngle * this.slideTime) / (stopAngle - startAngle);
 this.stopTime = this.slideTime + startTime;
 this.B = (stopAngle - startAngle) / this.slideTime;
 this.xD = this.left() - Math.round(this.xA * Math.cos(this.B * startTime)); // center point
 this.yD = this.top() - Math.round(this.yA * Math.sin(this.B * startTime)); 
 this.xTarget = Math.round(this.xA * Math.cos(this.B * this.stopTime) + this.xD); // end point
 this.yTarget = Math.round(this.yA * Math.sin(this.B * this.stopTime) + this.yD); 
 var d = new Date();
 this.C = d.getTime() - startTime;
 if (!this.moving) this.ellipse1();

} CrossBrowserElement.prototype.ellipse1 = function() {

 var now, t, newY, newX;
 now = new Date();
 t = now.getTime() - this.C;
 if (this.stop) { this.moving = false; }
 else if (t < this.stopTime) {
   setTimeout("window.cbeAll["+this.index+"].ellipse1()", this.timeout);
   if (this.radiusInc) {
     this.xA += this.radiusInc;
     this.yA += this.radiusInc;
   }
   newX = Math.round(this.xA * Math.cos(this.B * t) + this.xD);
   newY = Math.round(this.yA * Math.sin(this.B * t) + this.yD);
   if (this.onslide) cbeEval(this.onslide, this, newX, newY, t);
   this.moveTo(newX, newY);
   this.moving = true;
 }  
 else {
   if (this.radiusInc) {
     this.xTarget = Math.round(this.xA * Math.cos(this.B * this.slideTime) + this.xD);
     this.yTarget = Math.round(this.yA * Math.sin(this.B * this.slideTime) + this.yD); 
   }
   this.moveTo(this.xTarget, this.yTarget);
   this.moving = false;
   if (this.onslideend) {
     var tmp = this.onslideend;
     if (this.autoRemoveListener && window.cbeEventJsLoaded) {
       this.autoRemoveListener = false;
       this.removeEventListener("slideend");
     }
     cbeEval(tmp, this);
   }
 }  

} CrossBrowserElement.prototype.stopSlide = function() { this.stop = true; } CrossBrowserElement.prototype.startSequence = function(uIndex) {

 if (!this.moving) {
   if (!uIndex) this.seqIndex = 0;
   else this.seqIndex = uIndex;
   this.addEventListener("slideEnd", cbeSlideSequence);
   cbeSlideSequence(this);
 }

} CrossBrowserElement.prototype.stopSequence = function() {

 this.stop=true;
 this.removeEventListener("slideEnd", cbeSlideSequence);

} function cbeSlideSequence(cbe) {

 var
   pw = cbe.parentNode.width(),
   ph = cbe.parentNode.height(),
   w = cbe.width(),
   h = cbe.height();
 if (cbe.seqIndex >= cbe.sequence.length) cbe.seqIndex = 0;
 eval("cbe."+cbe.sequence[cbe.seqIndex++]);

} var cbeSlideRateLinear=0, cbeSlideRateSine=1, cbeSlideRateCosine=2; CrossBrowserElement.prototype.slideRate = cbeSlideRateSine; CrossBrowserElement.prototype.seqIndex = 0; CrossBrowserElement.prototype.radiusInc = 0; CrossBrowserElement.prototype.t = 0; CrossBrowserElement.prototype.xTarget = 0; CrossBrowserElement.prototype.yTarget = 0; CrossBrowserElement.prototype.slideTime = 1000; CrossBrowserElement.prototype.xA = 0; CrossBrowserElement.prototype.yA = 0; CrossBrowserElement.prototype.xD = 0; CrossBrowserElement.prototype.yD = 0; CrossBrowserElement.prototype.B = 0; CrossBrowserElement.prototype.C = 0; CrossBrowserElement.prototype.moving = false; CrossBrowserElement.prototype.stop = true; CrossBrowserElement.prototype.timeout = 35; CrossBrowserElement.prototype.autoRemoveListener = false; CrossBrowserElement.prototype.onslidestart = null; CrossBrowserElement.prototype.onslide = null; CrossBrowserElement.prototype.onslideend = null; var cbeSlideJsLoaded = true; // End cbe_slide.js </script>

<script type="text/javascript" > /* cbe_util.js $Revision: 0.14 $

* CBE v4.19, Cross-Browser DHTML API from Cross-Browser.ru
* Copyright (c) 2002 Michael Foster (mike@cross-browser.ru)
* Distributed under the terms of the GNU LGPL from gnu.org
  • /

// visit function returns: 0 == stop, 1 == continue, 2 == skip subtree function cbeTraverseTree(order, startNode, visitFunction, data) {

 cbeTraversePreOrder(startNode, 0, 0, visitFunction, data);

} function cbeTraversePreOrder(node, level, branch, vFn, data) {

 var ret = vFn(node,level,branch,data);
 if (!ret) return 0;
 if (ret == 1 && node.firstChild) {
   var child = node.firstChild;
   while (child) {
     if (!level) ++branch;
     if (!cbeTraversePreOrder(child,level+1,branch,vFn,data)) return 1;
     child = child.nextSibling;
   }
 }
 return 1;

} var cbeImageCount=0; var cbeImageObj = new Array(); var cbeImageName = new Array(); function cbeNewImage(imgName, imgUrl, imgWidth, imgHeight) {

 var imgObj;
 if (arguments.length == 4) imgObj = new Image(imgWidth,imgHeight);
 else imgObj = new Image();
 imgObj.src = imgUrl;
 imgObj.id = imgObj.name = imgName;
 cbeImageObj[cbeImageCount] = imgObj;
 cbeImageName[cbeImageCount++] = imgName;
 return imgObj;

} function cbeSetImage(tagImg, preloadedImg) {

 var t, p;
 if (typeof(tagImg)=="string") t = cbeGetImageByName(tagImg);
 else t = tagImg;
 if (typeof(preloadedImg)=="string") p = cbeGetImageByName(preloadedImg);
 else p = preloadedImg;
 t.src = p.src;

} function cbeGetImageByName(imgName) {

 var i, j;
 if (document.images[imgName]) return document.images[imgName];
 if (is.nav4) {
   for (i = 0; i < cbeAll.length; i++) {
     if (cbeAll[i].ele.document) {
       for (j = 0; j < cbeAll[i].ele.document.images.length; j++) {
         if (imgName == cbeAll[i].ele.document.images[j].name) return cbeAll[i].ele.document.images[j];
       }
     }
   }
 }
 for (i = 0; i < cbeImageName.length; i++) {
   if (cbeImageName[i] == imgName) return cbeImageObj[i];
 }
 return null;

} function cbeGetFormByName(frmName) {

 var i, j;
 if (document.forms[frmName]) return document.forms[frmName];
 if (is.nav4) {
   for (i = 0; i < cbeAll.length; i++) {
     if (cbeAll[i].ele.document) {
       for (j = 0; j < cbeAll[i].ele.document.forms.length; j++) {
         if (frmName == cbeAll[i].ele.document.forms[j].name) return cbeAll[i].ele.document.forms[j];
       }
     }
   }
 }
 return null;

} // cookie implementations based on code from Netscape Javascript Guide function cbeSetCookie(name, value, expire, path) {

 document.cookie = name + "=" + escape(value) + ((!expire) ? "" : ("; expires=" + expire.toGMTString())) + "; path=/";

} function cbeGetCookie(name) {

 var value=null, search=name+"=";
 if (document.cookie.length > 0) {
   var offset = document.cookie.indexOf(search);
   if (offset != -1) {
     offset += search.length;
     var end = document.cookie.indexOf(";", offset);
     if (end == -1) end = document.cookie.length;
     value = unescape(document.cookie.substring(offset, end));
   }
 }
 return value;

} function cbeGetURLArguments() {

 var idx = location.href.indexOf("?");
 var params = new Array();
 if (idx != -1) {
   var pairs = location.href.substring(idx+1, location.href.length).split("&");
   for (var i=0; i<pairs.length; i++) {
     nameVal = pairs[i].split("=");
     params[i] = nameVal[1];
     params[nameVal[0]] = nameVal[1];
   }
 }
 return params;

} function cbePad(str, finalLen, padChar, left) {

 if (left) { for (var i=str.length; i<finalLen; ++i) str = padChar + str; }
 else { for (var i=str.length; i<finalLen; ++i) str += padChar; }
 return str;

} function cbeHexString(n, digits, prefix) {

 var p = "", n = Math.ceil(n);
 if (prefix) p = prefix;
 n = n.toString(16);
 for (var i=0; i < digits - n.length; ++i) {
   p += "0"; 
 }
 return p + n;

} function cbeRadians(deg) { return deg * (Math.PI / 180); } function cbeDegrees(rad) { return rad * (180 / Math.PI); } function cbeAddDragResizeListener(cbe) {

 cbe.addEventListener("dragStart", cbeDragResizeStartListener);
 cbe.addEventListener("drag", cbeDragResizeListener);

} function cbeRemoveDragResizeListener(cbe) {

 cbe.removeEventListener("dragStart", cbeDragResizeStartListener);
 cbe.removeEventListener("drag", cbeDragResizeListener);

} function cbeDragResizeStartListener(e) {

 if (e.offsetX > (e.cbeCurrentTarget.width() - 20) && e.offsetY > (e.cbeCurrentTarget.height() - 20)) {
   e.cbeCurrentTarget.isResizing = true;
 }
 else e.cbeCurrentTarget.isResizing = false;

} function cbeDragResizeListener(e) {

 if (e.cbeCurrentTarget.isResizing) e.cbeCurrentTarget.resizeBy(e.dx, e.dy);
 else e.cbeCurrentTarget.moveBy(e.dx, e.dy);

} var cbeUtilJsLoaded = true; // End cbe_util.js </script>

<script type="text/javascript" > var now = new Date(); var currYear,currMonth; var i,j,currDateObj,firstDay,daysInMonth,sevenDayRows; var DHTMLC, prev, curr, next, moniker; var months = new Array("January","February","March","April","May","June","July","August","September","October","November","December"); var days = new Array("Sunday","Monday","Tuesday","Wednesday","Thursday","Friday","Saturday"); /* 1. Is Cookie set?

 YES: Retrieve and set currMonth & currYear to the values stored in Cookie
 NO: Set currMonth & currYear to now and set Cookie

2. CBE will automatically call windowOnLoad() which, in turn, will...

a. Create the CrossBrowserElement objects.
b. Call Calendar() which will...
 i. Calculate the calendar info: firstDay, daysInMonth, sevenDayRows.
 ii. Determine nextMonth, nextYear, prevMonth, & prevYear.
 iii. Call cbeTraverseTree() with a reference to drawCalendar() which will...
  * Populate the innerHTML for each object in the CBE Object Tree.
  • /

// For simplicity"s sake: Include the equal sign in the cookie"s name var cookieName = "ISO8601="; if (document.cookie.indexOf(cookieName) != -1) {

 // Retrieve the stored date to set the global variables (used to generate the calender)
 start = document.cookie.indexOf(cookieName) + cookieName.length;  
 end = document.cookie.indexOf(";",start);
 if (end == -1) end = document.cookie.length;
 ISO8601 = document.cookie.substring(start,end);
 currDate = ISO8601.split("-");
 currYear  = currDate[0];
 currMonth  = currDate[1];

} else {

 // Use the present date to set the global variables (used to generate the calender)
 currYear  = now.getYear();
 currMonth  = now.getMonth();
 // Some browsers may not be Y2K compliant...
 if (currYear < 1900) currYear += 1900;

} function Calendar(Month,Year) {

 currDateObj  = new Date(Year,Month,1);
 // Update the global variables (used to generate the calender)
 currMonth  = Month;
 currYear  = Year;
 
 // Perform the basic calculations necessary to generate a calendar
 firstDay  = currDateObj.getDay();  // The day-of-the-week of the first day of the month;
 daysInMonth  = 32 - new Date(Year,Month,32).getDate();
 sevenDayRows = Math.ceil((firstDay + daysInMonth) / 7);
 
 switch (Month) {
 case 0:
   nextMonth  = Month + 1;
   nextYear  = Year;
   prevMonth  = 11;
   prevYear  = Year - 1;
   break;
 
 case 11:
   nextMonth  = 0;
   nextYear  = Year + 1;
   prevMonth  = Month - 1;
   prevYear  = Year;
   break;
 
 default:
   nextMonth  = Month + 1;
   nextYear  = Year;
   prevMonth  = Month - 1;
   prevYear  = Year;
   break;
 }
 
 i = 0; j = 1;
 cbeTraverseTree("preorder",DHTMLC,drawCalendar);
 DHTMLC.resizeTo(230, sevenDayRows * 20 + 60);
 moniker.top(sevenDayRows * 20 + 50);
 prev.innerHtml("<A HREF="javascript:Calendar(prevMonth,prevYear);">" + months[prevMonth].substr(0,3) + "</A>");
 curr.innerHtml(months[Month] + ", " + Year);
 next.innerHtml("<A HREF="javascript:Calendar(nextMonth,nextYear);">" + months[nextMonth].substr(0,3) + "</A>");

} function drawCalendar(node,level,branch) {

 var HREF;
 if (level == 2 && branch > 2) {
   if (i >= firstDay && j <= daysInMonth) {
     HREF = "javascript:void(document.forms[0].elements[0].value=\"" + (currMonth + 1) + "/" + j + "/" + currYear + "\")";
     node.innerHtml("<A HREF="" + HREF + "">" + j++ + "</A>");
     node.innerHtml();node.show();
   } else {
     node.hide();
   }
   i++;
 }
 return true;

} var clicked, displaying; var buttons, button1, button2, button3, button4, button5; var page, wii, htui, will, htgi, wywn; var cover; function createSlides(node,level,branch) {

 if (level == 1) {
   with(node) {
     node.moveTo(0,450);
     node.sizeTo(550,420);
   }
 }
 return true;

} function resetButtonColors(node,level,branch) {

 if (node.id == "badge1") return true;
 if (level == 1) node.background("#ccffcc");
 return true;

} function mouseOverListener(e) {

 if (e.cbeCurrentTarget.id == clicked) return true;
 e.cbeCurrentTarget.background("#99ff99");

} function mouseOutListener(e) {

 if (e.cbeCurrentTarget.id == clicked) return true;
 e.cbeCurrentTarget.background("#ccffcc");

} function onClickListener(e) {

 cbeTraverseTree("preorder",buttons,resetButtonColors);
 e.cbeCurrentTarget.background("#ffffff");
 clicked = e.cbeCurrentTarget.id;
 if (displaying) eval(displaying).slideTo(0,450,1500);
 switch(e.cbeCurrentTarget.id) {
 case "button1": displaying = "wii";  wii.slideTo(0,0,1500);  break;
 case "button2": displaying = "will"; will.slideTo(0,0,1500); break;
 case "button3": displaying = "wywn"; wywn.slideTo(0,0,1500); break;
 case "button4": displaying = "htgi"; htgi.slideTo(0,0,1500); break;
 case "button5": displaying = "htui"; htui.slideTo(0,0,1500); break;
 }

} function windowOnload() {

 page  = cbeGetElementById("page").cbe;
 page.sizeTo(570,450);
 page.clip("auto");
 if (is.ie4up) page.left(171);
 cbeTraverseTree("preorder",page,createSlides);
 // These references will be accessed by eval"ing their names in onClickListener()
 wii  = cbeGetElementById("wii").cbe;
 htui  = cbeGetElementById("htui").cbe;
 will  = cbeGetElementById("will").cbe;
 htgi  = cbeGetElementById("htgi").cbe;
 wywn  = cbeGetElementById("wywn").cbe;
 buttons = cbeGetElementById("buttons").cbe;
 button1 = cbeGetElementById("button1").cbe;
 button1.addEventListener("mouseOver",mouseOverListener);
 button1.addEventListener("mouseOut",mouseOutListener);
 button1.addEventListener("click",onClickListener);
 button2 = cbeGetElementById("button2").cbe;
 button2.addEventListener("mouseOver",mouseOverListener);
 button2.addEventListener("mouseOut",mouseOutListener);
 button2.addEventListener("click",onClickListener);
 button3 = cbeGetElementById("button3").cbe;
 button3.addEventListener("mouseOver",mouseOverListener);
 button3.addEventListener("mouseOut",mouseOutListener);
 button3.addEventListener("click",onClickListener);
 button4 = cbeGetElementById("button4").cbe;
 button4.addEventListener("mouseOver",mouseOverListener);
 button4.addEventListener("mouseOut",mouseOutListener);
 button4.addEventListener("click",onClickListener);
 button5 = cbeGetElementById("button5").cbe;
 button5.addEventListener("mouseOver",mouseOverListener);
 button5.addEventListener("mouseOut",mouseOutListener);
 button5.addEventListener("click",onClickListener);
 cover  = cbeGetElementById("cover").cbe;
 cover.sizeTo(570,450);
 cover.hide();
 DHTMLC  = cbeGetElementById("DHTMLC").cbe;
 prev  = cbeGetElementById("prev").cbe;
 curr  = cbeGetElementById("curr").cbe;
 next  = cbeGetElementById("next").cbe;
 moniker  = cbeGetElementById("moniker").cbe;
 Calendar(currMonth,currYear);
 DHTMLC.clip("auto");
 DHTMLC.show();

}

</script> </head> <body>

First Item
Second Item
Third
Fourth
Fifth

First Item

Content

Content

  • 1
  • 2
<a href="javascript:void(document.forms[0].elements[0].value="8/1/2005")">1</a>
<a href="javascript:void(document.forms[0].elements[0].value="8/2/2005")">2</a>
<a href="javascript:void(document.forms[0].elements[0].value="8/3/2005")">3</a>
<a href="javascript:void(document.forms[0].elements[0].value="8/4/2005")">4</a>
<a href="javascript:void(document.forms[0].elements[0].value="8/5/2005")">5</a>
<a href="javascript:void(document.forms[0].elements[0].value="8/6/2005")">6</a>
<a href="javascript:void(document.forms[0].elements[0].value="8/7/2005")">7</a>
<a href="javascript:void(document.forms[0].elements[0].value="8/8/2005")">8</a>
<a href="javascript:void(document.forms[0].elements[0].value="8/9/2005")">9</a>
<a href="javascript:void(document.forms[0].elements[0].value="8/10/2005")">10</a>
<a href="javascript:void(document.forms[0].elements[0].value="8/11/2005")">11</a>
<a href="javascript:void(document.forms[0].elements[0].value="8/12/2005")">12</a>
<a href="javascript:void(document.forms[0].elements[0].value="8/13/2005")">13</a>
<a href="javascript:void(document.forms[0].elements[0].value="8/14/2005")">14</a>
<a href="javascript:void(document.forms[0].elements[0].value="8/15/2005")">15</a>
<a href="javascript:void(document.forms[0].elements[0].value="8/16/2005")">16</a>
<a href="javascript:void(document.forms[0].elements[0].value="8/17/2005")">17</a>
<a href="javascript:void(document.forms[0].elements[0].value="8/18/2005")">18</a>
<a href="javascript:void(document.forms[0].elements[0].value="8/19/2005")">19</a>
<a href="javascript:void(document.forms[0].elements[0].value="8/20/2005")">20</a>
<a href="javascript:void(document.forms[0].elements[0].value="8/21/2005")">21</a>
<a href="javascript:void(document.forms[0].elements[0].value="8/22/2005")">22</a>
<a href="javascript:void(document.forms[0].elements[0].value="8/23/2005")">23</a>
<a href="javascript:void(document.forms[0].elements[0].value="8/24/2005")">24</a>
<a href="javascript:void(document.forms[0].elements[0].value="8/25/2005")">25</a>
<a href="javascript:void(document.forms[0].elements[0].value="8/26/2005")">26</a>
<a href="javascript:void(document.forms[0].elements[0].value="8/27/2005")">27</a>
<a href="javascript:void(document.forms[0].elements[0].value="8/28/2005")">28</a>
<a href="javascript:void(document.forms[0].elements[0].value="8/29/2005")">29</a>
<a href="javascript:void(document.forms[0].elements[0].value="8/30/2005")">30</a>
<a href="javascript:void(document.forms[0].elements[0].value="8/31/2005")">31</a>
   <form>You selected...<input size="10" type="text"></form>

2

LIne

  1. C -
  2. w s.
  3. days - T

3

.

  1. The DHTML Calendar files:
    1. ,
    2. d
    3. .
  2. d
    1. cbe_core.js, and
    2. cbe_util.js.

H

e

  1. via HTTP, or
  2. via </a>.

T

H

A

  1. R
  2. R
  3. U
  4. E
  5. I
  6. I
  7. n.

</body></html>


 </source>
   
  


Calendar: Multiple day selection

   <source lang="html4strict">

<html> <head>

 <title>Sample for the multiple dates feature</title>
 
 <style rel="stylesheet" type="text/css" media="all" title="win2k-cold-1">

/* The main calendar widget. DIV containing a table. */ .calendar {

 position: relative;
 display: none;
 border-top: 2px solid #fff;
 border-right: 2px solid #000;
 border-bottom: 2px solid #000;
 border-left: 2px solid #fff;
 font-size: 11px;
 color: #000;
 cursor: default;
 background: #c8d0d4;
 font-family: tahoma,verdana,sans-serif;

} .calendar table {

 border-top: 1px solid #000;
 border-right: 1px solid #fff;
 border-bottom: 1px solid #fff;
 border-left: 1px solid #000;
 font-size: 11px;
 color: #000;
 cursor: default;
 background: #c8d0d4;
 font-family: tahoma,verdana,sans-serif;

} /* Header part -- contains navigation buttons and day names. */ .calendar .button { /* "<<", "<", ">", ">>" buttons have this class */

 text-align: center;
 padding: 1px;
 border-top: 1px solid #fff;
 border-right: 1px solid #000;
 border-bottom: 1px solid #000;
 border-left: 1px solid #fff;

} .calendar .nav {

 background: transparent url(menuarrow.gif) no-repeat 100% 100%;

} .calendar thead .title { /* This holds the current "month, year" */

 font-weight: bold;
 padding: 1px;
 border: 1px solid #000;
 background: #788084;
 color: #fff;
 text-align: center;

} .calendar thead .headrow { /* Row <TR> containing navigation buttons */ } .calendar thead .daynames { /* Row <TR> containing the day names */ } .calendar thead .name { /* Cells <TD> containing the day names */

 border-bottom: 1px solid #000;
 padding: 2px;
 text-align: center;
 background: #e8f0f4;

} .calendar thead .weekend { /* How a weekend day name shows in header */

 color: #f00;

} .calendar thead .hilite { /* How do the buttons in header appear when hover */

 border-top: 2px solid #fff;
 border-right: 2px solid #000;
 border-bottom: 2px solid #000;
 border-left: 2px solid #fff;
 padding: 0px;
 background-color: #d8e0e4;

} .calendar thead .active { /* Active (pressed) buttons in header */

 padding: 2px 0px 0px 2px;
 border-top: 1px solid #000;
 border-right: 1px solid #fff;
 border-bottom: 1px solid #fff;
 border-left: 1px solid #000;
 background-color: #b8c0c4;

} /* The body part -- contains all the days in month. */ .calendar tbody .day { /* Cells <TD> containing month days dates */

 width: 2em;
 text-align: right;
 padding: 2px 4px 2px 2px;

} .calendar tbody .day.othermonth {

 font-size: 80%;
 color: #aaa;

} .calendar tbody .day.othermonth.oweekend {

 color: #faa;

} .calendar table .wn {

 padding: 2px 3px 2px 2px;
 border-right: 1px solid #000;
 background: #e8f4f0;

} .calendar tbody .rowhilite td {

 background: #d8e4e0;

} .calendar tbody .rowhilite td.wn {

 background: #c8d4d0;

} .calendar tbody td.hilite { /* Hovered cells <TD> */

 padding: 1px 3px 1px 1px;
 border: 1px solid;
 border-color: #fff #000 #000 #fff;

} .calendar tbody td.active { /* Active (pressed) cells <TD> */

 padding: 2px 2px 0px 2px;
 border: 1px solid;
 border-color: #000 #fff #fff #000;

} .calendar tbody td.selected { /* Cell showing selected date */

 font-weight: bold;
 padding: 2px 2px 0px 2px;
 border: 1px solid;
 border-color: #000 #fff #fff #000;
 background: #d8e0e4;

} .calendar tbody td.weekend { /* Cells showing weekend days */

 color: #f00;

} .calendar tbody td.today { /* Cell showing today date */

 font-weight: bold;
 color: #00f;

} .calendar tbody .disabled { color: #999; } .calendar tbody .emptycell { /* Empty cells (the best is to hide them) */

 visibility: hidden;

} .calendar tbody .emptyrow { /* Empty row (some months need less than 6 rows) */

 display: none;

} /* The footer part -- status bar and "Close" button */ .calendar tfoot .footrow { /* The <TR> in footer (only one right now) */ } .calendar tfoot .ttip { /* Tooltip (status bar) cell <TD> */

 background: #e8f0f4;
 padding: 1px;
 border: 1px solid #000;
 background: #788084;
 color: #fff;
 text-align: center;

} .calendar tfoot .hilite { /* Hover style for buttons in footer */

 border-top: 1px solid #fff;
 border-right: 1px solid #000;
 border-bottom: 1px solid #000;
 border-left: 1px solid #fff;
 padding: 1px;
 background: #d8e0e4;

} .calendar tfoot .active { /* Active (pressed) style for buttons in footer */

 padding: 2px 0px 0px 2px;
 border-top: 1px solid #000;
 border-right: 1px solid #fff;
 border-bottom: 1px solid #fff;
 border-left: 1px solid #000;

} /* Combo boxes (menus that display months/years for direct selection) */ .calendar .rubo {

 position: absolute;
 display: none;
 width: 4em;
 top: 0px;
 left: 0px;
 cursor: default;
 border-top: 1px solid #fff;
 border-right: 1px solid #000;
 border-bottom: 1px solid #000;
 border-left: 1px solid #fff;
 background: #d8e0e4;
 font-size: 90%;
 padding: 1px;
 z-index: 100;

} .calendar .rubo .label, .calendar .rubo .label-IEfix {

 text-align: center;
 padding: 1px;

} .calendar .rubo .label-IEfix {

 width: 4em;

} .calendar .rubo .active {

 background: #c8d0d4;
 padding: 0px;
 border-top: 1px solid #000;
 border-right: 1px solid #fff;
 border-bottom: 1px solid #fff;
 border-left: 1px solid #000;

} .calendar .rubo .hilite {

 background: #048;
 color: #aef;

} .calendar td.time {

 border-top: 1px solid #000;
 padding: 1px 0px;
 text-align: center;
 background-color: #e8f0f4;

} .calendar td.time .hour, .calendar td.time .minute, .calendar td.time .ampm {

 padding: 0px 3px 0px 4px;
 border: 1px solid #889;
 font-weight: bold;
 background-color: #fff;

} .calendar td.time .ampm {

 text-align: center;

} .calendar td.time .colon {

 padding: 0px 2px 0px 3px;
 font-weight: bold;

} .calendar td.time span.hilite {

 border-color: #000;
 background-color: #667;
 color: #fff;

} .calendar td.time span.active {

 border-color: #f00;
 background-color: #000;
 color: #0f0;

}

 </style>
 
 <script type="text/javascript">

/* Copyright Mihai Bazon, 2002-2005 | www.bazon.net/mishoo

* -----------------------------------------------------------
*
* The DHTML Calendar, version 1.0 "It is happening again"
*
* Details and latest version at:
* www.dynarch.ru/projects/calendar
*
* This script is developed by Dynarch.ru.  Visit us at www.dynarch.ru.
*
* This script is distributed under the GNU Lesser General Public License.
* Read the entire license text here: http://www.gnu.org/licenses/lgpl.html
*/

// $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;
 // HTML elements
 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;
 // Information
 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;
   // 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;
 }

}; // ** constants /// "static", needed for event handlers. Calendar._C = null; /// detect a special case of "web browser" Calendar.is_ie = ( /msie/i.test(navigator.userAgent) &&

      !/opera/i.test(navigator.userAgent) );

Calendar.is_ie5 = ( Calendar.is_ie && /msie 5\.0/i.test(navigator.userAgent) ); /// detect Opera browser Calendar.is_opera = /opera/i.test(navigator.userAgent); /// detect KHTML-based browsers Calendar.is_khtml = /Konqueror|Safari|KHTML/i.test(navigator.userAgent); // 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;

}; // 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;

}; // END: UTILITY FUNCTIONS // 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";
 }

}; // 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);
 }

}; /**

*  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;
   // 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 <mihai_bazon@yahoo.ru> to get it into the distribution  ;-)\n\n" +
         "Thank you!\n" +
         "http://dynarch.ru/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 // BEGIN: CALENDAR OBJECT FUNCTIONS /**

*  This function creates the calendar inside the given parent.  If _par is
*  null than it creates a popup calendar inside the BODY element.  If _par is
*  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 = "
" + text + "
";
   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("×", 1, 200).ttip = Calendar._TT["CLOSE"];
 }
 row = Calendar.createElement("tr", thead);
 row.className = "headrow";
 this._nav_py = hh("«", 1, -2);
 this._nav_py.ttip = Calendar._TT["PREV_YEAR"];
 this._nav_pm = hh("‹", 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_nm = hh("›", 1, 1);
 this._nav_nm.ttip = Calendar._TT["NEXT_MONTH"];
 this._nav_ny = hh("»", 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"] || " ";
   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 = " ";
     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);

}; /** 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);

}; /**

*  (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 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 = " ";
         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";

}; 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);
 }

}; /**

*  Refreshes the calendar.  Useful if the "disabledHandler" function is
*  dynamic, meaning that the list of disabled date can change at runtime.
*  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);

}; /** Modifies the "firstDayOfWeek" parameter (pass 0 for Synday, 1 for Monday, etc.). */ Calendar.prototype.setFirstDayOfWeek = function (firstDayOfWeek) {

 this._init(firstDayOfWeek, this.date);
 this._displayWeekdays();

}; /**

*  Allows customization of what dates are enabled.  The "unaryFunction"
*  parameter must be a function object that receives the date (as a JS Date
*  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;

}; /** Customization of allowed year range for the calendar. */ 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));
 }

}; /** Calls the second user handler (closeHandler). */ 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;

}; /**

*  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);

}; // 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);
 }

}; /** 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();

}; /**

*  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();

}; /**

*  Shows the calendar at a given absolute position (beware that, depending on
*  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();

}; /** 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);
   }
   // 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
   }
   // 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();

}; /** Customizes the date format. */ Calendar.prototype.setDateFormat = function (str) {

 this.dateFormat = str;

}; /** Customizes the tooltip date format. */ 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";
     }
   }
 }

}; /** Internal function; it displays the bar with the names of the weekday. */ Calendar.prototype._displayWeekdays = function () {

 var fdow = this.firstDayOfWeek;
 var cell = this.firstdayname;
 var weekend = Calendar._TT["WEEKEND"];
 for (var i = 0; i < 7; ++i) {
   cell.className = "day name";
   var realday = (i + fdow) % 7;
   if (i) {
     cell.ttip = Calendar._TT["DAY_FIRST"].replace("%s", Calendar._DN[realday]);
     cell.navtype = 100;
     cell.calendar = this;
     cell.fdow = realday;
     Calendar._add_evs(cell);
   }
   if (weekend.indexOf(realday.toString()) != -1) {
     Calendar.addClass(cell, "weekend");
   }
   cell.innerHTML = Calendar._SDN[(i + fdow) % 7];
   cell = cell.nextSibling;
 }

}; /** Internal function. Hides all combo boxes that might be displayed. */ Calendar.prototype._hideCombos = function () {

 this.monthsCombo.style.display = "none";
 this.yearsCombo.style.display = "none";

}; /** Internal function. Starts dragging the element. */ Calendar.prototype._dragStart = function (ev) {

 if (this.dragging) {
   return;
 }
 this.dragging = true;
 var posX;
 var posY;
 if (Calendar.is_ie) {
   posY = window.event.clientY + document.body.scrollTop;
   posX = window.event.clientX + document.body.scrollLeft;
 } else {
   posY = ev.clientY + window.scrollY;
   posX = ev.clientX + window.scrollX;
 }
 var st = this.element.style;
 this.xOffs = posX - parseInt(st.left);
 this.yOffs = posY - parseInt(st.top);
 with (Calendar) {
   addEvent(document, "mousemove", calDragIt);
   addEvent(document, "mouseup", calDragEnd);
 }

}; // BEGIN: DATE OBJECT PATCHES /** Adds the number of days array to the Date object. */ Date._MD = new Array(31,28,31,30,31,30,31,31,30,31,30,31); /** Constants used for time computations */ Date.SECOND = 1000 /* milliseconds */; Date.MINUTE = 60 * Date.SECOND; Date.HOUR = 60 * Date.MINUTE; Date.DAY = 24 * Date.HOUR; Date.WEEK = 7 * Date.DAY; Date.parseDate = function(str, fmt) {

 var today = new Date();
 var y = 0;
 var m = -1;
 var d = 0;
 var a = str.split(/\W+/);
 var b = fmt.match(/%./g);
 var i = 0, j = 0;
 var hr = 0;
 var min = 0;
 for (i = 0; i < a.length; ++i) {
   if (!a[i])
     continue;
   switch (b[i]) {
       case "%d":
       case "%e":
     d = parseInt(a[i], 10);
     break;
       case "%m":
     m = parseInt(a[i], 10) - 1;
     break;
       case "%Y":
       case "%y":
     y = parseInt(a[i], 10);
     (y < 100) && (y += (y > 29) ? 1900 : 2000);
     break;
       case "%b":
       case "%B":
     for (j = 0; j < 12; ++j) {
       if (Calendar._MN[j].substr(0, a[i].length).toLowerCase() == a[i].toLowerCase()) { m = j; break; }
     }
     break;
       case "%H":
       case "%I":
       case "%k":
       case "%l":
     hr = parseInt(a[i], 10);
     break;
       case "%P":
       case "%p":
     if (/pm/i.test(a[i]) && hr < 12)
       hr += 12;
     else if (/am/i.test(a[i]) && hr >= 12)
       hr -= 12;
     break;
       case "%M":
     min = parseInt(a[i], 10);
     break;
   }
 }
 if (isNaN(y)) y = today.getFullYear();
 if (isNaN(m)) m = today.getMonth();
 if (isNaN(d)) d = today.getDate();
 if (isNaN(hr)) hr = today.getHours();
 if (isNaN(min)) min = today.getMinutes();
 if (y != 0 && m != -1 && d != 0)
   return new Date(y, m, d, hr, min, 0);
 y = 0; m = -1; d = 0;
 for (i = 0; i < a.length; ++i) {
   if (a[i].search(/[a-zA-Z]+/) != -1) {
     var t = -1;
     for (j = 0; j < 12; ++j) {
       if (Calendar._MN[j].substr(0, a[i].length).toLowerCase() == a[i].toLowerCase()) { t = j; break; }
     }
     if (t != -1) {
       if (m != -1) {
         d = m+1;
       }
       m = t;
     }
   } else if (parseInt(a[i], 10) <= 12 && m == -1) {
     m = a[i]-1;
   } else if (parseInt(a[i], 10) > 31 && y == 0) {
     y = parseInt(a[i], 10);
     (y < 100) && (y += (y > 29) ? 1900 : 2000);
   } else if (d == 0) {
     d = a[i];
   }
 }
 if (y == 0)
   y = today.getFullYear();
 if (m != -1 && d != 0)
   return new Date(y, m, d, hr, min, 0);
 return today;

}; /** Returns the number of days in the current month */ Date.prototype.getMonthDays = function(month) {

 var year = this.getFullYear();
 if (typeof month == "undefined") {
   month = this.getMonth();
 }
 if (((0 == (year%4)) && ( (0 != (year%100)) || (0 == (year%400)))) && month == 1) {
   return 29;
 } else {
   return Date._MD[month];
 }

}; /** Returns the number of day in the year. */ Date.prototype.getDayOfYear = function() {

 var now = new Date(this.getFullYear(), this.getMonth(), this.getDate(), 0, 0, 0);
 var then = new Date(this.getFullYear(), 0, 0, 0, 0, 0);
 var time = now - then;
 return Math.floor(time / Date.DAY);

}; /** Returns the number of the week in year, as defined in ISO 8601. */ Date.prototype.getWeekNumber = function() {

 var d = new Date(this.getFullYear(), this.getMonth(), this.getDate(), 0, 0, 0);
 var DoW = d.getDay();
 d.setDate(d.getDate() - (DoW + 6) % 7 + 3); // Nearest Thu
 var ms = d.valueOf(); // GMT
 d.setMonth(0);
 d.setDate(4); // Thu in Week 1
 return Math.round((ms - d.valueOf()) / (7 * 864e5)) + 1;

}; /** Checks date and time equality */ Date.prototype.equalsTo = function(date) {

 return ((this.getFullYear() == date.getFullYear()) &&
   (this.getMonth() == date.getMonth()) &&
   (this.getDate() == date.getDate()) &&
   (this.getHours() == date.getHours()) &&
   (this.getMinutes() == date.getMinutes()));

}; /** Set only the year, month, date parts (keep existing time) */ Date.prototype.setDateOnly = function(date) {

 var tmp = new Date(date);
 this.setDate(1);
 this.setFullYear(tmp.getFullYear());
 this.setMonth(tmp.getMonth());
 this.setDate(tmp.getDate());

}; /** Prints the date in a string according to the given format. */ Date.prototype.print = function (str) {

 var m = this.getMonth();
 var d = this.getDate();
 var y = this.getFullYear();
 var wn = this.getWeekNumber();
 var w = this.getDay();
 var s = {};
 var hr = this.getHours();
 var pm = (hr >= 12);
 var ir = (pm) ? (hr - 12) : hr;
 var dy = this.getDayOfYear();
 if (ir == 0)
   ir = 12;
 var min = this.getMinutes();
 var sec = this.getSeconds();
 s["%a"] = Calendar._SDN[w]; // abbreviated weekday name [FIXME: I18N]
 s["%A"] = Calendar._DN[w]; // full weekday name
 s["%b"] = Calendar._SMN[m]; // abbreviated month name [FIXME: I18N]
 s["%B"] = Calendar._MN[m]; // full month name
 // FIXME: %c : preferred date and time representation for the current locale
 s["%C"] = 1 + Math.floor(y / 100); // the century number
 s["%d"] = (d < 10) ? ("0" + d) : d; // the day of the month (range 01 to 31)
 s["%e"] = d; // the day of the month (range 1 to 31)
 // FIXME: %D : american date style: %m/%d/%y
 // FIXME: %E, %F, %G, %g, %h (man strftime)
 s["%H"] = (hr < 10) ? ("0" + hr) : hr; // hour, range 00 to 23 (24h format)
 s["%I"] = (ir < 10) ? ("0" + ir) : ir; // hour, range 01 to 12 (12h format)
 s["%j"] = (dy < 100) ? ((dy < 10) ? ("00" + dy) : ("0" + dy)) : dy; // day of the year (range 001 to 366)
 s["%k"] = hr;    // hour, range 0 to 23 (24h format)
 s["%l"] = ir;    // hour, range 1 to 12 (12h format)
 s["%m"] = (m < 9) ? ("0" + (1+m)) : (1+m); // month, range 01 to 12
 s["%M"] = (min < 10) ? ("0" + min) : min; // minute, range 00 to 59
 s["%n"] = "\n";    // a newline character
 s["%p"] = pm ? "PM" : "AM";
 s["%P"] = pm ? "pm" : "am";
 // FIXME: %r : the time in am/pm notation %I:%M:%S %p
 // FIXME: %R : the time in 24-hour notation %H:%M
 s["%s"] = Math.floor(this.getTime() / 1000);
 s["%S"] = (sec < 10) ? ("0" + sec) : sec; // seconds, range 00 to 59
 s["%t"] = "\t";    // a tab character
 // FIXME: %T : the time in 24-hour notation (%H:%M:%S)
 s["%U"] = s["%W"] = s["%V"] = (wn < 10) ? ("0" + wn) : wn;
 s["%u"] = w + 1;  // the day of the week (range 1 to 7, 1 = MON)
 s["%w"] = w;    // the day of the week (range 0 to 6, 0 = SUN)
 // FIXME: %x : preferred date representation for the current locale without the time
 // FIXME: %X : preferred time representation for the current locale without the date
 s["%y"] = ("" + y).substr(2, 2); // year without the century (range 00 to 99)
 s["%Y"] = y;    // year with the century
 s["%%"] = "%";    // a literal "%" character
 var re = /%./g;
 if (!Calendar.is_ie5 && !Calendar.is_khtml)
   return str.replace(re, function (par) { return s[par] || par; });
 var a = str.match(re);
 for (var i = 0; i < a.length; i++) {
   var tmp = s[a[i]];
   if (tmp) {
     re = new RegExp(a[i], "g");
     str = str.replace(re, tmp);
   }
 }
 return str;

}; Date.prototype.__msh_oldSetFullYear = Date.prototype.setFullYear; Date.prototype.setFullYear = function(y) {

 var d = new Date(this);
 d.__msh_oldSetFullYear(y);
 if (d.getMonth() != this.getMonth())
   this.setDate(28);
 this.__msh_oldSetFullYear(y);

}; // END: DATE OBJECT PATCHES

// global object that remembers the calendar window._dynarch_popupCalendar = null;

 </script>
 
 <script type="text/javascript">

// ** I18N // Calendar EN language // Author: Mihai Bazon, <mihai_bazon@yahoo.ru> // Encoding: any // Distributed under the same terms as the calendar itself. // For translators: please use UTF-8 if possible. We strongly believe that // Unicode is the answer to a real internationalized world. Also please // include your contact information in the header, as can be seen above. // full day names Calendar._DN = new Array ("Sunday",

"Monday",
"Tuesday",
"Wednesday",
"Thursday",
"Friday",
"Saturday",
"Sunday");

// Please note that the following array of short day names (and the same goes // for short month names, _SMN) isn"t absolutely necessary. We give it here // for exemplification on how one can customize the short day names, but if // they are simply the first N letters of the full name you can simply say: // // Calendar._SDN_len = N; // short day name length // Calendar._SMN_len = N; // short month name length // // If N = 3 then this is not needed either since we assume a value of 3 if not // present, to be compatible with translation files that were written before // this feature. // short day names Calendar._SDN = new Array ("Sun",

"Mon",
"Tue",
"Wed",
"Thu",
"Fri",
"Sat",
"Sun");

// First day of the week. "0" means display Sunday first, "1" means display // Monday first, etc. Calendar._FD = 0; // full month names Calendar._MN = new Array ("January",

"February",
"March",
"April",
"May",
"June",
"July",
"August",
"September",
"October",
"November",
"December");

// short month names Calendar._SMN = new Array ("Jan",

"Feb",
"Mar",
"Apr",
"May",
"Jun",
"Jul",
"Aug",
"Sep",
"Oct",
"Nov",
"Dec");

// tooltips Calendar._TT = {}; Calendar._TT["INFO"] = "About the calendar"; Calendar._TT["ABOUT"] = "DHTML Date/Time Selector\n" + "(c) dynarch.ru 2002-2005 / Author: Mihai Bazon\n" + // don"t translate this this ;-) "For latest version visit: http://www.dynarch.ru/projects/calendar/\n" + "Distributed under GNU LGPL. See http://gnu.org/licenses/lgpl.html for details." + "\n\n" + "Date selection:\n" + "- Use the \xab, \xbb buttons to select year\n" + "- Use the " + String.fromCharCode(0x2039) + ", " + String.fromCharCode(0x203a) + " buttons to select month\n" + "- Hold mouse button on any of the above buttons for faster selection."; Calendar._TT["ABOUT_TIME"] = "\n\n" + "Time selection:\n" + "- Click on any of the time parts to increase it\n" + "- or Shift-click to decrease it\n" + "- or click and drag for faster selection."; Calendar._TT["PREV_YEAR"] = "Prev. year (hold for menu)"; Calendar._TT["PREV_MONTH"] = "Prev. month (hold for menu)"; Calendar._TT["GO_TODAY"] = "Go Today"; Calendar._TT["NEXT_MONTH"] = "Next month (hold for menu)"; Calendar._TT["NEXT_YEAR"] = "Next year (hold for menu)"; Calendar._TT["SEL_DATE"] = "Select date"; Calendar._TT["DRAG_TO_MOVE"] = "Drag to move"; Calendar._TT["PART_TODAY"] = " (today)"; // the following is to inform that "%s" is to be the first day of week // %s will be replaced with the day name. Calendar._TT["DAY_FIRST"] = "Display %s first"; // This may be locale-dependent. It specifies the week-end days, as an array // of comma-separated numbers. The numbers are from 0 to 6: 0 means Sunday, 1 // means Monday, etc. Calendar._TT["WEEKEND"] = "0,6"; Calendar._TT["CLOSE"] = "Close"; Calendar._TT["TODAY"] = "Today"; Calendar._TT["TIME_PART"] = "(Shift-)Click or drag to change value"; // date formats Calendar._TT["DEF_DATE_FORMAT"] = "%Y-%m-%d"; Calendar._TT["TT_DATE_FORMAT"] = "%a, %b %e"; Calendar._TT["WK"] = "wk"; Calendar._TT["TIME"] = "Time:";

 </script>
 
 <script type="text/javascript">

/* Copyright Mihai Bazon, 2002, 2003 | http://dynarch.ru/mishoo/

* ---------------------------------------------------------------------------
*
* The DHTML Calendar
*
* Details and latest version at:
* http://dynarch.ru/mishoo/calendar.epl
*
* This script is distributed under the GNU Lesser General Public License.
* Read the entire license text here: http://www.gnu.org/licenses/lgpl.html
*
* This file defines helper functions for setting up the calendar.  They are
* intended to help non-programmers get a working calendar on their site
* quickly.  This script should not be seen as part of the calendar.  It just
* shows you what one can do with the calendar, while in the same time
* providing a quick and simple method for setting it up.  If you need
* exhaustive customization of the calendar creation process feel free to
* modify this code to suit your needs (this is recommended and much better
* than modifying calendar.js itself).
*/

// $Id: calendar-setup.js,v 1.25 2005/03/07 09:51:33 mishoo Exp $ /**

*  This function "patches" an input field (or other element) to use a calendar
*  widget for date selection.
*
*  The "params" is a single object that can have the following properties:
*
*    prop. name   | description
*  -------------------------------------------------------------------------------------------------
*   inputField    | the ID of an input field to store the date
*   displayArea   | the ID of a DIV or other element to show the date
*   button        | ID of a button or other element that will trigger the calendar
*   eventName     | event that will trigger the calendar, without the "on" prefix (default: "click")
*   ifFormat      | date format that will be stored in the input field
*   daFormat      | the date format that will be used to display the date in displayArea
*   singleClick   | (true/false) wether the calendar is in single click mode or not (default: true)
*   firstDay      | numeric: 0 to 6.  "0" means display Sunday first, "1" means display Monday first, etc.
*   align         | alignment (default: "Br"); if you don"t know what"s this see the calendar documentation
*   range         | array with 2 elements.  Default: [1900, 2999] -- the range of years available
*   weekNumbers   | (true/false) if it"s true (default) the calendar will display week numbers
*   flat          | null or element ID; if not null the calendar will be a flat calendar having the parent with the given ID
*   flatCallback  | function that receives a JS Date object and returns an URL to point the browser to (for flat calendar)
*   disableFunc   | function that receives a JS Date object and should return true if that date has to be disabled in the calendar
*   onSelect      | function that gets called when a date is selected.  You don"t _have_ to supply this (the default is generally okay)
*   onClose       | function that gets called when the calendar is closed.  [default]
*   onUpdate      | function that gets called after the date is updated in the input field.  Receives a reference to the calendar.
*   date          | the date that the calendar will be initially displayed to
*   showsTime     | default: false; if true the calendar will include a time selector
*   timeFormat    | the time format; can be "12" or "24", default is "12"
*   electric      | if true (default) then given fields/date areas are updated for each move; otherwise they"re updated only on close
*   step          | configures the step of the years in drop-down boxes; default: 2
*   position      | configures the calendar absolute position; default: null
*   cache         | if "true" (but default: "false") it will reuse the same calendar object, where possible
*   showOthers    | if "true" (but default: "false") it will show days from other months too
*
*  None of them is required, they all have default values.  However, if you
*  pass none of "inputField", "displayArea" or "button" you"ll get a warning
*  saying "nothing to setup".
*/

Calendar.setup = function (params) {

 function param_default(pname, def) { if (typeof params[pname] == "undefined") { params[pname] = def; } };
 param_default("inputField",     null);
 param_default("displayArea",    null);
 param_default("button",         null);
 param_default("eventName",      "click");
 param_default("ifFormat",       "%Y/%m/%d");
 param_default("daFormat",       "%Y/%m/%d");
 param_default("singleClick",    true);
 param_default("disableFunc",    null);
 param_default("dateStatusFunc", params["disableFunc"]);  // takes precedence if both are defined
 param_default("dateText",       null);
 param_default("firstDay",       null);
 param_default("align",          "Br");
 param_default("range",          [1900, 2999]);
 param_default("weekNumbers",    true);
 param_default("flat",           null);
 param_default("flatCallback",   null);
 param_default("onSelect",       null);
 param_default("onClose",        null);
 param_default("onUpdate",       null);
 param_default("date",           null);
 param_default("showsTime",      false);
 param_default("timeFormat",     "24");
 param_default("electric",       true);
 param_default("step",           2);
 param_default("position",       null);
 param_default("cache",          false);
 param_default("showOthers",     false);
 param_default("multiple",       null);
 var tmp = ["inputField", "displayArea", "button"];
 for (var i in tmp) {
   if (typeof params[tmp[i]] == "string") {
     params[tmp[i]] = document.getElementById(params[tmp[i]]);
   }
 }
 if (!(params.flat || params.multiple || params.inputField || params.displayArea || params.button)) {
   alert("Calendar.setup:\n  Nothing to setup (no fields found).  Please check your code");
   return false;
 }
 function onSelect(cal) {
   var p = cal.params;
   var update = (cal.dateClicked || p.electric);
   if (update && p.inputField) {
     p.inputField.value = cal.date.print(p.ifFormat);
     if (typeof p.inputField.onchange == "function")
       p.inputField.onchange();
   }
   if (update && p.displayArea)
     p.displayArea.innerHTML = cal.date.print(p.daFormat);
   if (update && typeof p.onUpdate == "function")
     p.onUpdate(cal);
   if (update && p.flat) {
     if (typeof p.flatCallback == "function")
       p.flatCallback(cal);
   }
   if (update && p.singleClick && cal.dateClicked)
     cal.callCloseHandler();
 };
 if (params.flat != null) {
   if (typeof params.flat == "string")
     params.flat = document.getElementById(params.flat);
   if (!params.flat) {
     alert("Calendar.setup:\n  Flat specified but can"t find parent.");
     return false;
   }
   var cal = new Calendar(params.firstDay, params.date, params.onSelect || onSelect);
   cal.showsOtherMonths = params.showOthers;
   cal.showsTime = params.showsTime;
   cal.time24 = (params.timeFormat == "24");
   cal.params = params;
   cal.weekNumbers = params.weekNumbers;
   cal.setRange(params.range[0], params.range[1]);
   cal.setDateStatusHandler(params.dateStatusFunc);
   cal.getDateText = params.dateText;
   if (params.ifFormat) {
     cal.setDateFormat(params.ifFormat);
   }
   if (params.inputField && typeof params.inputField.value == "string") {
     cal.parseDate(params.inputField.value);
   }
   cal.create(params.flat);
   cal.show();
   return false;
 }
 var triggerEl = params.button || params.displayArea || params.inputField;
 triggerEl["on" + params.eventName] = function() {
   var dateEl = params.inputField || params.displayArea;
   var dateFmt = params.inputField ? params.ifFormat : params.daFormat;
   var mustCreate = false;
   var cal = window.calendar;
   if (dateEl)
     params.date = Date.parseDate(dateEl.value || dateEl.innerHTML, dateFmt);
   if (!(cal && params.cache)) {
     window.calendar = cal = new Calendar(params.firstDay,
                  params.date,
                  params.onSelect || onSelect,
                  params.onClose || function(cal) { cal.hide(); });
     cal.showsTime = params.showsTime;
     cal.time24 = (params.timeFormat == "24");
     cal.weekNumbers = params.weekNumbers;
     mustCreate = true;
   } else {
     if (params.date)
       cal.setDate(params.date);
     cal.hide();
   }
   if (params.multiple) {
     cal.multiple = {};
     for (var i = params.multiple.length; --i >= 0;) {
       var d = params.multiple[i];
       var ds = d.print("%Y%m%d");
       cal.multiple[ds] = d;
     }
   }
   cal.showsOtherMonths = params.showOthers;
   cal.yearStep = params.step;
   cal.setRange(params.range[0], params.range[1]);
   cal.params = params;
   cal.setDateStatusHandler(params.dateStatusFunc);
   cal.getDateText = params.dateText;
   cal.setDateFormat(dateFmt);
   if (mustCreate)
     cal.create();
   cal.refresh();
   if (!params.position)
     cal.showAtElement(params.button || params.displayArea || params.inputField, params.align);
   else
     cal.showAt(params.position[0], params.position[1]);
   return false;
 };
 return cal;

};

 </script>

</head> <body>

Sample for the multiple dates feature

Starting version 0.9.7, the calendar is able to handle multiple dates selection, in either flat or popup form. For this to happen one needs to pass the "multiple: true" parameter to Calendar.setup and to install an onUpdate handler that watches for modifications.

 <a id="trigger" href="#">[open calendar...]</a>
 <script type="text/javascript">
 //
   // the default multiple dates selected, first time the calendar is instantiated
   var MA = [];
   function closed(cal) {
     // here we"ll write the output; this is only for example.  You
     // will normally fill an input field or something with the dates.
     var el = document.getElementById("output");
     // reset initial content.
     el.innerHTML = "";
     // Reset the "MA", in case one triggers the calendar again.
     // CAREFUL!  You don"t want to do "MA = [];".  We need to modify
     // the value of the current array, instead of creating a new one.
     // Calendar.setup is called only once! :-)  So be careful.
     MA.length = 0;
     // walk the calendar"s multiple dates selection hash
     for (var i in cal.multiple) {
       var d = cal.multiple[i];
       // sometimes the date is not actually selected, that"s why we need to check.
       if (d) {
         // OK, selected.  Fill an input field.  Or something.  Just for example,
         // we will display all selected dates in the element having the id "output".
         el.innerHTML += d.print("%A, %Y %B %d") + "
"; // and push it in the "MA", in case one triggers the calendar again. MA[MA.length] = d; } } cal.hide(); return true; }; Calendar.setup({ align  : "BR", showOthers : true, multiple  : MA, // pass the initial or computed array of multiple dates to be initially selected onClose  : closed, button  : "trigger" }); </script>

<address><a href="http://dynarch.ru/mishoo/">mishoo</a></address>

Last modified: Thu Mar  3 20:17:42 EET 2005 

</body> </html>


 </source>
   
  

<A href="http://www.wbex.ru/Code/JavaScriptDownload/jscalendar-1.0.zip">jscalendar-1.0.zip( 396 k)</a>


Calendar: special day

   <source lang="html4strict">

<html> <head> <meta http-equiv="content-type" content="text/xml; charset=utf-8" /> <title>Simple calendar setup [flat calendar]</title>


 <style rel="stylesheet" type="text/css" media="all" title="win2k-cold-1">

/* The main calendar widget. DIV containing a table. */ .calendar {

 position: relative;
 display: none;
 border-top: 2px solid #fff;
 border-right: 2px solid #000;
 border-bottom: 2px solid #000;
 border-left: 2px solid #fff;
 font-size: 11px;
 color: #000;
 cursor: default;
 background: #c8d0d4;
 font-family: tahoma,verdana,sans-serif;

} .calendar table {

 border-top: 1px solid #000;
 border-right: 1px solid #fff;
 border-bottom: 1px solid #fff;
 border-left: 1px solid #000;
 font-size: 11px;
 color: #000;
 cursor: default;
 background: #c8d0d4;
 font-family: tahoma,verdana,sans-serif;

} /* Header part -- contains navigation buttons and day names. */ .calendar .button { /* "<<", "<", ">", ">>" buttons have this class */

 text-align: center;
 padding: 1px;
 border-top: 1px solid #fff;
 border-right: 1px solid #000;
 border-bottom: 1px solid #000;
 border-left: 1px solid #fff;

} .calendar .nav {

 background: transparent url(menuarrow.gif) no-repeat 100% 100%;

} .calendar thead .title { /* This holds the current "month, year" */

 font-weight: bold;
 padding: 1px;
 border: 1px solid #000;
 background: #788084;
 color: #fff;
 text-align: center;

} .calendar thead .headrow { /* Row <TR> containing navigation buttons */ } .calendar thead .daynames { /* Row <TR> containing the day names */ } .calendar thead .name { /* Cells <TD> containing the day names */

 border-bottom: 1px solid #000;
 padding: 2px;
 text-align: center;
 background: #e8f0f4;

} .calendar thead .weekend { /* How a weekend day name shows in header */

 color: #f00;

} .calendar thead .hilite { /* How do the buttons in header appear when hover */

 border-top: 2px solid #fff;
 border-right: 2px solid #000;
 border-bottom: 2px solid #000;
 border-left: 2px solid #fff;
 padding: 0px;
 background-color: #d8e0e4;

} .calendar thead .active { /* Active (pressed) buttons in header */

 padding: 2px 0px 0px 2px;
 border-top: 1px solid #000;
 border-right: 1px solid #fff;
 border-bottom: 1px solid #fff;
 border-left: 1px solid #000;
 background-color: #b8c0c4;

} /* The body part -- contains all the days in month. */ .calendar tbody .day { /* Cells <TD> containing month days dates */

 width: 2em;
 text-align: right;
 padding: 2px 4px 2px 2px;

} .calendar tbody .day.othermonth {

 font-size: 80%;
 color: #aaa;

} .calendar tbody .day.othermonth.oweekend {

 color: #faa;

} .calendar table .wn {

 padding: 2px 3px 2px 2px;
 border-right: 1px solid #000;
 background: #e8f4f0;

} .calendar tbody .rowhilite td {

 background: #d8e4e0;

} .calendar tbody .rowhilite td.wn {

 background: #c8d4d0;

} .calendar tbody td.hilite { /* Hovered cells <TD> */

 padding: 1px 3px 1px 1px;
 border: 1px solid;
 border-color: #fff #000 #000 #fff;

} .calendar tbody td.active { /* Active (pressed) cells <TD> */

 padding: 2px 2px 0px 2px;
 border: 1px solid;
 border-color: #000 #fff #fff #000;

} .calendar tbody td.selected { /* Cell showing selected date */

 font-weight: bold;
 padding: 2px 2px 0px 2px;
 border: 1px solid;
 border-color: #000 #fff #fff #000;
 background: #d8e0e4;

} .calendar tbody td.weekend { /* Cells showing weekend days */

 color: #f00;

} .calendar tbody td.today { /* Cell showing today date */

 font-weight: bold;
 color: #00f;

} .calendar tbody .disabled { color: #999; } .calendar tbody .emptycell { /* Empty cells (the best is to hide them) */

 visibility: hidden;

} .calendar tbody .emptyrow { /* Empty row (some months need less than 6 rows) */

 display: none;

} /* The footer part -- status bar and "Close" button */ .calendar tfoot .footrow { /* The <TR> in footer (only one right now) */ } .calendar tfoot .ttip { /* Tooltip (status bar) cell <TD> */

 background: #e8f0f4;
 padding: 1px;
 border: 1px solid #000;
 background: #788084;
 color: #fff;
 text-align: center;

} .calendar tfoot .hilite { /* Hover style for buttons in footer */

 border-top: 1px solid #fff;
 border-right: 1px solid #000;
 border-bottom: 1px solid #000;
 border-left: 1px solid #fff;
 padding: 1px;
 background: #d8e0e4;

} .calendar tfoot .active { /* Active (pressed) style for buttons in footer */

 padding: 2px 0px 0px 2px;
 border-top: 1px solid #000;
 border-right: 1px solid #fff;
 border-bottom: 1px solid #fff;
 border-left: 1px solid #000;

} /* Combo boxes (menus that display months/years for direct selection) */ .calendar .rubo {

 position: absolute;
 display: none;
 width: 4em;
 top: 0px;
 left: 0px;
 cursor: default;
 border-top: 1px solid #fff;
 border-right: 1px solid #000;
 border-bottom: 1px solid #000;
 border-left: 1px solid #fff;
 background: #d8e0e4;
 font-size: 90%;
 padding: 1px;
 z-index: 100;

} .calendar .rubo .label, .calendar .rubo .label-IEfix {

 text-align: center;
 padding: 1px;

} .calendar .rubo .label-IEfix {

 width: 4em;

} .calendar .rubo .active {

 background: #c8d0d4;
 padding: 0px;
 border-top: 1px solid #000;
 border-right: 1px solid #fff;
 border-bottom: 1px solid #fff;
 border-left: 1px solid #000;

} .calendar .rubo .hilite {

 background: #048;
 color: #aef;

} .calendar td.time {

 border-top: 1px solid #000;
 padding: 1px 0px;
 text-align: center;
 background-color: #e8f0f4;

} .calendar td.time .hour, .calendar td.time .minute, .calendar td.time .ampm {

 padding: 0px 3px 0px 4px;
 border: 1px solid #889;
 font-weight: bold;
 background-color: #fff;

} .calendar td.time .ampm {

 text-align: center;

} .calendar td.time .colon {

 padding: 0px 2px 0px 3px;
 font-weight: bold;

} .calendar td.time span.hilite {

 border-color: #000;
 background-color: #667;
 color: #fff;

} .calendar td.time span.active {

 border-color: #f00;
 background-color: #000;
 color: #0f0;

}

 </style>
 
 <script type="text/javascript">

/* Copyright Mihai Bazon, 2002-2005 | www.bazon.net/mishoo

* -----------------------------------------------------------
*
* The DHTML Calendar, version 1.0 "It is happening again"
*
* Details and latest version at:
* www.dynarch.ru/projects/calendar
*
* This script is developed by Dynarch.ru.  Visit us at www.dynarch.ru.
*
* This script is distributed under the GNU Lesser General Public License.
* Read the entire license text here: http://www.gnu.org/licenses/lgpl.html
*/

// $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;
 // HTML elements
 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;
 // Information
 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;
   // 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;
 }

}; // ** constants /// "static", needed for event handlers. Calendar._C = null; /// detect a special case of "web browser" Calendar.is_ie = ( /msie/i.test(navigator.userAgent) &&

      !/opera/i.test(navigator.userAgent) );

Calendar.is_ie5 = ( Calendar.is_ie && /msie 5\.0/i.test(navigator.userAgent) ); /// detect Opera browser Calendar.is_opera = /opera/i.test(navigator.userAgent); /// detect KHTML-based browsers Calendar.is_khtml = /Konqueror|Safari|KHTML/i.test(navigator.userAgent); // 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;

}; // 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;

}; // END: UTILITY FUNCTIONS // 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";
 }

}; // 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);
 }

}; /**

*  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;
   // 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 <mihai_bazon@yahoo.ru> to get it into the distribution  ;-)\n\n" +
         "Thank you!\n" +
         "http://dynarch.ru/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 // BEGIN: CALENDAR OBJECT FUNCTIONS /**

*  This function creates the calendar inside the given parent.  If _par is
*  null than it creates a popup calendar inside the BODY element.  If _par is
*  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 = "
" + text + "
";
   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("×", 1, 200).ttip = Calendar._TT["CLOSE"];
 }
 row = Calendar.createElement("tr", thead);
 row.className = "headrow";
 this._nav_py = hh("«", 1, -2);
 this._nav_py.ttip = Calendar._TT["PREV_YEAR"];
 this._nav_pm = hh("‹", 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_nm = hh("›", 1, 1);
 this._nav_nm.ttip = Calendar._TT["NEXT_MONTH"];
 this._nav_ny = hh("»", 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"] || " ";
   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 = " ";
     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);

}; /** 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);

}; /**

*  (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 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 = " ";
         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";

}; 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);
 }

}; /**

*  Refreshes the calendar.  Useful if the "disabledHandler" function is
*  dynamic, meaning that the list of disabled date can change at runtime.
*  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);

}; /** Modifies the "firstDayOfWeek" parameter (pass 0 for Synday, 1 for Monday, etc.). */ Calendar.prototype.setFirstDayOfWeek = function (firstDayOfWeek) {

 this._init(firstDayOfWeek, this.date);
 this._displayWeekdays();

}; /**

*  Allows customization of what dates are enabled.  The "unaryFunction"
*  parameter must be a function object that receives the date (as a JS Date
*  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;

}; /** Customization of allowed year range for the calendar. */ 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));
 }

}; /** Calls the second user handler (closeHandler). */ 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;

}; /**

*  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);

}; // 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);
 }

}; /** 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();

}; /**

*  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();

}; /**

*  Shows the calendar at a given absolute position (beware that, depending on
*  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();

}; /** 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);
   }
   // 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
   }
   // 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();

}; /** Customizes the date format. */ Calendar.prototype.setDateFormat = function (str) {

 this.dateFormat = str;

}; /** Customizes the tooltip date format. */ 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";
     }
   }
 }

}; /** Internal function; it displays the bar with the names of the weekday. */ Calendar.prototype._displayWeekdays = function () {

 var fdow = this.firstDayOfWeek;
 var cell = this.firstdayname;
 var weekend = Calendar._TT["WEEKEND"];
 for (var i = 0; i < 7; ++i) {
   cell.className = "day name";
   var realday = (i + fdow) % 7;
   if (i) {
     cell.ttip = Calendar._TT["DAY_FIRST"].replace("%s", Calendar._DN[realday]);
     cell.navtype = 100;
     cell.calendar = this;
     cell.fdow = realday;
     Calendar._add_evs(cell);
   }
   if (weekend.indexOf(realday.toString()) != -1) {
     Calendar.addClass(cell, "weekend");
   }
   cell.innerHTML = Calendar._SDN[(i + fdow) % 7];
   cell = cell.nextSibling;
 }

}; /** Internal function. Hides all combo boxes that might be displayed. */ Calendar.prototype._hideCombos = function () {

 this.monthsCombo.style.display = "none";
 this.yearsCombo.style.display = "none";

}; /** Internal function. Starts dragging the element. */ Calendar.prototype._dragStart = function (ev) {

 if (this.dragging) {
   return;
 }
 this.dragging = true;
 var posX;
 var posY;
 if (Calendar.is_ie) {
   posY = window.event.clientY + document.body.scrollTop;
   posX = window.event.clientX + document.body.scrollLeft;
 } else {
   posY = ev.clientY + window.scrollY;
   posX = ev.clientX + window.scrollX;
 }
 var st = this.element.style;
 this.xOffs = posX - parseInt(st.left);
 this.yOffs = posY - parseInt(st.top);
 with (Calendar) {
   addEvent(document, "mousemove", calDragIt);
   addEvent(document, "mouseup", calDragEnd);
 }

}; // BEGIN: DATE OBJECT PATCHES /** Adds the number of days array to the Date object. */ Date._MD = new Array(31,28,31,30,31,30,31,31,30,31,30,31); /** Constants used for time computations */ Date.SECOND = 1000 /* milliseconds */; Date.MINUTE = 60 * Date.SECOND; Date.HOUR = 60 * Date.MINUTE; Date.DAY = 24 * Date.HOUR; Date.WEEK = 7 * Date.DAY; Date.parseDate = function(str, fmt) {

 var today = new Date();
 var y = 0;
 var m = -1;
 var d = 0;
 var a = str.split(/\W+/);
 var b = fmt.match(/%./g);
 var i = 0, j = 0;
 var hr = 0;
 var min = 0;
 for (i = 0; i < a.length; ++i) {
   if (!a[i])
     continue;
   switch (b[i]) {
       case "%d":
       case "%e":
     d = parseInt(a[i], 10);
     break;
       case "%m":
     m = parseInt(a[i], 10) - 1;
     break;
       case "%Y":
       case "%y":
     y = parseInt(a[i], 10);
     (y < 100) && (y += (y > 29) ? 1900 : 2000);
     break;
       case "%b":
       case "%B":
     for (j = 0; j < 12; ++j) {
       if (Calendar._MN[j].substr(0, a[i].length).toLowerCase() == a[i].toLowerCase()) { m = j; break; }
     }
     break;
       case "%H":
       case "%I":
       case "%k":
       case "%l":
     hr = parseInt(a[i], 10);
     break;
       case "%P":
       case "%p":
     if (/pm/i.test(a[i]) && hr < 12)
       hr += 12;
     else if (/am/i.test(a[i]) && hr >= 12)
       hr -= 12;
     break;
       case "%M":
     min = parseInt(a[i], 10);
     break;
   }
 }
 if (isNaN(y)) y = today.getFullYear();
 if (isNaN(m)) m = today.getMonth();
 if (isNaN(d)) d = today.getDate();
 if (isNaN(hr)) hr = today.getHours();
 if (isNaN(min)) min = today.getMinutes();
 if (y != 0 && m != -1 && d != 0)
   return new Date(y, m, d, hr, min, 0);
 y = 0; m = -1; d = 0;
 for (i = 0; i < a.length; ++i) {
   if (a[i].search(/[a-zA-Z]+/) != -1) {
     var t = -1;
     for (j = 0; j < 12; ++j) {
       if (Calendar._MN[j].substr(0, a[i].length).toLowerCase() == a[i].toLowerCase()) { t = j; break; }
     }
     if (t != -1) {
       if (m != -1) {
         d = m+1;
       }
       m = t;
     }
   } else if (parseInt(a[i], 10) <= 12 && m == -1) {
     m = a[i]-1;
   } else if (parseInt(a[i], 10) > 31 && y == 0) {
     y = parseInt(a[i], 10);
     (y < 100) && (y += (y > 29) ? 1900 : 2000);
   } else if (d == 0) {
     d = a[i];
   }
 }
 if (y == 0)
   y = today.getFullYear();
 if (m != -1 && d != 0)
   return new Date(y, m, d, hr, min, 0);
 return today;

}; /** Returns the number of days in the current month */ Date.prototype.getMonthDays = function(month) {

 var year = this.getFullYear();
 if (typeof month == "undefined") {
   month = this.getMonth();
 }
 if (((0 == (year%4)) && ( (0 != (year%100)) || (0 == (year%400)))) && month == 1) {
   return 29;
 } else {
   return Date._MD[month];
 }

}; /** Returns the number of day in the year. */ Date.prototype.getDayOfYear = function() {

 var now = new Date(this.getFullYear(), this.getMonth(), this.getDate(), 0, 0, 0);
 var then = new Date(this.getFullYear(), 0, 0, 0, 0, 0);
 var time = now - then;
 return Math.floor(time / Date.DAY);

}; /** Returns the number of the week in year, as defined in ISO 8601. */ Date.prototype.getWeekNumber = function() {

 var d = new Date(this.getFullYear(), this.getMonth(), this.getDate(), 0, 0, 0);
 var DoW = d.getDay();
 d.setDate(d.getDate() - (DoW + 6) % 7 + 3); // Nearest Thu
 var ms = d.valueOf(); // GMT
 d.setMonth(0);
 d.setDate(4); // Thu in Week 1
 return Math.round((ms - d.valueOf()) / (7 * 864e5)) + 1;

}; /** Checks date and time equality */ Date.prototype.equalsTo = function(date) {

 return ((this.getFullYear() == date.getFullYear()) &&
   (this.getMonth() == date.getMonth()) &&
   (this.getDate() == date.getDate()) &&
   (this.getHours() == date.getHours()) &&
   (this.getMinutes() == date.getMinutes()));

}; /** Set only the year, month, date parts (keep existing time) */ Date.prototype.setDateOnly = function(date) {

 var tmp = new Date(date);
 this.setDate(1);
 this.setFullYear(tmp.getFullYear());
 this.setMonth(tmp.getMonth());
 this.setDate(tmp.getDate());

}; /** Prints the date in a string according to the given format. */ Date.prototype.print = function (str) {

 var m = this.getMonth();
 var d = this.getDate();
 var y = this.getFullYear();
 var wn = this.getWeekNumber();
 var w = this.getDay();
 var s = {};
 var hr = this.getHours();
 var pm = (hr >= 12);
 var ir = (pm) ? (hr - 12) : hr;
 var dy = this.getDayOfYear();
 if (ir == 0)
   ir = 12;
 var min = this.getMinutes();
 var sec = this.getSeconds();
 s["%a"] = Calendar._SDN[w]; // abbreviated weekday name [FIXME: I18N]
 s["%A"] = Calendar._DN[w]; // full weekday name
 s["%b"] = Calendar._SMN[m]; // abbreviated month name [FIXME: I18N]
 s["%B"] = Calendar._MN[m]; // full month name
 // FIXME: %c : preferred date and time representation for the current locale
 s["%C"] = 1 + Math.floor(y / 100); // the century number
 s["%d"] = (d < 10) ? ("0" + d) : d; // the day of the month (range 01 to 31)
 s["%e"] = d; // the day of the month (range 1 to 31)
 // FIXME: %D : american date style: %m/%d/%y
 // FIXME: %E, %F, %G, %g, %h (man strftime)
 s["%H"] = (hr < 10) ? ("0" + hr) : hr; // hour, range 00 to 23 (24h format)
 s["%I"] = (ir < 10) ? ("0" + ir) : ir; // hour, range 01 to 12 (12h format)
 s["%j"] = (dy < 100) ? ((dy < 10) ? ("00" + dy) : ("0" + dy)) : dy; // day of the year (range 001 to 366)
 s["%k"] = hr;    // hour, range 0 to 23 (24h format)
 s["%l"] = ir;    // hour, range 1 to 12 (12h format)
 s["%m"] = (m < 9) ? ("0" + (1+m)) : (1+m); // month, range 01 to 12
 s["%M"] = (min < 10) ? ("0" + min) : min; // minute, range 00 to 59
 s["%n"] = "\n";    // a newline character
 s["%p"] = pm ? "PM" : "AM";
 s["%P"] = pm ? "pm" : "am";
 // FIXME: %r : the time in am/pm notation %I:%M:%S %p
 // FIXME: %R : the time in 24-hour notation %H:%M
 s["%s"] = Math.floor(this.getTime() / 1000);
 s["%S"] = (sec < 10) ? ("0" + sec) : sec; // seconds, range 00 to 59
 s["%t"] = "\t";    // a tab character
 // FIXME: %T : the time in 24-hour notation (%H:%M:%S)
 s["%U"] = s["%W"] = s["%V"] = (wn < 10) ? ("0" + wn) : wn;
 s["%u"] = w + 1;  // the day of the week (range 1 to 7, 1 = MON)
 s["%w"] = w;    // the day of the week (range 0 to 6, 0 = SUN)
 // FIXME: %x : preferred date representation for the current locale without the time
 // FIXME: %X : preferred time representation for the current locale without the date
 s["%y"] = ("" + y).substr(2, 2); // year without the century (range 00 to 99)
 s["%Y"] = y;    // year with the century
 s["%%"] = "%";    // a literal "%" character
 var re = /%./g;
 if (!Calendar.is_ie5 && !Calendar.is_khtml)
   return str.replace(re, function (par) { return s[par] || par; });
 var a = str.match(re);
 for (var i = 0; i < a.length; i++) {
   var tmp = s[a[i]];
   if (tmp) {
     re = new RegExp(a[i], "g");
     str = str.replace(re, tmp);
   }
 }
 return str;

}; Date.prototype.__msh_oldSetFullYear = Date.prototype.setFullYear; Date.prototype.setFullYear = function(y) {

 var d = new Date(this);
 d.__msh_oldSetFullYear(y);
 if (d.getMonth() != this.getMonth())
   this.setDate(28);
 this.__msh_oldSetFullYear(y);

}; // END: DATE OBJECT PATCHES

// global object that remembers the calendar window._dynarch_popupCalendar = null;

 </script>
 
 <script type="text/javascript">

// ** I18N // Calendar EN language // Author: Mihai Bazon, <mihai_bazon@yahoo.ru> // Encoding: any // Distributed under the same terms as the calendar itself. // For translators: please use UTF-8 if possible. We strongly believe that // Unicode is the answer to a real internationalized world. Also please // include your contact information in the header, as can be seen above. // full day names Calendar._DN = new Array ("Sunday",

"Monday",
"Tuesday",
"Wednesday",
"Thursday",
"Friday",
"Saturday",
"Sunday");

// Please note that the following array of short day names (and the same goes // for short month names, _SMN) isn"t absolutely necessary. We give it here // for exemplification on how one can customize the short day names, but if // they are simply the first N letters of the full name you can simply say: // // Calendar._SDN_len = N; // short day name length // Calendar._SMN_len = N; // short month name length // // If N = 3 then this is not needed either since we assume a value of 3 if not // present, to be compatible with translation files that were written before // this feature. // short day names Calendar._SDN = new Array ("Sun",

"Mon",
"Tue",
"Wed",
"Thu",
"Fri",
"Sat",
"Sun");

// First day of the week. "0" means display Sunday first, "1" means display // Monday first, etc. Calendar._FD = 0; // full month names Calendar._MN = new Array ("January",

"February",
"March",
"April",
"May",
"June",
"July",
"August",
"September",
"October",
"November",
"December");

// short month names Calendar._SMN = new Array ("Jan",

"Feb",
"Mar",
"Apr",
"May",
"Jun",
"Jul",
"Aug",
"Sep",
"Oct",
"Nov",
"Dec");

// tooltips Calendar._TT = {}; Calendar._TT["INFO"] = "About the calendar"; Calendar._TT["ABOUT"] = "DHTML Date/Time Selector\n" + "(c) dynarch.ru 2002-2005 / Author: Mihai Bazon\n" + // don"t translate this this ;-) "For latest version visit: http://www.dynarch.ru/projects/calendar/\n" + "Distributed under GNU LGPL. See http://gnu.org/licenses/lgpl.html for details." + "\n\n" + "Date selection:\n" + "- Use the \xab, \xbb buttons to select year\n" + "- Use the " + String.fromCharCode(0x2039) + ", " + String.fromCharCode(0x203a) + " buttons to select month\n" + "- Hold mouse button on any of the above buttons for faster selection."; Calendar._TT["ABOUT_TIME"] = "\n\n" + "Time selection:\n" + "- Click on any of the time parts to increase it\n" + "- or Shift-click to decrease it\n" + "- or click and drag for faster selection."; Calendar._TT["PREV_YEAR"] = "Prev. year (hold for menu)"; Calendar._TT["PREV_MONTH"] = "Prev. month (hold for menu)"; Calendar._TT["GO_TODAY"] = "Go Today"; Calendar._TT["NEXT_MONTH"] = "Next month (hold for menu)"; Calendar._TT["NEXT_YEAR"] = "Next year (hold for menu)"; Calendar._TT["SEL_DATE"] = "Select date"; Calendar._TT["DRAG_TO_MOVE"] = "Drag to move"; Calendar._TT["PART_TODAY"] = " (today)"; // the following is to inform that "%s" is to be the first day of week // %s will be replaced with the day name. Calendar._TT["DAY_FIRST"] = "Display %s first"; // This may be locale-dependent. It specifies the week-end days, as an array // of comma-separated numbers. The numbers are from 0 to 6: 0 means Sunday, 1 // means Monday, etc. Calendar._TT["WEEKEND"] = "0,6"; Calendar._TT["CLOSE"] = "Close"; Calendar._TT["TODAY"] = "Today"; Calendar._TT["TIME_PART"] = "(Shift-)Click or drag to change value"; // date formats Calendar._TT["DEF_DATE_FORMAT"] = "%Y-%m-%d"; Calendar._TT["TT_DATE_FORMAT"] = "%a, %b %e"; Calendar._TT["WK"] = "wk"; Calendar._TT["TIME"] = "Time:";

 </script>
 
 <script type="text/javascript">

/* Copyright Mihai Bazon, 2002, 2003 | http://dynarch.ru/mishoo/

* ---------------------------------------------------------------------------
*
* The DHTML Calendar
*
* Details and latest version at:
* http://dynarch.ru/mishoo/calendar.epl
*
* This script is distributed under the GNU Lesser General Public License.
* Read the entire license text here: http://www.gnu.org/licenses/lgpl.html
*
* This file defines helper functions for setting up the calendar.  They are
* intended to help non-programmers get a working calendar on their site
* quickly.  This script should not be seen as part of the calendar.  It just
* shows you what one can do with the calendar, while in the same time
* providing a quick and simple method for setting it up.  If you need
* exhaustive customization of the calendar creation process feel free to
* modify this code to suit your needs (this is recommended and much better
* than modifying calendar.js itself).
*/

// $Id: calendar-setup.js,v 1.25 2005/03/07 09:51:33 mishoo Exp $ /**

*  This function "patches" an input field (or other element) to use a calendar
*  widget for date selection.
*
*  The "params" is a single object that can have the following properties:
*
*    prop. name   | description
*  -------------------------------------------------------------------------------------------------
*   inputField    | the ID of an input field to store the date
*   displayArea   | the ID of a DIV or other element to show the date
*   button        | ID of a button or other element that will trigger the calendar
*   eventName     | event that will trigger the calendar, without the "on" prefix (default: "click")
*   ifFormat      | date format that will be stored in the input field
*   daFormat      | the date format that will be used to display the date in displayArea
*   singleClick   | (true/false) wether the calendar is in single click mode or not (default: true)
*   firstDay      | numeric: 0 to 6.  "0" means display Sunday first, "1" means display Monday first, etc.
*   align         | alignment (default: "Br"); if you don"t know what"s this see the calendar documentation
*   range         | array with 2 elements.  Default: [1900, 2999] -- the range of years available
*   weekNumbers   | (true/false) if it"s true (default) the calendar will display week numbers
*   flat          | null or element ID; if not null the calendar will be a flat calendar having the parent with the given ID
*   flatCallback  | function that receives a JS Date object and returns an URL to point the browser to (for flat calendar)
*   disableFunc   | function that receives a JS Date object and should return true if that date has to be disabled in the calendar
*   onSelect      | function that gets called when a date is selected.  You don"t _have_ to supply this (the default is generally okay)
*   onClose       | function that gets called when the calendar is closed.  [default]
*   onUpdate      | function that gets called after the date is updated in the input field.  Receives a reference to the calendar.
*   date          | the date that the calendar will be initially displayed to
*   showsTime     | default: false; if true the calendar will include a time selector
*   timeFormat    | the time format; can be "12" or "24", default is "12"
*   electric      | if true (default) then given fields/date areas are updated for each move; otherwise they"re updated only on close
*   step          | configures the step of the years in drop-down boxes; default: 2
*   position      | configures the calendar absolute position; default: null
*   cache         | if "true" (but default: "false") it will reuse the same calendar object, where possible
*   showOthers    | if "true" (but default: "false") it will show days from other months too
*
*  None of them is required, they all have default values.  However, if you
*  pass none of "inputField", "displayArea" or "button" you"ll get a warning
*  saying "nothing to setup".
*/

Calendar.setup = function (params) {

 function param_default(pname, def) { if (typeof params[pname] == "undefined") { params[pname] = def; } };
 param_default("inputField",     null);
 param_default("displayArea",    null);
 param_default("button",         null);
 param_default("eventName",      "click");
 param_default("ifFormat",       "%Y/%m/%d");
 param_default("daFormat",       "%Y/%m/%d");
 param_default("singleClick",    true);
 param_default("disableFunc",    null);
 param_default("dateStatusFunc", params["disableFunc"]);  // takes precedence if both are defined
 param_default("dateText",       null);
 param_default("firstDay",       null);
 param_default("align",          "Br");
 param_default("range",          [1900, 2999]);
 param_default("weekNumbers",    true);
 param_default("flat",           null);
 param_default("flatCallback",   null);
 param_default("onSelect",       null);
 param_default("onClose",        null);
 param_default("onUpdate",       null);
 param_default("date",           null);
 param_default("showsTime",      false);
 param_default("timeFormat",     "24");
 param_default("electric",       true);
 param_default("step",           2);
 param_default("position",       null);
 param_default("cache",          false);
 param_default("showOthers",     false);
 param_default("multiple",       null);
 var tmp = ["inputField", "displayArea", "button"];
 for (var i in tmp) {
   if (typeof params[tmp[i]] == "string") {
     params[tmp[i]] = document.getElementById(params[tmp[i]]);
   }
 }
 if (!(params.flat || params.multiple || params.inputField || params.displayArea || params.button)) {
   alert("Calendar.setup:\n  Nothing to setup (no fields found).  Please check your code");
   return false;
 }
 function onSelect(cal) {
   var p = cal.params;
   var update = (cal.dateClicked || p.electric);
   if (update && p.inputField) {
     p.inputField.value = cal.date.print(p.ifFormat);
     if (typeof p.inputField.onchange == "function")
       p.inputField.onchange();
   }
   if (update && p.displayArea)
     p.displayArea.innerHTML = cal.date.print(p.daFormat);
   if (update && typeof p.onUpdate == "function")
     p.onUpdate(cal);
   if (update && p.flat) {
     if (typeof p.flatCallback == "function")
       p.flatCallback(cal);
   }
   if (update && p.singleClick && cal.dateClicked)
     cal.callCloseHandler();
 };
 if (params.flat != null) {
   if (typeof params.flat == "string")
     params.flat = document.getElementById(params.flat);
   if (!params.flat) {
     alert("Calendar.setup:\n  Flat specified but can"t find parent.");
     return false;
   }
   var cal = new Calendar(params.firstDay, params.date, params.onSelect || onSelect);
   cal.showsOtherMonths = params.showOthers;
   cal.showsTime = params.showsTime;
   cal.time24 = (params.timeFormat == "24");
   cal.params = params;
   cal.weekNumbers = params.weekNumbers;
   cal.setRange(params.range[0], params.range[1]);
   cal.setDateStatusHandler(params.dateStatusFunc);
   cal.getDateText = params.dateText;
   if (params.ifFormat) {
     cal.setDateFormat(params.ifFormat);
   }
   if (params.inputField && typeof params.inputField.value == "string") {
     cal.parseDate(params.inputField.value);
   }
   cal.create(params.flat);
   cal.show();
   return false;
 }
 var triggerEl = params.button || params.displayArea || params.inputField;
 triggerEl["on" + params.eventName] = function() {
   var dateEl = params.inputField || params.displayArea;
   var dateFmt = params.inputField ? params.ifFormat : params.daFormat;
   var mustCreate = false;
   var cal = window.calendar;
   if (dateEl)
     params.date = Date.parseDate(dateEl.value || dateEl.innerHTML, dateFmt);
   if (!(cal && params.cache)) {
     window.calendar = cal = new Calendar(params.firstDay,
                  params.date,
                  params.onSelect || onSelect,
                  params.onClose || function(cal) { cal.hide(); });
     cal.showsTime = params.showsTime;
     cal.time24 = (params.timeFormat == "24");
     cal.weekNumbers = params.weekNumbers;
     mustCreate = true;
   } else {
     if (params.date)
       cal.setDate(params.date);
     cal.hide();
   }
   if (params.multiple) {
     cal.multiple = {};
     for (var i = params.multiple.length; --i >= 0;) {
       var d = params.multiple[i];
       var ds = d.print("%Y%m%d");
       cal.multiple[ds] = d;
     }
   }
   cal.showsOtherMonths = params.showOthers;
   cal.yearStep = params.step;
   cal.setRange(params.range[0], params.range[1]);
   cal.params = params;
   cal.setDateStatusHandler(params.dateStatusFunc);
   cal.getDateText = params.dateText;
   cal.setDateFormat(dateFmt);
   if (mustCreate)
     cal.create();
   cal.refresh();
   if (!params.position)
     cal.showAtElement(params.button || params.displayArea || params.inputField, params.align);
   else
     cal.showAt(params.position[0], params.position[1]);
   return false;
 };
 return cal;

};

 </script>
   <style type="text/css">
     .special { background-color: #000; color: #fff; }
   </style>

</head> <body>

DHTML Calendar for the special day

This page demonstrates how to setup a flat calendar.

The code in this page uses a helper function defined in "calendar-setup.js". With it you can setup the calendar in minutes.


<script type="text/javascript">

 var SPECIAL_DAYS = {
   0 : [ 13, 24 ],    // special days in January
   2 : [ 1, 6, 8, 12, 18 ],  // special days in March
   8 : [ 21, 11 ]    // special days in September
 };
 function dateIsSpecial(year, month, day) {
   var m = SPECIAL_DAYS[month];
   if (!m) return false;
   for (var i in m) if (m[i] == day) return true;
   return false;
 };
 function dateChanged(calendar) {
   // Beware that this function is called even if the end-user only
   // changed the month/year.  In order to determine if a date was
   // clicked you can use the dateClicked property of the calendar:
   if (calendar.dateClicked) {
     // OK, a date was clicked, redirect to /yyyy/mm/dd/index.php
     var y = calendar.date.getFullYear();
     var m = calendar.date.getMonth();     // integer, 0..11
     var d = calendar.date.getDate();      // integer, 1..31
     // redirect...
     window.location = "/" + y + "/" + m + "/" + d + "/index.php";
   }
 };
 Calendar.setup(
   {
     flat         : "calendar-container", // ID of the parent element
     flatCallback : dateChanged,          // our callback function
     dateStatusFunc : function(date, y, m, d) {
                        if (dateIsSpecial(y, m, d)) return "special";
                        else return false; // other dates are enabled
                        // return true if you want to disable other dates
                      }
   }
 );

</script>

The positioning of the DIV that contains the calendar is entirely your job. For instance, the "calendar-container" DIV from this page has the following style: "float: right; margin-left: 1em; margin-bottom: 1em".

Following there is the code that has been used to create this calendar. You can find the full description of the Calendar.setup() function in the <a href="doc/html/reference.html">calendar documenation</a>.

<div style="float: right; margin-left: 1em; margin-bottom: 1em;"
id="calendar-container"></div>
<script type="text/javascript">
  function dateChanged(calendar) {
    // Beware that this function is called even if the end-user only
    // changed the month/year.  In order to determine if a date was
    // clicked you can use the dateClicked property of the calendar:
    if (calendar.dateClicked) {
      // OK, a date was clicked, redirect to /yyyy/mm/dd/index.php
      var y = calendar.date.getFullYear();
      var m = calendar.date.getMonth();     // integer, 0..11
      var d = calendar.date.getDate();      // integer, 1..31
      // redirect...
      window.location = "/" + y + "/" + m + "/" + d + "/index.php";
    }
  };
  Calendar.setup(
    {
      flat         : "calendar-container", // ID of the parent element
      flatCallback : dateChanged           // our callback function
    }
  );
</script>

</body> </html>


 </source>
   
  

<A href="http://www.wbex.ru/Code/JavaScriptDownload/jscalendar-1.0.zip">jscalendar-1.0.zip( 396 k)</a>


Calendar with different theme

   <source lang="html4strict">


<?xml version="1.0" encoding="utf-8"?> <!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Strict//EN" "http://www.w3.org/TR/xhtml1/DTD/xhtml1-strict.dtd"> <html>

<head> <meta http-equiv="content-type" content="text/xml; charset=utf-8" /> <title>The Coolest DHTML Calendar - Online Demo</title> <link rel="stylesheet" type="text/css" media="all" href="skins/aqua/theme.css" title="Aqua" /> <link rel="alternate stylesheet" type="text/css" media="all" href="calendar-blue.css" title="winter" /> <link rel="alternate stylesheet" type="text/css" media="all" href="calendar-blue2.css" title="blue" /> <link rel="alternate stylesheet" type="text/css" media="all" href="calendar-brown.css" title="summer" /> <link rel="alternate stylesheet" type="text/css" media="all" href="calendar-green.css" title="green" /> <link rel="alternate stylesheet" type="text/css" media="all" href="calendar-win2k-1.css" title="win2k-1" /> <link rel="alternate stylesheet" type="text/css" media="all" href="calendar-win2k-2.css" title="win2k-2" /> <link rel="alternate stylesheet" type="text/css" media="all" href="calendar-win2k-cold-1.css" title="win2k-cold-1" /> <link rel="alternate stylesheet" type="text/css" media="all" href="calendar-win2k-cold-2.css" title="win2k-cold-2" /> <link rel="alternate stylesheet" type="text/css" media="all" href="calendar-system.css" title="system" />

<script type="text/javascript" src="calendar.js"></script>

<script type="text/javascript" src="lang/calendar-en.js"></script>


<script type="text/javascript"> var oldLink = null; // code to change the active stylesheet function setActiveStyleSheet(link, title) {

 var i, a, main;
 for(i=0; (a = document.getElementsByTagName("link")[i]); i++) {
   if(a.getAttribute("rel").indexOf("style") != -1 && a.getAttribute("title")) {
     a.disabled = true;
     if(a.getAttribute("title") == title) a.disabled = false;
   }
 }
 if (oldLink) oldLink.style.fontWeight = "normal";
 oldLink = link;
 link.style.fontWeight = "bold";
 return false;

} // This function gets called when the end-user clicks on some date. function selected(cal, date) {

 cal.sel.value = date; // just update the date in the input field.
 if (cal.dateClicked && (cal.sel.id == "sel1" || cal.sel.id == "sel3"))
   // if we add this call we close the calendar on single-click.
   // just to exemplify both cases, we are using this only for the 1st
   // and the 3rd field, while 2nd and 4th will still require double-click.
   cal.callCloseHandler();

} // And this gets called when the end-user clicks on the _selected_ date, // or clicks on the "Close" button. It just hides the calendar without // destroying it. function closeHandler(cal) {

 cal.hide();                        // hide the calendar

// cal.destroy();

 _dynarch_popupCalendar = null;

} // This function shows the calendar under the element having the given id. // It takes care of catching "mousedown" signals on document and hiding the // calendar if the click was outside. function showCalendar(id, format, showsTime, showsOtherMonths) {

 var el = document.getElementById(id);
 if (_dynarch_popupCalendar != null) {
   // we already have some calendar created
   _dynarch_popupCalendar.hide();                 // so we hide it first.
 } else {
   // first-time call, create the calendar.
   var cal = new Calendar(1, null, selected, closeHandler);
   // uncomment the following line to hide the week numbers
   // cal.weekNumbers = false;
   if (typeof showsTime == "string") {
     cal.showsTime = true;
     cal.time24 = (showsTime == "24");
   }
   if (showsOtherMonths) {
     cal.showsOtherMonths = true;
   }
   _dynarch_popupCalendar = cal;                  // remember it in the global var
   cal.setRange(1900, 2070);        // min/max year allowed.
   cal.create();
 }
 _dynarch_popupCalendar.setDateFormat(format);    // set the specified date format
 _dynarch_popupCalendar.parseDate(el.value);      // try to parse the text in field
 _dynarch_popupCalendar.sel = el;                 // inform it what input field we use
 // the reference element that we pass to showAtElement is the button that
 // triggers the calendar.  In this example we align the calendar bottom-right
 // to the button.
 _dynarch_popupCalendar.showAtElement(el.nextSibling, "Br");        // show the calendar
 return false;

} var MINUTE = 60 * 1000; var HOUR = 60 * MINUTE; var DAY = 24 * HOUR; var WEEK = 7 * DAY; // If this handler returns true then the "date" given as // parameter will be disabled. In this example we enable // only days within a range of 10 days from the current // date. // You can use the functions date.getFullYear() -- returns the year // as 4 digit number, date.getMonth() -- returns the month as 0..11, // and date.getDate() -- returns the date of the month as 1..31, to // make heavy calculations here. However, beware that this function // should be very fast, as it is called for each day in a month when // the calendar is (re)constructed. function isDisabled(date) {

 var today = new Date();
 return (Math.abs(date.getTime() - today.getTime()) / DAY) > 10;

} function flatSelected(cal, date) {

 var el = document.getElementById("preview");
 el.innerHTML = date;

} function showFlatCalendar() {

 var parent = document.getElementById("display");
 // construct a calendar giving only the "selected" handler.
 var cal = new Calendar(0, null, flatSelected);
 // hide week numbers
 cal.weekNumbers = false;
 // We want some dates to be disabled; see function isDisabled above
 cal.setDisabledHandler(isDisabled);
 cal.setDateFormat("%A, %B %e");
 // this call must be the last as it might use data initialized above; if
 // we specify a parent, as opposite to the "showCalendar" function above,
 // then we create a flat calendar -- not popup.  Hidden, though, but...
 cal.create(parent);
 // ... we can show it here.
 cal.show();

} </script> <style type="text/css"> .ex { font-weight: bold; background: #fed; color: #080 } .help { color: #080; font-style: italic; } body { background: #fea; font: 10pt tahoma,verdana,sans-serif; } table { font: 13px verdana,tahoma,sans-serif; } a { color: #00f; } a:visited { color: #00f; } a:hover { color: #f00; background: #fefaf0; } a:active { color: #08f; } .key { border: 1px solid #000; background: #fff; color: #008; padding: 0px 5px; cursor: default; font-size: 80%; } </style> </head> <body onload="showFlatCalendar()">

<a href="http://www.dynarch.ru/projects/calendar/" title="Visit the project website">jscalendar</a>-1.0 "It is happening again"

Theme:
<a href="#" id="defaultTheme" onclick="return setActiveStyleSheet(this, "Aqua");">Aqua</a> | <a href="#" onclick="return setActiveStyleSheet(this, "winter");">winter</a> | <a href="#" onclick="return setActiveStyleSheet(this, "blue");">blue</a> | <a href="#" onclick="return setActiveStyleSheet(this, "summer");">summer</a> | <a href="#" onclick="return setActiveStyleSheet(this, "green");">green</a>
<a href="#" onclick="return setActiveStyleSheet(this, "win2k-1");">win2k-1</a> | <a href="#" onclick="return setActiveStyleSheet(this, "win2k-2");">win2k-2</a> | <a href="#" onclick="return setActiveStyleSheet(this, "win2k-cold-1");">win2k-cold-1</a> | <a href="#" onclick="return setActiveStyleSheet(this, "win2k-cold-2");">win2k-cold-2</a>
<a href="#" onclick="return setActiveStyleSheet(this, "system");">system</a> <script type="text/javascript"> setActiveStyleSheet(document.getElementById("defaultTheme"), "Aqua"); </script>







</table>
<address>

© <a href="http://www.dynarch.ru/">dynarch.ru</a> 2002-2005
Author: <a href="http://www.bazon.net/mishoo/">Mihai Bazon</a>
Distributed under the <a href="http://www.gnu.org/licenses/lgpl.html">GNU LGPL</a>.</address>

If you use this script on a public page we would love it if you would <a href="http://www.dynarch.ru/contact.html">let us know</a>.

</body></html>


 </source>
   
  

<A href="http://www.wbex.ru/Code/JavaScriptDownload/jscalendar-1.0.zip">jscalendar-1.0.zip( 396 k)</a>


Calendar with image for each month

   <source lang="html4strict">

<html> <head> <title>Calendar Demo</title> <script type="text/javascript"> //Constructor function calendar(id,d,p){

 this.id = id;
 this.dateObject = d;
 this.pix = p;
 this.write = writeCalendar;
 this.length = getLength;
 this.month = d.getMonth();
 this.date = d.getDate();
 this.day = d.getDay();
 this.year = d.getFullYear();
 this.getFormattedDate = getFormattedDate;
 //get the first day of the month"s day
 d.setDate(1);
 this.firstDay = d.getDay();
 //then reset the date object to the correct date
 d.setDate(this.date);

} var days = new Array("Sunday","Monday","Tuesday","Wednesday","Thursday","Friday","Saturday"); var months = new Array("January","February","March","April","May","June","July","August","September","October","November","December"); function getFormattedDate(){

 return days[this.day] + ", " + months[this.month] + " " + this.date + ", " + this.year;
 //return this.month + "/" + this.date + "/" + this.year;

} function writeCalendar(){

var calString = "
";
 //write month and year at top of table
calString += "

<form action="#">

Popup examples


Date #1: <input type="text" name="date1" id="sel1" size="30" ><input type="reset" value=" ... " onclick="return showCalendar("sel1", "%Y-%m-%d [%W] %H:%M", "24", true);"> %Y-%m-%d [%W] %H:%M -- single click
Date #2: <input type="text" name="date2" id="sel2" size="30" ><input type="reset" value=" ... " onclick="return showCalendar("sel2", "%a, %b %e, %Y [%I:%M %p]", "12");"> %a, %b %e, %Y [%I:%M %p] -- double click

<SELECT multiple size="4" name="component-select">

 <OPTION selected value="Component_1_a">Component_1</OPTION>
 <OPTION selected value="Component_1_b">Component_2</OPTION>
 <OPTION>Component_3</OPTION>
 <OPTION>Component_4</OPTION>
 <OPTION>Component_5</OPTION>
 <OPTION>Component_6</OPTION>
 <OPTION>Component_7</OPTION>

</SELECT> this select should hide when the calendar is above it.

Date #3: <input type="text" name="date3" id="sel3" size="30" ><input type="reset" value=" ... " onclick="return showCalendar("sel3", "%d/%m/%Y");"> %d/%m/%Y -- single click
Date #4: <input type="text" name="date4" id="sel4" size="30" ><input type="reset" value=" ... " onclick="return showCalendar("sel4", "%A, %B %e, %Y");"> %A, %B %e, %Y -- double click </form>

This is release 1.0. Works on MSIE/Win 5.0 or better (really), Opera 7+, Mozilla, Firefox, Netscape 6.x, 7.0 and all other Gecko-s, Konqueror and Safari.

Keyboard navigation

Starting with version 0.9.2, you can also use the keyboard to select dates (only for popup calendars; does not work with Opera 7 or Konqueror/Safari). The following keys are available:

  • , , , -- select date
  • CTRL + , -- select month
  • CTRL + , -- select year
  • SPACE -- go to today date
  • ENTER -- accept the currently selected date
  • ESC -- cancel selection
             Flat calendar

A non-popup version will appear below as soon as the page is loaded. Note that it doesn"t show the week number.

 

The example above uses the setDisabledHandler() member function to setup a handler that would only enable days withing a range of 10 days, forward or backward, from the current date.

         </div>
"; //write the image - comment out to hide images calString += "";
 //write the month
calString += "";
 //write a row containing days of the week
calString += ""; for(i=0;i<days.length;i++){ calString += "";
 }
 
 //write the body of the calendar
calString += ""; //create 6 rows so that the calendar doesn"t resize for(j=0;j<42;j++){ var displayNum = (j-this.firstDay+1); if(j<this.firstDay){ //write the leading empty cells calString += "";
   }else if(displayNum==this.date){
calString += "";
   }else if(displayNum > this.length()){
     //Empty cells at bottom of calendar
calString += "";
   }else{
     //the rest of the numbered cells
calString += "";
   }
   if(j%7==6){
calString += ""; } } //close the last number row calString += ""; //write the nav row calString += ""; calString += ""; calString += ""; calString += ""; calString += ""; calString += ""; calString += ""; calString += "
<img src="" + this.pix[this.month].src + ""/>
" + months[this.month] + ", " + this.year + "
" + days[i].substring(0,3) + "
 " + displayNum + " " + displayNum + "
 
"; calString += "
";
 return calString;

} function getLength(){

 //thirty days has September...
 switch(this.month){
   case 1:
     if((this.dateObject.getFullYear()%4==0&&this.dateObject.getFullYear()%100!=0)||this.dateObject.getFullYear()%400==0)
       return 29; //leap year
     else
       return 28;
   case 3:
     return 30;
   case 5:
     return 30;
   case 8:
     return 30;
   case 10:
     return 30
   default:
     return 31;
 }

} function changeDate(td,cal){

 //Some JavaScript trickery
 //Change the cal argument to the existing calendar object
 //This is why the first argument in the constructor must match the variable name
 //The cal reference also allows for multiple calendars on a page
 cal = eval(cal);
 document.getElementById(cal.id + "selected").className = "days";
 document.getElementById(cal.id + "selected").id = "";
 td.className = "date";
 td.id = cal.id + "selected";
 //set the calendar object to the new date
 cal.dateObject.setDate(td.firstChild.nodeValue);
 cal = new calendar(cal.id,cal.dateObject,cal.pix);
 //here is where you could react to a date change - I"ll just display the formatted date
 alert(cal.getFormattedDate());

} function changeMonth(mo,cal){

 //more trickery!
 cal = eval(cal);
 //The Date object is smart enough to know that it should roll over in December
 //when going forward and in January when going back
 cal.dateObject.setMonth(cal.dateObject.getMonth() + mo);
 cal = new calendar(cal.id,cal.dateObject,cal.pix);
 cal.formattedDate = cal.getFormattedDate();
 document.getElementById("calContainer").innerHTML = cal.write();
 

}

</script> <style rel="stylesheet" type="text/css"> .month, .nav{

 background-color: navy;
 color: white;
 font: 10pt sans-serif;

} .nav{

 cursor: pointer;
 cursor: hand;

} .dayHeader{

 color: black;
 font: 10pt sans-serif;
 border-bottom: 1px black solid;
 font-weight: bold;

} .empty{

 background-color: white;
 border-bottom: 1px black solid;

} .days{

 color: black;
 background-color: rgb(235,235,235);;
 font: 10pt sans-serif;
 border-bottom: 1px black solid;
 border-left: 1px black solid;
 border-right: 1px black solid;
 cursor: pointer;
 cursor: hand;

} .date{

 color: maroon;
 font: 10pt sans-serif;
 font-weight: bold;
 border-bottom: 1px black solid;
 border-left: 1px black solid;
 border-right: 1px black solid;
 cursor: pointer;
 cursor: hand;

} </style> </head> <body> <script language="JavaScript"> //create the pix array var pix = new Array(); for(i=0; i<12; i++){

 pix[i] = new Image();
 pix[i].src = "patternImages/fractal" + i + ".jpg";

} //Place this script wherever you want your calendar //The first argument must match the var name var thisMonth = new calendar("thisMonth",new Date(),pix); document.write(thisMonth.write()); </script> </body> </html>


 </source>
   
  

<A href="http://www.wbex.ru/Code/JavaScriptDownload/CalendarEachMonth.zip">CalendarEachMonth.zip( 135 k)</a>


Date Picker in new window

   <source lang="html4strict">

<html>

<script language="JavaScript"> //Script by Denis Gritcyuk: tspicker@yahoo.ru // Title: Timestamp picker // Description: See the demo at url // URL: http://us.geocities.ru/tspicker/ // Version: 1.0 // Date: 12-05-2001 (mm-dd-yyyy) // Author: Denis Gritcyuk <denis@softcomplex.ru>; <tspicker@yahoo.ru> // Notes: Permission given to use this script in any kind of applications if // header lines are left unchanged. Feel free to contact the author // for feature requests and/or donations function show_calendar(str_target, str_datetime) {

 var arr_months = ["January", "February", "March", "April", "May", "June",
   "July", "August", "September", "October", "November", "December"];
 var week_days = ["Su", "Mo", "Tu", "We", "Th", "Fr", "Sa"];
 var n_weekstart = 1; // day week starts from (normally 0 or 1)
 var dt_datetime = (str_datetime == null || str_datetime =="" ?  new Date() : str2dt(str_datetime));
 var dt_prev_month = new Date(dt_datetime);
 dt_prev_month.setMonth(dt_datetime.getMonth()-1);
 var dt_next_month = new Date(dt_datetime);
 dt_next_month.setMonth(dt_datetime.getMonth()+1);
 var dt_firstday = new Date(dt_datetime);
 dt_firstday.setDate(1);
 dt_firstday.setDate(1-(7+dt_firstday.getDay()-n_weekstart)%7);
 var dt_lastday = new Date(dt_next_month);
 dt_lastday.setDate(0);
 
 // html generation (feel free to tune it for your particular application)
 // print calendar header
 var str_buffer = new String (
   "<html>\n"+
   "<head>\n"+
   "  <title>Calendar</title>\n"+
   "</head>\n"+
   "<body bgcolor=\"White\">\n"+
"\n"+ "
\n"+ "\n"+ "\n \n"+ " \n"+ " \n\n" ); var dt_current_day = new Date(dt_firstday); // print weekdays titles str_buffer += "\n"; for (var n=0; n<7; n++) str_buffer += " \n"; // print calendar table str_buffer += "\n"; while (dt_current_day.getMonth() == dt_datetime.getMonth() || dt_current_day.getMonth() == dt_firstday.getMonth()) { // print row heder str_buffer += "\n"; for (var n_current_wday=0; n_current_wday<7; n_current_wday++) { if (dt_current_day.getDate() == dt_datetime.getDate() && dt_current_day.getMonth() == dt_datetime.getMonth()) // print current date str_buffer += " containing navigation buttons */ } .calendar thead .daynames { /* Row containing the day names */ } .calendar thead .name { /* Cells in footer (only one right now) */ } .calendar tfoot .ttip { /* Tooltip (status bar) cell
<a href=\"javascript:window.opener.show_calendar(""+
   str_target+"", ""+ dt2dtstr(dt_prev_month)+""+document.cal.time.value);\">"+
   "<img src=\"prev.gif\" width=\"16\" height=\"16\" border=\"0\""+
" alt=\"previous month\"></a>
"+
   ""
+arr_months[dt_datetime.getMonth()]+" "+dt_datetime.getFullYear()+"
<a href=\"javascript:window.opener.show_calendar(""
   +str_target+"", ""+dt2dtstr(dt_next_month)+""+document.cal.time.value);\">"+
   "<img src=\"next.gif\" width=\"16\" height=\"16\" border=\"0\""+
" alt=\"next month\"></a>
"+
   ""+
week_days[(n_weekstart+n)%7]+"
";
       else if (dt_current_day.getDay() == 0 || dt_current_day.getDay() == 6)
         // weekend days
str_buffer += "
";
       else
         // print working days of current month
str_buffer += "
";
       if (dt_current_day.getMonth() == dt_datetime.getMonth())
         // print days of current month
         str_buffer += "<a href=\"javascript:window.opener."+str_target+
         ".value=""+dt2dtstr(dt_current_day)+""+document.cal.time.value; window.close();\">"+
         "";
       else 
         // print days of other months
         str_buffer += "<a href=\"javascript:window.opener."+str_target+
         ".value=""+dt2dtstr(dt_current_day)+""+document.cal.time.value; window.close();\">"+
         "";
       str_buffer += dt_current_day.getDate()+"</a></td>\n";
       dt_current_day.setDate(dt_current_day.getDate()+1);
   }
   // print row footer
   str_buffer += "</tr>\n";
 }
 // print calendar footer
 str_buffer +=
"<form name=\"cal\">\n
"+
   ""+
   "Time: <input type=\"text\" name=\"time\" value=\""+dt2tmstr(dt_datetime)+
   "\" size=\"8\" maxlength=\"8\"></td></tr>\n</form>\n" +
   "</table>\n" +
   "</tr>\n</td>\n</table>\n" +
   "</body>\n" +
   "</html>\n";
 var vWinCal = window.open("", "Calendar", 
   "width=200,height=250,status=no,resizable=yes,top=200,left=200");
 vWinCal.opener = self;
 var calc_doc = vWinCal.document;
 calc_doc.write (str_buffer);
 calc_doc.close();

} // datetime parsing and formatting routimes. modify them if you wish other datetime format function str2dt (str_datetime) {

 var re_date = /^(\d+)\-(\d+)\-(\d+)\s+(\d+)\:(\d+)\:(\d+)$/;
 if (!re_date.exec(str_datetime))
   return alert("Invalid Datetime format: "+ str_datetime);
 return (new Date (RegExp.$3, RegExp.$2-1, RegExp.$1, RegExp.$4, RegExp.$5, RegExp.$6));

} function dt2dtstr (dt_datetime) {

 return (new String (
     dt_datetime.getDate()+"-"+(dt_datetime.getMonth()+1)+"-"+dt_datetime.getFullYear()+" "));

} function dt2tmstr (dt_datetime) {

 return (new String (
     dt_datetime.getHours()+":"+dt_datetime.getMinutes()+":"+dt_datetime.getSeconds()));

}

</script> <form name="tstest"> <input type="Text" name="timestamp" value=""> <a href="javascript:show_calendar("document.tstest.timestamp", document.tstest.timestamp.value);"><img src="cal.gif" width="16" height="16" border="0" alt="Click Here to Pick up the timestamp"></a> </form> <html>


 </source>
   
  

<A href="http://www.wbex.ru/Code/JavaScriptDownload/datepick.zip">datepick.zip( 3 k)</a>


Date Time Picker

<A href="http://www.wbex.ru/Code/JavaScriptDownload/datetimepick.zip">datetimepick.zip( 5 k)</a>

1. <A href="/Code/JavaScript/GUI-Components/HTMLCalendarbasedonDynAPI.htm">HTML Calendar based on DynAPI</a> <A href="/Code/JavaScript/GUI-Components/HTMLCalendarbasedonDynAPI.htm"></a> 2. <A href="/Code/JavaScript/GUI-Components/JavaScriptDatePickerbasedonComboBox.htm">JavaScript Date Picker based on ComboBox</a> <A href="/Code/JavaScript/GUI-Components/JavaScriptDatePickerbasedonComboBox.htm"></a> 3. <A href="/Code/JavaScript/GUI-Components/CalendarControlSingleSelectImplementation.htm">Calendar Control - Single-Select Implementation</a> <A href="/Code/JavaScript/GUI-Components/CalendarControlSingleSelectImplementation.htm"></a> 4. <A href="/Code/JavaScript/GUI-Components/CalendarControl2UpImplementation.htm">Calendar Control - 2-Up Implementation</a> <A href="/Code/JavaScript/GUI-Components/CalendarControl2UpImplementation.htm"></a> 5. <A href="/Code/JavaScript/GUI-Components/CalendarControlHandlingonSelectonDeselect.htm">Calendar Control - Handling onSelect / onDeselect</a> <A href="/Code/JavaScript/GUI-Components/CalendarControlHandlingonSelectonDeselect.htm"></a> 6. <A href="/Code/JavaScript/GUI-Components/CalendarControlMixMaxImplementation.htm">Calendar Control - Mix/Max Implementation</a> <A href="/Code/JavaScript/GUI-Components/CalendarControlMixMaxImplementation.htm"></a> 7. <A href="/Code/JavaScript/GUI-Components/CalendarControlMultiSelectImplementation.htm">Calendar Control - Multi-Select Implementation</a> <A href="/Code/JavaScript/GUI-Components/CalendarControlMultiSelectImplementation.htm"></a> 8. <A href="/Code/JavaScript/GUI-Components/CalendarControlMultiSelect2upImplementation.htm">Calendar Control - Multi-Select 2-up Implementation</a> <A href="/Code/JavaScript/GUI-Components/CalendarControlMultiSelect2upImplementation.htm"></a> 9. <A href="/Code/JavaScript/GUI-Components/CalendarControlCustomRendererExampleHolidayRendererImplementation.htm">Calendar Control - Custom Renderer Example (Holiday Renderer Implementation)</a> <A href="/Code/JavaScript/GUI-Components/CalendarControlCustomRendererExampleHolidayRendererImplementation.htm"></a> 10. <A href="/Code/JavaScript/GUI-Components/CalendarControlDateRestrictionExampleDateRestrictionImplementation.htm">Calendar Control - Date Restriction Example (Date Restriction Implementation)</a> <A href="/Code/JavaScript/GUI-Components/CalendarControlDateRestrictionExampleDateRestrictionImplementation.htm"></a> 11. <A href="/Code/JavaScript/GUI-Components/CalendarControlRowHighlightExampleRowHighlightImplementation.htm">Calendar Control - Row Highlight Example (Row Highlight Implementation)</a> <A href="/Code/JavaScript/GUI-Components/CalendarControlRowHighlightExampleRowHighlightImplementation.htm"></a> 12. <A href="/Code/JavaScript/GUI-Components/Popupcalendar.htm">Popup calendar</a> <A href="/Code/JavaScript/GUI-Components/Popupcalendar.htm"></a> 13. <A href="/Code/JavaScript/GUI-Components/MonthCalendar.htm">Month Calendar</a> 14. <A href="/Code/JavaScript/GUI-Components/PopupCalendarforatextfield.htm">Popup Calendar for a textfield</a> 15. <A href="/Code/JavaScript/GUI-Components/MultiselectionCalendar.htm">Multiselection Calendar</a> 16. <A href="/Code/JavaScript/GUI-Components/FreeDatePickerAneasyplugintoaddadatepickercalendarinyourwebsite.htm">Free Date Picker : An easy plugin to add a date picker (calendar) in your web site</a> 17. <A href="/Code/JavaScript/GUI-Components/HTMLDatePicker.htm">HTML Date Picker</a> 18. <A href="/Code/JavaScript/GUI-Components/DatePickerinnewwindow.htm">Date Picker in new window</a> <A href="/Code/JavaScript/GUI-Components/DatePickerinnewwindow.htm"></a> 19. <A href="/Code/JavaScript/GUI-Components/AllbrowserCalendar.htm">All browser Calendar</a> <A href="/Code/JavaScript/GUI-Components/AllbrowserCalendar.htm"></a> 20. <A href="/Code/JavaScript/GUI-Components/DHTMLCalendarfortheimpatient.htm">DHTML Calendar for the impatient</a> <A href="/Code/JavaScript/GUI-Components/DHTMLCalendarfortheimpatient.htm"></a> 21. <A href="/Code/JavaScript/GUI-Components/Calendarspecialday.htm">Calendar: special day</a> <A href="/Code/JavaScript/GUI-Components/Calendarspecialday.htm"></a> 22. <A href="/Code/JavaScript/GUI-Components/Calendardayinfo.htm">Calendar: day info</a> <A href="/Code/JavaScript/GUI-Components/Calendardayinfo.htm"></a> 23. <A href="/Code/JavaScript/GUI-Components/CalendarMultipledayselection.htm">Calendar: Multiple day selection</a> <A href="/Code/JavaScript/GUI-Components/CalendarMultipledayselection.htm"></a> 24. <A href="/Code/JavaScript/GUI-Components/Calendarwithdifferenttheme.htm">Calendar with different theme</a> <A href="/Code/JavaScript/GUI-Components/Calendarwithdifferenttheme.htm"></a> 25. <A href="/Code/JavaScript/GUI-Components/Calendarwithimageforeachmonth.htm">Calendar with image for each month</a> <A href="/Code/JavaScript/GUI-Components/Calendarwithimageforeachmonth.htm"></a> 26. <A href="/Code/JavaScript/GUI-Components/FancyCalendar.htm">Fancy Calendar </a> <A href="/Code/JavaScript/GUI-Components/FancyCalendar.htm"></a> 27. <A href="/Code/JavaScript/GUI-Components/AnotherCalendar.htm">Another Calendar </a> <A href="/Code/JavaScript/GUI-Components/AnotherCalendar.htm"></a> 28. <A href="/Code/JavaScript/GUI-Components/MonthCalendar2.htm">Month Calendar (2)</a> 29. <A href="/Code/JavaScript/GUI-Components/BuildingaCalculator.htm">Building a Calculator</a> 30. <A href="/Code/JavaScript/GUI-Components/ADynamicCalendarTable.htm">A Dynamic Calendar Table</a> 31. <A href="/Code/JavaScript/GUI-Components/DynamicHTMLCalendar.htm">Dynamic HTML Calendar</a> 32. <A href="/Code/JavaScript/GUI-Components/AStaticCalendarbyJavaScript.htm"> A Static Calendar by JavaScript</a> 33. <A href="/Code/JavaScript/GUI-Components/DisplayingtheCalendar.htm">Displaying the Calendar</a> 34. <A href="/Code/JavaScript/GUI-Components/CalendarIEonly.htm">Calendar (IE only)</a> 35. <A href="/Code/JavaScript/GUI-Components/Calendarinslidetab.htm">Calendar in slide tab</a> 36. <A href="/Code/JavaScript/GUI-Components/AnotherDHTMLCalendar.htm">Another DHTML Calendar</a> 37. <A href="/Code/JavaScript/GUI-Components/EventCalendar.htm">Event Calendar</a> <A href="/Code/JavaScript/GUI-Components/EventCalendar.htm"></a> 38. <A href="/Code/JavaScript/GUI-Components/Opencalendar.htm">Open calendar</a> <A href="/Code/JavaScript/GUI-Components/Opencalendar.htm"></a> 39. <A href="/Code/JavaScript/GUI-Components/swazzcalendar10.htm">swazz calendar 1.0</a> <A href="/Code/JavaScript/GUI-Components/swazzcalendar10.htm"></a> 40. <A href="/Code/JavaScript/GUI-Components/jquerycalendar.htm">jquery calendar</a> <A href="/Code/JavaScript/GUI-Components/jquerycalendar.htm"></a>

DHTML Calendar for the impatient

   <source lang="html4strict">


<html> <head> <meta http-equiv="content-type" content="text/xml; charset=utf-8" /> <title>Simple calendar setup [flat calendar]</title>


 <style rel="stylesheet" type="text/css" media="all" title="win2k-cold-1">

/* The main calendar widget. DIV containing a table. */ .calendar {

 position: relative;
 display: none;
 border-top: 2px solid #fff;
 border-right: 2px solid #000;
 border-bottom: 2px solid #000;
 border-left: 2px solid #fff;
 font-size: 11px;
 color: #000;
 cursor: default;
 background: #c8d0d4;
 font-family: tahoma,verdana,sans-serif;

} .calendar table {

 border-top: 1px solid #000;
 border-right: 1px solid #fff;
 border-bottom: 1px solid #fff;
 border-left: 1px solid #000;
 font-size: 11px;
 color: #000;
 cursor: default;
 background: #c8d0d4;
 font-family: tahoma,verdana,sans-serif;

} /* Header part -- contains navigation buttons and day names. */ .calendar .button { /* "<<", "<", ">", ">>" buttons have this class */

 text-align: center;
 padding: 1px;
 border-top: 1px solid #fff;
 border-right: 1px solid #000;
 border-bottom: 1px solid #000;
 border-left: 1px solid #fff;

} .calendar .nav {

 background: transparent url(menuarrow.gif) no-repeat 100% 100%;

} .calendar thead .title { /* This holds the current "month, year" */

 font-weight: bold;
 padding: 1px;
 border: 1px solid #000;
 background: #788084;
 color: #fff;
 text-align: center;

}

.calendar thead .headrow { /* Row
containing the day names */
 border-bottom: 1px solid #000;
 padding: 2px;
 text-align: center;
 background: #e8f0f4;

} .calendar thead .weekend { /* How a weekend day name shows in header */

 color: #f00;

} .calendar thead .hilite { /* How do the buttons in header appear when hover */

 border-top: 2px solid #fff;
 border-right: 2px solid #000;
 border-bottom: 2px solid #000;
 border-left: 2px solid #fff;
 padding: 0px;
 background-color: #d8e0e4;

} .calendar thead .active { /* Active (pressed) buttons in header */

 padding: 2px 0px 0px 2px;
 border-top: 1px solid #000;
 border-right: 1px solid #fff;
 border-bottom: 1px solid #fff;
 border-left: 1px solid #000;
 background-color: #b8c0c4;

} /* The body part -- contains all the days in month. */

.calendar tbody .day { /* Cells
containing month days dates */
 width: 2em;
 text-align: right;
 padding: 2px 4px 2px 2px;

} .calendar tbody .day.othermonth {

 font-size: 80%;
 color: #aaa;

} .calendar tbody .day.othermonth.oweekend {

 color: #faa;

} .calendar table .wn {

 padding: 2px 3px 2px 2px;
 border-right: 1px solid #000;
 background: #e8f4f0;

} .calendar tbody .rowhilite td {

 background: #d8e4e0;

} .calendar tbody .rowhilite td.wn {

 background: #c8d4d0;

}

.calendar tbody td.hilite { /* Hovered cells
*/
 padding: 1px 3px 1px 1px;
 border: 1px solid;
 border-color: #fff #000 #000 #fff;

}

.calendar tbody td.active { /* Active (pressed) cells
*/
 padding: 2px 2px 0px 2px;
 border: 1px solid;
 border-color: #000 #fff #fff #000;

} .calendar tbody td.selected { /* Cell showing selected date */

 font-weight: bold;
 padding: 2px 2px 0px 2px;
 border: 1px solid;
 border-color: #000 #fff #fff #000;
 background: #d8e0e4;

} .calendar tbody td.weekend { /* Cells showing weekend days */

 color: #f00;

} .calendar tbody td.today { /* Cell showing today date */

 font-weight: bold;
 color: #00f;

} .calendar tbody .disabled { color: #999; } .calendar tbody .emptycell { /* Empty cells (the best is to hide them) */

 visibility: hidden;

} .calendar tbody .emptyrow { /* Empty row (some months need less than 6 rows) */

 display: none;

} /* The footer part -- status bar and "Close" button */

.calendar tfoot .footrow { /* The
*/
 background: #e8f0f4;
 padding: 1px;
 border: 1px solid #000;
 background: #788084;
 color: #fff;
 text-align: center;

} .calendar tfoot .hilite { /* Hover style for buttons in footer */

 border-top: 1px solid #fff;
 border-right: 1px solid #000;
 border-bottom: 1px solid #000;
 border-left: 1px solid #fff;
 padding: 1px;
 background: #d8e0e4;

} .calendar tfoot .active { /* Active (pressed) style for buttons in footer */

 padding: 2px 0px 0px 2px;
 border-top: 1px solid #000;
 border-right: 1px solid #fff;
 border-bottom: 1px solid #fff;
 border-left: 1px solid #000;

} /* Combo boxes (menus that display months/years for direct selection) */ .calendar .rubo {

 position: absolute;
 display: none;
 width: 4em;
 top: 0px;
 left: 0px;
 cursor: default;
 border-top: 1px solid #fff;
 border-right: 1px solid #000;
 border-bottom: 1px solid #000;
 border-left: 1px solid #fff;
 background: #d8e0e4;
 font-size: 90%;
 padding: 1px;
 z-index: 100;

} .calendar .rubo .label, .calendar .rubo .label-IEfix {

 text-align: center;
 padding: 1px;

} .calendar .rubo .label-IEfix {

 width: 4em;

} .calendar .rubo .active {

 background: #c8d0d4;
 padding: 0px;
 border-top: 1px solid #000;
 border-right: 1px solid #fff;
 border-bottom: 1px solid #fff;
 border-left: 1px solid #000;

} .calendar .rubo .hilite {

 background: #048;
 color: #aef;

} .calendar td.time {

 border-top: 1px solid #000;
 padding: 1px 0px;
 text-align: center;
 background-color: #e8f0f4;

} .calendar td.time .hour, .calendar td.time .minute, .calendar td.time .ampm {

 padding: 0px 3px 0px 4px;
 border: 1px solid #889;
 font-weight: bold;
 background-color: #fff;

} .calendar td.time .ampm {

 text-align: center;

} .calendar td.time .colon {

 padding: 0px 2px 0px 3px;
 font-weight: bold;

} .calendar td.time span.hilite {

 border-color: #000;
 background-color: #667;
 color: #fff;

} .calendar td.time span.active {

 border-color: #f00;
 background-color: #000;
 color: #0f0;

}

 </style>
 
 <script type="text/javascript">

/* Copyright Mihai Bazon, 2002-2005 | www.bazon.net/mishoo

* -----------------------------------------------------------
*
* The DHTML Calendar, version 1.0 "It is happening again"
*
* Details and latest version at:
* www.dynarch.ru/projects/calendar
*
* This script is developed by Dynarch.ru.  Visit us at www.dynarch.ru.
*
* This script is distributed under the GNU Lesser General Public License.
* Read the entire license text here: http://www.gnu.org/licenses/lgpl.html
*/

// $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;
 // HTML elements
 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;
 // Information
 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;
   // 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;
 }

}; // ** constants /// "static", needed for event handlers. Calendar._C = null; /// detect a special case of "web browser" Calendar.is_ie = ( /msie/i.test(navigator.userAgent) &&

      !/opera/i.test(navigator.userAgent) );

Calendar.is_ie5 = ( Calendar.is_ie && /msie 5\.0/i.test(navigator.userAgent) ); /// detect Opera browser Calendar.is_opera = /opera/i.test(navigator.userAgent); /// detect KHTML-based browsers Calendar.is_khtml = /Konqueror|Safari|KHTML/i.test(navigator.userAgent); // 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;

}; // 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;

}; // END: UTILITY FUNCTIONS // 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";
 }

}; // 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);
 }

}; /**

*  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;
   // 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 <mihai_bazon@yahoo.ru> to get it into the distribution  ;-)\n\n" +
         "Thank you!\n" +
         "http://dynarch.ru/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 // BEGIN: CALENDAR OBJECT FUNCTIONS /**

*  This function creates the calendar inside the given parent.  If _par is
*  null than it creates a popup calendar inside the BODY element.  If _par is
*  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 = "
" + text + "
";
   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("×", 1, 200).ttip = Calendar._TT["CLOSE"];
 }
 row = Calendar.createElement("tr", thead);
 row.className = "headrow";
 this._nav_py = hh("«", 1, -2);
 this._nav_py.ttip = Calendar._TT["PREV_YEAR"];
 this._nav_pm = hh("‹", 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_nm = hh("›", 1, 1);
 this._nav_nm.ttip = Calendar._TT["NEXT_MONTH"];
 this._nav_ny = hh("»", 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"] || " ";
   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 = " ";
     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);

}; /** 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);

}; /**

*  (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 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 = " ";
         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";

}; 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);
 }

}; /**

*  Refreshes the calendar.  Useful if the "disabledHandler" function is
*  dynamic, meaning that the list of disabled date can change at runtime.
*  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);

}; /** Modifies the "firstDayOfWeek" parameter (pass 0 for Synday, 1 for Monday, etc.). */ Calendar.prototype.setFirstDayOfWeek = function (firstDayOfWeek) {

 this._init(firstDayOfWeek, this.date);
 this._displayWeekdays();

}; /**

*  Allows customization of what dates are enabled.  The "unaryFunction"
*  parameter must be a function object that receives the date (as a JS Date
*  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;

}; /** Customization of allowed year range for the calendar. */ 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));
 }

}; /** Calls the second user handler (closeHandler). */ 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;

}; /**

*  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);

}; // 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);
 }

}; /** 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();

}; /**

*  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();

}; /**

*  Shows the calendar at a given absolute position (beware that, depending on
*  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();

}; /** 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);
   }
   // 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
   }
   // 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();

}; /** Customizes the date format. */ Calendar.prototype.setDateFormat = function (str) {

 this.dateFormat = str;

}; /** Customizes the tooltip date format. */ 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";
     }
   }
 }

}; /** Internal function; it displays the bar with the names of the weekday. */ Calendar.prototype._displayWeekdays = function () {

 var fdow = this.firstDayOfWeek;
 var cell = this.firstdayname;
 var weekend = Calendar._TT["WEEKEND"];
 for (var i = 0; i < 7; ++i) {
   cell.className = "day name";
   var realday = (i + fdow) % 7;
   if (i) {
     cell.ttip = Calendar._TT["DAY_FIRST"].replace("%s", Calendar._DN[realday]);
     cell.navtype = 100;
     cell.calendar = this;
     cell.fdow = realday;
     Calendar._add_evs(cell);
   }
   if (weekend.indexOf(realday.toString()) != -1) {
     Calendar.addClass(cell, "weekend");
   }
   cell.innerHTML = Calendar._SDN[(i + fdow) % 7];
   cell = cell.nextSibling;
 }

}; /** Internal function. Hides all combo boxes that might be displayed. */ Calendar.prototype._hideCombos = function () {

 this.monthsCombo.style.display = "none";
 this.yearsCombo.style.display = "none";

}; /** Internal function. Starts dragging the element. */ Calendar.prototype._dragStart = function (ev) {

 if (this.dragging) {
   return;
 }
 this.dragging = true;
 var posX;
 var posY;
 if (Calendar.is_ie) {
   posY = window.event.clientY + document.body.scrollTop;
   posX = window.event.clientX + document.body.scrollLeft;
 } else {
   posY = ev.clientY + window.scrollY;
   posX = ev.clientX + window.scrollX;
 }
 var st = this.element.style;
 this.xOffs = posX - parseInt(st.left);
 this.yOffs = posY - parseInt(st.top);
 with (Calendar) {
   addEvent(document, "mousemove", calDragIt);
   addEvent(document, "mouseup", calDragEnd);
 }

}; // BEGIN: DATE OBJECT PATCHES /** Adds the number of days array to the Date object. */ Date._MD = new Array(31,28,31,30,31,30,31,31,30,31,30,31); /** Constants used for time computations */ Date.SECOND = 1000 /* milliseconds */; Date.MINUTE = 60 * Date.SECOND; Date.HOUR = 60 * Date.MINUTE; Date.DAY = 24 * Date.HOUR; Date.WEEK = 7 * Date.DAY; Date.parseDate = function(str, fmt) {

 var today = new Date();
 var y = 0;
 var m = -1;
 var d = 0;
 var a = str.split(/\W+/);
 var b = fmt.match(/%./g);
 var i = 0, j = 0;
 var hr = 0;
 var min = 0;
 for (i = 0; i < a.length; ++i) {
   if (!a[i])
     continue;
   switch (b[i]) {
       case "%d":
       case "%e":
     d = parseInt(a[i], 10);
     break;
       case "%m":
     m = parseInt(a[i], 10) - 1;
     break;
       case "%Y":
       case "%y":
     y = parseInt(a[i], 10);
     (y < 100) && (y += (y > 29) ? 1900 : 2000);
     break;
       case "%b":
       case "%B":
     for (j = 0; j < 12; ++j) {
       if (Calendar._MN[j].substr(0, a[i].length).toLowerCase() == a[i].toLowerCase()) { m = j; break; }
     }
     break;
       case "%H":
       case "%I":
       case "%k":
       case "%l":
     hr = parseInt(a[i], 10);
     break;
       case "%P":
       case "%p":
     if (/pm/i.test(a[i]) && hr < 12)
       hr += 12;
     else if (/am/i.test(a[i]) && hr >= 12)
       hr -= 12;
     break;
       case "%M":
     min = parseInt(a[i], 10);
     break;
   }
 }
 if (isNaN(y)) y = today.getFullYear();
 if (isNaN(m)) m = today.getMonth();
 if (isNaN(d)) d = today.getDate();
 if (isNaN(hr)) hr = today.getHours();
 if (isNaN(min)) min = today.getMinutes();
 if (y != 0 && m != -1 && d != 0)
   return new Date(y, m, d, hr, min, 0);
 y = 0; m = -1; d = 0;
 for (i = 0; i < a.length; ++i) {
   if (a[i].search(/[a-zA-Z]+/) != -1) {
     var t = -1;
     for (j = 0; j < 12; ++j) {
       if (Calendar._MN[j].substr(0, a[i].length).toLowerCase() == a[i].toLowerCase()) { t = j; break; }
     }
     if (t != -1) {
       if (m != -1) {
         d = m+1;
       }
       m = t;
     }
   } else if (parseInt(a[i], 10) <= 12 && m == -1) {
     m = a[i]-1;
   } else if (parseInt(a[i], 10) > 31 && y == 0) {
     y = parseInt(a[i], 10);
     (y < 100) && (y += (y > 29) ? 1900 : 2000);
   } else if (d == 0) {
     d = a[i];
   }
 }
 if (y == 0)
   y = today.getFullYear();
 if (m != -1 && d != 0)
   return new Date(y, m, d, hr, min, 0);
 return today;

}; /** Returns the number of days in the current month */ Date.prototype.getMonthDays = function(month) {

 var year = this.getFullYear();
 if (typeof month == "undefined") {
   month = this.getMonth();
 }
 if (((0 == (year%4)) && ( (0 != (year%100)) || (0 == (year%400)))) && month == 1) {
   return 29;
 } else {
   return Date._MD[month];
 }

}; /** Returns the number of day in the year. */ Date.prototype.getDayOfYear = function() {

 var now = new Date(this.getFullYear(), this.getMonth(), this.getDate(), 0, 0, 0);
 var then = new Date(this.getFullYear(), 0, 0, 0, 0, 0);
 var time = now - then;
 return Math.floor(time / Date.DAY);

}; /** Returns the number of the week in year, as defined in ISO 8601. */ Date.prototype.getWeekNumber = function() {

 var d = new Date(this.getFullYear(), this.getMonth(), this.getDate(), 0, 0, 0);
 var DoW = d.getDay();
 d.setDate(d.getDate() - (DoW + 6) % 7 + 3); // Nearest Thu
 var ms = d.valueOf(); // GMT
 d.setMonth(0);
 d.setDate(4); // Thu in Week 1
 return Math.round((ms - d.valueOf()) / (7 * 864e5)) + 1;

}; /** Checks date and time equality */ Date.prototype.equalsTo = function(date) {

 return ((this.getFullYear() == date.getFullYear()) &&
   (this.getMonth() == date.getMonth()) &&
   (this.getDate() == date.getDate()) &&
   (this.getHours() == date.getHours()) &&
   (this.getMinutes() == date.getMinutes()));

}; /** Set only the year, month, date parts (keep existing time) */ Date.prototype.setDateOnly = function(date) {

 var tmp = new Date(date);
 this.setDate(1);
 this.setFullYear(tmp.getFullYear());
 this.setMonth(tmp.getMonth());
 this.setDate(tmp.getDate());

}; /** Prints the date in a string according to the given format. */ Date.prototype.print = function (str) {

 var m = this.getMonth();
 var d = this.getDate();
 var y = this.getFullYear();
 var wn = this.getWeekNumber();
 var w = this.getDay();
 var s = {};
 var hr = this.getHours();
 var pm = (hr >= 12);
 var ir = (pm) ? (hr - 12) : hr;
 var dy = this.getDayOfYear();
 if (ir == 0)
   ir = 12;
 var min = this.getMinutes();
 var sec = this.getSeconds();
 s["%a"] = Calendar._SDN[w]; // abbreviated weekday name [FIXME: I18N]
 s["%A"] = Calendar._DN[w]; // full weekday name
 s["%b"] = Calendar._SMN[m]; // abbreviated month name [FIXME: I18N]
 s["%B"] = Calendar._MN[m]; // full month name
 // FIXME: %c : preferred date and time representation for the current locale
 s["%C"] = 1 + Math.floor(y / 100); // the century number
 s["%d"] = (d < 10) ? ("0" + d) : d; // the day of the month (range 01 to 31)
 s["%e"] = d; // the day of the month (range 1 to 31)
 // FIXME: %D : american date style: %m/%d/%y
 // FIXME: %E, %F, %G, %g, %h (man strftime)
 s["%H"] = (hr < 10) ? ("0" + hr) : hr; // hour, range 00 to 23 (24h format)
 s["%I"] = (ir < 10) ? ("0" + ir) : ir; // hour, range 01 to 12 (12h format)
 s["%j"] = (dy < 100) ? ((dy < 10) ? ("00" + dy) : ("0" + dy)) : dy; // day of the year (range 001 to 366)
 s["%k"] = hr;    // hour, range 0 to 23 (24h format)
 s["%l"] = ir;    // hour, range 1 to 12 (12h format)
 s["%m"] = (m < 9) ? ("0" + (1+m)) : (1+m); // month, range 01 to 12
 s["%M"] = (min < 10) ? ("0" + min) : min; // minute, range 00 to 59
 s["%n"] = "\n";    // a newline character
 s["%p"] = pm ? "PM" : "AM";
 s["%P"] = pm ? "pm" : "am";
 // FIXME: %r : the time in am/pm notation %I:%M:%S %p
 // FIXME: %R : the time in 24-hour notation %H:%M
 s["%s"] = Math.floor(this.getTime() / 1000);
 s["%S"] = (sec < 10) ? ("0" + sec) : sec; // seconds, range 00 to 59
 s["%t"] = "\t";    // a tab character
 // FIXME: %T : the time in 24-hour notation (%H:%M:%S)
 s["%U"] = s["%W"] = s["%V"] = (wn < 10) ? ("0" + wn) : wn;
 s["%u"] = w + 1;  // the day of the week (range 1 to 7, 1 = MON)
 s["%w"] = w;    // the day of the week (range 0 to 6, 0 = SUN)
 // FIXME: %x : preferred date representation for the current locale without the time
 // FIXME: %X : preferred time representation for the current locale without the date
 s["%y"] = ("" + y).substr(2, 2); // year without the century (range 00 to 99)
 s["%Y"] = y;    // year with the century
 s["%%"] = "%";    // a literal "%" character
 var re = /%./g;
 if (!Calendar.is_ie5 && !Calendar.is_khtml)
   return str.replace(re, function (par) { return s[par] || par; });
 var a = str.match(re);
 for (var i = 0; i < a.length; i++) {
   var tmp = s[a[i]];
   if (tmp) {
     re = new RegExp(a[i], "g");
     str = str.replace(re, tmp);
   }
 }
 return str;

}; Date.prototype.__msh_oldSetFullYear = Date.prototype.setFullYear; Date.prototype.setFullYear = function(y) {

 var d = new Date(this);
 d.__msh_oldSetFullYear(y);
 if (d.getMonth() != this.getMonth())
   this.setDate(28);
 this.__msh_oldSetFullYear(y);

}; // END: DATE OBJECT PATCHES

// global object that remembers the calendar window._dynarch_popupCalendar = null;

 </script>
 
 <script type="text/javascript">

// ** I18N // Calendar EN language // Author: Mihai Bazon, <mihai_bazon@yahoo.ru> // Encoding: any // Distributed under the same terms as the calendar itself. // For translators: please use UTF-8 if possible. We strongly believe that // Unicode is the answer to a real internationalized world. Also please // include your contact information in the header, as can be seen above. // full day names Calendar._DN = new Array ("Sunday",

"Monday",
"Tuesday",
"Wednesday",
"Thursday",
"Friday",
"Saturday",
"Sunday");

// Please note that the following array of short day names (and the same goes // for short month names, _SMN) isn"t absolutely necessary. We give it here // for exemplification on how one can customize the short day names, but if // they are simply the first N letters of the full name you can simply say: // // Calendar._SDN_len = N; // short day name length // Calendar._SMN_len = N; // short month name length // // If N = 3 then this is not needed either since we assume a value of 3 if not // present, to be compatible with translation files that were written before // this feature. // short day names Calendar._SDN = new Array ("Sun",

"Mon",
"Tue",
"Wed",
"Thu",
"Fri",
"Sat",
"Sun");

// First day of the week. "0" means display Sunday first, "1" means display // Monday first, etc. Calendar._FD = 0; // full month names Calendar._MN = new Array ("January",

"February",
"March",
"April",
"May",
"June",
"July",
"August",
"September",
"October",
"November",
"December");

// short month names Calendar._SMN = new Array ("Jan",

"Feb",
"Mar",
"Apr",
"May",
"Jun",
"Jul",
"Aug",
"Sep",
"Oct",
"Nov",
"Dec");

// tooltips Calendar._TT = {}; Calendar._TT["INFO"] = "About the calendar"; Calendar._TT["ABOUT"] = "DHTML Date/Time Selector\n" + "(c) dynarch.ru 2002-2005 / Author: Mihai Bazon\n" + // don"t translate this this ;-) "For latest version visit: http://www.dynarch.ru/projects/calendar/\n" + "Distributed under GNU LGPL. See http://gnu.org/licenses/lgpl.html for details." + "\n\n" + "Date selection:\n" + "- Use the \xab, \xbb buttons to select year\n" + "- Use the " + String.fromCharCode(0x2039) + ", " + String.fromCharCode(0x203a) + " buttons to select month\n" + "- Hold mouse button on any of the above buttons for faster selection."; Calendar._TT["ABOUT_TIME"] = "\n\n" + "Time selection:\n" + "- Click on any of the time parts to increase it\n" + "- or Shift-click to decrease it\n" + "- or click and drag for faster selection."; Calendar._TT["PREV_YEAR"] = "Prev. year (hold for menu)"; Calendar._TT["PREV_MONTH"] = "Prev. month (hold for menu)"; Calendar._TT["GO_TODAY"] = "Go Today"; Calendar._TT["NEXT_MONTH"] = "Next month (hold for menu)"; Calendar._TT["NEXT_YEAR"] = "Next year (hold for menu)"; Calendar._TT["SEL_DATE"] = "Select date"; Calendar._TT["DRAG_TO_MOVE"] = "Drag to move"; Calendar._TT["PART_TODAY"] = " (today)"; // the following is to inform that "%s" is to be the first day of week // %s will be replaced with the day name. Calendar._TT["DAY_FIRST"] = "Display %s first"; // This may be locale-dependent. It specifies the week-end days, as an array // of comma-separated numbers. The numbers are from 0 to 6: 0 means Sunday, 1 // means Monday, etc. Calendar._TT["WEEKEND"] = "0,6"; Calendar._TT["CLOSE"] = "Close"; Calendar._TT["TODAY"] = "Today"; Calendar._TT["TIME_PART"] = "(Shift-)Click or drag to change value"; // date formats Calendar._TT["DEF_DATE_FORMAT"] = "%Y-%m-%d"; Calendar._TT["TT_DATE_FORMAT"] = "%a, %b %e"; Calendar._TT["WK"] = "wk"; Calendar._TT["TIME"] = "Time:";

 </script>
 
 <script type="text/javascript">

/* Copyright Mihai Bazon, 2002, 2003 | http://dynarch.ru/mishoo/

* ---------------------------------------------------------------------------
*
* The DHTML Calendar
*
* Details and latest version at:
* http://dynarch.ru/mishoo/calendar.epl
*
* This script is distributed under the GNU Lesser General Public License.
* Read the entire license text here: http://www.gnu.org/licenses/lgpl.html
*
* This file defines helper functions for setting up the calendar.  They are
* intended to help non-programmers get a working calendar on their site
* quickly.  This script should not be seen as part of the calendar.  It just
* shows you what one can do with the calendar, while in the same time
* providing a quick and simple method for setting it up.  If you need
* exhaustive customization of the calendar creation process feel free to
* modify this code to suit your needs (this is recommended and much better
* than modifying calendar.js itself).
*/

// $Id: calendar-setup.js,v 1.25 2005/03/07 09:51:33 mishoo Exp $ /**

*  This function "patches" an input field (or other element) to use a calendar
*  widget for date selection.
*
*  The "params" is a single object that can have the following properties:
*
*    prop. name   | description
*  -------------------------------------------------------------------------------------------------
*   inputField    | the ID of an input field to store the date
*   displayArea   | the ID of a DIV or other element to show the date
*   button        | ID of a button or other element that will trigger the calendar
*   eventName     | event that will trigger the calendar, without the "on" prefix (default: "click")
*   ifFormat      | date format that will be stored in the input field
*   daFormat      | the date format that will be used to display the date in displayArea
*   singleClick   | (true/false) wether the calendar is in single click mode or not (default: true)
*   firstDay      | numeric: 0 to 6.  "0" means display Sunday first, "1" means display Monday first, etc.
*   align         | alignment (default: "Br"); if you don"t know what"s this see the calendar documentation
*   range         | array with 2 elements.  Default: [1900, 2999] -- the range of years available
*   weekNumbers   | (true/false) if it"s true (default) the calendar will display week numbers
*   flat          | null or element ID; if not null the calendar will be a flat calendar having the parent with the given ID
*   flatCallback  | function that receives a JS Date object and returns an URL to point the browser to (for flat calendar)
*   disableFunc   | function that receives a JS Date object and should return true if that date has to be disabled in the calendar
*   onSelect      | function that gets called when a date is selected.  You don"t _have_ to supply this (the default is generally okay)
*   onClose       | function that gets called when the calendar is closed.  [default]
*   onUpdate      | function that gets called after the date is updated in the input field.  Receives a reference to the calendar.
*   date          | the date that the calendar will be initially displayed to
*   showsTime     | default: false; if true the calendar will include a time selector
*   timeFormat    | the time format; can be "12" or "24", default is "12"
*   electric      | if true (default) then given fields/date areas are updated for each move; otherwise they"re updated only on close
*   step          | configures the step of the years in drop-down boxes; default: 2
*   position      | configures the calendar absolute position; default: null
*   cache         | if "true" (but default: "false") it will reuse the same calendar object, where possible
*   showOthers    | if "true" (but default: "false") it will show days from other months too
*
*  None of them is required, they all have default values.  However, if you
*  pass none of "inputField", "displayArea" or "button" you"ll get a warning
*  saying "nothing to setup".
*/

Calendar.setup = function (params) {

 function param_default(pname, def) { if (typeof params[pname] == "undefined") { params[pname] = def; } };
 param_default("inputField",     null);
 param_default("displayArea",    null);
 param_default("button",         null);
 param_default("eventName",      "click");
 param_default("ifFormat",       "%Y/%m/%d");
 param_default("daFormat",       "%Y/%m/%d");
 param_default("singleClick",    true);
 param_default("disableFunc",    null);
 param_default("dateStatusFunc", params["disableFunc"]);  // takes precedence if both are defined
 param_default("dateText",       null);
 param_default("firstDay",       null);
 param_default("align",          "Br");
 param_default("range",          [1900, 2999]);
 param_default("weekNumbers",    true);
 param_default("flat",           null);
 param_default("flatCallback",   null);
 param_default("onSelect",       null);
 param_default("onClose",        null);
 param_default("onUpdate",       null);
 param_default("date",           null);
 param_default("showsTime",      false);
 param_default("timeFormat",     "24");
 param_default("electric",       true);
 param_default("step",           2);
 param_default("position",       null);
 param_default("cache",          false);
 param_default("showOthers",     false);
 param_default("multiple",       null);
 var tmp = ["inputField", "displayArea", "button"];
 for (var i in tmp) {
   if (typeof params[tmp[i]] == "string") {
     params[tmp[i]] = document.getElementById(params[tmp[i]]);
   }
 }
 if (!(params.flat || params.multiple || params.inputField || params.displayArea || params.button)) {
   alert("Calendar.setup:\n  Nothing to setup (no fields found).  Please check your code");
   return false;
 }
 function onSelect(cal) {
   var p = cal.params;
   var update = (cal.dateClicked || p.electric);
   if (update && p.inputField) {
     p.inputField.value = cal.date.print(p.ifFormat);
     if (typeof p.inputField.onchange == "function")
       p.inputField.onchange();
   }
   if (update && p.displayArea)
     p.displayArea.innerHTML = cal.date.print(p.daFormat);
   if (update && typeof p.onUpdate == "function")
     p.onUpdate(cal);
   if (update && p.flat) {
     if (typeof p.flatCallback == "function")
       p.flatCallback(cal);
   }
   if (update && p.singleClick && cal.dateClicked)
     cal.callCloseHandler();
 };
 if (params.flat != null) {
   if (typeof params.flat == "string")
     params.flat = document.getElementById(params.flat);
   if (!params.flat) {
     alert("Calendar.setup:\n  Flat specified but can"t find parent.");
     return false;
   }
   var cal = new Calendar(params.firstDay, params.date, params.onSelect || onSelect);
   cal.showsOtherMonths = params.showOthers;
   cal.showsTime = params.showsTime;
   cal.time24 = (params.timeFormat == "24");
   cal.params = params;
   cal.weekNumbers = params.weekNumbers;
   cal.setRange(params.range[0], params.range[1]);
   cal.setDateStatusHandler(params.dateStatusFunc);
   cal.getDateText = params.dateText;
   if (params.ifFormat) {
     cal.setDateFormat(params.ifFormat);
   }
   if (params.inputField && typeof params.inputField.value == "string") {
     cal.parseDate(params.inputField.value);
   }
   cal.create(params.flat);
   cal.show();
   return false;
 }
 var triggerEl = params.button || params.displayArea || params.inputField;
 triggerEl["on" + params.eventName] = function() {
   var dateEl = params.inputField || params.displayArea;
   var dateFmt = params.inputField ? params.ifFormat : params.daFormat;
   var mustCreate = false;
   var cal = window.calendar;
   if (dateEl)
     params.date = Date.parseDate(dateEl.value || dateEl.innerHTML, dateFmt);
   if (!(cal && params.cache)) {
     window.calendar = cal = new Calendar(params.firstDay,
                  params.date,
                  params.onSelect || onSelect,
                  params.onClose || function(cal) { cal.hide(); });
     cal.showsTime = params.showsTime;
     cal.time24 = (params.timeFormat == "24");
     cal.weekNumbers = params.weekNumbers;
     mustCreate = true;
   } else {
     if (params.date)
       cal.setDate(params.date);
     cal.hide();
   }
   if (params.multiple) {
     cal.multiple = {};
     for (var i = params.multiple.length; --i >= 0;) {
       var d = params.multiple[i];
       var ds = d.print("%Y%m%d");
       cal.multiple[ds] = d;
     }
   }
   cal.showsOtherMonths = params.showOthers;
   cal.yearStep = params.step;
   cal.setRange(params.range[0], params.range[1]);
   cal.params = params;
   cal.setDateStatusHandler(params.dateStatusFunc);
   cal.getDateText = params.dateText;
   cal.setDateFormat(dateFmt);
   if (mustCreate)
     cal.create();
   cal.refresh();
   if (!params.position)
     cal.showAtElement(params.button || params.displayArea || params.inputField, params.align);
   else
     cal.showAt(params.position[0], params.position[1]);
   return false;
 };
 return cal;

};

 </script>

</head> <body>

DHTML Calendar for the impatient

This page demonstrates how to setup a flat calendar. .

The code in this page uses a helper function defined in "calendar-setup.js". With it you can setup the calendar in minutes.


<script type="text/javascript">

 function dateChanged(calendar) {
   // Beware that this function is called even if the end-user only
   // changed the month/year.  In order to determine if a date was
   // clicked you can use the dateClicked property of the calendar:
   if (calendar.dateClicked) {
     // OK, a date was clicked, redirect to /yyyy/mm/dd/index.php
     var y = calendar.date.getFullYear();
     var m = calendar.date.getMonth();     // integer, 0..11
     var d = calendar.date.getDate();      // integer, 1..31
     // redirect...
     window.location = "/" + y + "/" + m + "/" + d + "/index.php";
   }
 };
 Calendar.setup(
   {
     flat         : "calendar-container", // ID of the parent element
     flatCallback : dateChanged           // our callback function
   }
 );

</script>

The positioning of the DIV that contains the calendar is entirely your job. For instance, the "calendar-container" DIV from this page has the following style: "float: right; margin-left: 1em; margin-bottom: 1em".

Following there is the code that has been used to create this calendar. You can find the full description of the Calendar.setup() function in the <a href="doc/html/reference.html">calendar documenation</a>.

<div style="float: right; margin-left: 1em; margin-bottom: 1em;"
id="calendar-container"></div>
<script type="text/javascript">
  function dateChanged(calendar) {
    // Beware that this function is called even if the end-user only
    // changed the month/year.  In order to determine if a date was
    // clicked you can use the dateClicked property of the calendar:
    if (calendar.dateClicked) {
      // OK, a date was clicked, redirect to /yyyy/mm/dd/index.php
      var y = calendar.date.getFullYear();
      var m = calendar.date.getMonth();     // integer, 0..11
      var d = calendar.date.getDate();      // integer, 1..31
      // redirect...
      window.location = "/" + y + "/" + m + "/" + d + "/index.php";
    }
  };
  Calendar.setup(
    {
      flat         : "calendar-container", // ID of the parent element
      flatCallback : dateChanged           // our callback function
    }
  );
</script>

</body> </html>


 </source>
   
  

<A href="http://www.wbex.ru/Code/JavaScriptDownload/jscalendar-1.0.zip">jscalendar-1.0.zip( 396 k)</a>


Displaying the Calendar

   <source lang="html4strict">

/* Mastering JavaScript, Premium Edition by James Jaworski ISBN:078212819X Publisher Sybex CopyRight 2001

  • /

<HTML> <HEAD> <TITLE>Monthly Calendar</TITLE> <SCRIPT LANGUAGE="JavaScript" ></SCRIPT> </HEAD> <BODY> <SCRIPT LANGUAGE="JavaScript"></SCRIPT> </BODY> </HTML>


 </source>
   
  


Dynamic HTML Calendar

   <source lang="html4strict">

/* JavaScript Bible, Fourth Edition by Danny Goodman John Wiley & Sons CopyRight 2001

  • /

<HTML> <HEAD> <TITLE>JavaScripted Dynamic HTML Table</TITLE> <STYLE TYPE="text/css"> TD, TH {text-align:center} </STYLE> <SCRIPT LANGUAGE="JavaScript"> /*******************

 UTILITY FUNCTIONS
                                        • /

// day of week of month"s first day function getFirstDay(theYear, theMonth){

   var firstDate = new Date(theYear,theMonth,1)
   return firstDate.getDay()

} // number of days in the month function getMonthLen(theYear, theMonth) {

   var oneDay = 1000 * 60 * 60 * 24
   var thisMonth = new Date(theYear, theMonth, 1)
   var nextMonth = new Date(theYear, theMonth + 1, 1)
   var len = Math.ceil((nextMonth.getTime() - 
       thisMonth.getTime())/oneDay)
   return len

} // create array of English month names var theMonths = ["January","February","March","April","May","June","July","August", "September","October","November","December"] // return IE4+ or W3C DOM reference for an ID function getObject(obj) {

   var theObj
   if (document.all) {
       if (typeof obj == "string") {
           return document.all(obj)
       } else {
           return obj.style
       }
   }
   if (document.getElementById) {
       if (typeof obj == "string") {
           return document.getElementById(obj)
       } else {
           return obj.style
       }
   }
   return null

} /************************

 DRAW CALENDAR CONTENTS
                                                  • /

// clear and re-populate table based on form"s selections function populateTable(form) {

   var theMonth = form.chooseMonth.selectedIndex
   var theYear = parseInt(form.chooseYear.options[form.chooseYear.selectedIndex].text)
   // initialize date-dependent variables
   var firstDay = getFirstDay(theYear, theMonth)
   var howMany = getMonthLen(theYear, theMonth)
   
   // fill in month/year in table header
   getObject("tableHeader").innerHTML = theMonths[theMonth] + 
   " " + theYear
   
   // initialize vars for table creation
   var dayCounter = 1
   var TBody = getObject("tableBody")
   // clear any existing rows
   while (TBody.rows.length > 0) {
       TBody.deleteRow(0)
   }
   var newR, newC
   var done=false
   while (!done) {
       // create new row at end
       newR = TBody.insertRow(TBody.rows.length)
       for (var i = 0; i < 7; i++) {
           // create new cell at end of row
           newC = newR.insertCell(newR.cells.length)
           if (TBody.rows.length == 1 && i < firstDay) {
               // no content for boxes before first day
               newC.innerHTML = ""    
               continue
           }
           if (dayCounter == howMany) {
               // no more rows after this one
               done = true
           }
           // plug in date (or empty for boxes after last day)
           newC.innerHTML = (dayCounter <= howMany) ? 
               dayCounter++ : ""
       }
       
   }

} /*******************

 INITIALIZATIONS
                                        • /

// create dynamic list of year choices function fillYears() {

   var today = new Date()
   var thisYear = today.getFullYear()
   var yearChooser = document.dateChooser.chooseYear
   for (i = thisYear; i < thisYear + 5; i++) {
       yearChooser.options[yearChooser.options.length] = new Option(i, i)
   }
   setCurrMonth(today)

} // set month choice to current month function setCurrMonth(today) {

   document.dateChooser.chooseMonth.selectedIndex = today.getMonth()

} </SCRIPT> </HEAD> <BODY onLoad="fillYears(); populateTable(document.dateChooser)">

Month at a Glance (Dynamic HTML)


<TBODY ID="tableBody"></TBODY>

SunMonTueWed ThuFriSat

<FORM NAME="dateChooser"> <SELECT NAME="chooseMonth" onChange="populateTable(this.form)"> <OPTION SELECTED>January<OPTION>February <OPTION>March<OPTION>April<OPTION>May <OPTION>June<OPTION>July<OPTION>August <OPTION>September<OPTION>October <OPTION>November<OPTION>December </SELECT> <SELECT NAME="chooseYear" onChange="populateTable(this.form)"> </SELECT> </FORM>

</BODY> </HTML>


 </source>
   
  


Event Calendar

   <source lang="html4strict">

<HTML> <HEAD>

<SCRIPT LANGUAGE="JAVASCRIPT"> /********************************************************** The Object-Oriented Events Calendar

       Version 3.0
Copyright (c) 1999 --  Edward Narkiewicz
               ednark@wm.edu

Created for The Gay Student Union @ The College of William and Mary This should include calendar.js, events.js, and the GPL

   This program is free software; you can redistribute it and/or modify
   it under the terms of the GNU General Public License as published by
   the Free Software Foundation; either version 2 of the License, or
   (at your option) any later version.
   This program is distributed in the hope that it will be useful,
   but WITHOUT ANY WARRANTY; without even the implied warranty of
   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
   GNU General Public License for more details.
   You should have received a copy of the GNU General Public License
   along with this program; if not, write to the Free Software
   Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
                                                                                                                    • /
 /**********************************************************
         set Colors for Calendar
                               Empty is transparent or page deafult
 **********************************************************/
    var titleBackgroundColor = "#8080FF";
    var titleFontColor = "#FFFFFF";
    var daysofweekBackgroundColor = "#8080FF";
    var daysofweekFontColor = "#FFFFFF";
 var blankBackgroundColor = "";
 var blankFontColor = ""
 var blankString = " ";
 var pastBackgroundColor = "#C0C0FF";
 var pastFontColor = "#FFFFFF";
 var presentBackgroundColor = "#0000FF";
 var presentFontColor = "#FFFFFF";
 var futureBackgroundColor = "#A0A0FF";
 var futureFontColor = "#FFFFFF";
 var eventLinkColor = "#FF0000";
 /**********************************************************
         set Colors for PopupWindow
                               Empty is transparent or page deafult
 **********************************************************/
 var monthBackgroundColor = "#0000FF";
 var monthFontColor = "#FFFFFF";
 var nameBackgroundColor = "#8080FF";
 var nameFontColor = "#000000";
 var timeBackgroundColor = "#A0A0FF";
 var timeFontColor = "#000000";
 var locationBackgroundColor = "#A0A0FF";
 var locationFontColor = "#000000";
 var descriptionBackgroundColor = "#C0C0FF";
 var descriptionFontColor = "#000000";
 /**********************************************************
   Create StyleSheet for Color Scheme
 **********************************************************/
 var css = "";
 css += "<STYLE type="text/css"></STYLE> \n";
 document.writeln(css);

/**********************************************************

A bit of global knowledge our program should have
                                                                                                                    • /

var fullNameOfMonth = new Array( "January", "February", "March",

           "April", "May", "June", "July",
           "August", "September", "October",
           "November", "December" );

var shortNameOfMonth = new Array( "Jan", "Feb", "Mar",

                   "Apr", "May", "Jun", "Jul",
                 "Aug", "Sep", "Oct",
                 "Nov", "Dec" );

var daysInMonth = new Array( 31, 28, 31, 30, 31, 30,

         31, 31, 30, 31, 30, 31 );

var fullDayOfWeek = new Array( "Sunday", "Monday", "Tuesday",

                              "Wednesday", "Thursday",
                              "Friday", "Saturday");

var shortDayOfWeek = new Array( "Sun", "Mon", "Tue", "Wed",

           "Thr", "Fri", "Sat");

/**********************************************************

EVENT LIST DEFINITION
       In concept this is an EventList Object but...
       There is no need to make this it"s own object
       since there will only ever be one list in this version.
       You only get the array and the addition function...
                                                                                                                    • /

var Events = new Array(); /**********************************************************

EVENT CONSTRUCTOR DEFINITION
       var <event> = new CalendarEvent(YYYY,MM,DD);
       <event>.name = <name string>;
       <event>.time = 
                                                                                                                    • /

function CalendarEvent(year,month,day) {

 /**********************************************************
                       Date defaults will be given to the current day to save
                        us from any possible errors later on...
      **********************************************************/
       var now = new Date();     ///  format :: Wed Dec 13 06:49:08 GMT-0800 (Pacific Standard Time) 2000
       this.year = now.getYear();     /// # years from 1900
       if( this.year < 1000 ) /// if it gives less than 4 digits
       {
         if(this.year > 90) /// if it"s somewhere in the 1990"s
         {
           this.year += 1900
         }
         else /// it"s after 2000
         {
           this.year += 2000
         }
       }
       if( year)
       {
               this.year = year;
       }
       this.month = now.getMonth()+1; // 1->12
       if( month )
       {
               this.month = month;
       }
       this.day = now.getDate();
       if( day )
       {
               this.day = day;
       }
 /**********************************************************
   Specific information will be entered by directly
   accessing these variables... no need to hassle
   over method calls to do this.. but for clarity they
   will have to be called spereately
      **********************************************************/
       this.name = "";
       this.time = "";
       this.location = "";
       this.description = "";

}

/********************************************************** <event>.addEvent();

       this just adds the event to a list so we
       know where to look for it when we are
       writing the calendar
                                                                                                                    • /

CalendarEvent.prototype.addEvent = function() {

       /**********************************************************
       Regular Expression Check.. we want to enter items into the
       array in a very specific yyyyMMdd format... so we can access
       them easily... to do this we need to make sure the month
       and day are in two digit format...
       im going to assume the year is in 4 digit format... i don"t
       know how to fix it if it isn"t... so i"ll just pretend it will never
       happen                 :)
               if the month or day is not in Digit Digit format...
               assume it is [0...9] and add a prefix of 0... i would
               just check ( < 10 ) but i don"t know if 09 is equivelant
               to 9 in this situation and we don"t want two leaeding 0"s.
               the  <digit> + "" + <digit>
               is to make sure javascript concatenates as the string
               as opposed to adding the two as a number.
       **********************************************************/
       if( !( /^\d\d$/.test(this.month) ) )
       {
               this.month = 0 + "" + this.month;
       }
       if( !( /^\d\d$/.test(this.day) ) )
       {
               this.day = 0 + "" + this.day;
       }
       var arrayLocation = this.year + "" + this.month + "" + this.day;
       if( Events[arrayLocation] )
       {
               var size = Events[arrayLocation].length;
               Events[arrayLocation][size] = this;
       } else {
               Events[arrayLocation] = new Array();
               Events[arrayLocation][0] = this;
       }

}

/**********************************************************

CALENDER CONSTRUCTOR DEFINITION
 var <name1> = new CalendarMonth()        //--> grabs current month in current year
 var <name2> = new CalendarMonth(2004)    //--> grabs current month in year 2004
 var <name3> = new CalendarMonth(2001,01) //--> grabs january in 2001
 <name1>.changeDay(-1)      //--> moves the date to yesterday
 <name2>.changeDay(1)        //--> moves the date to tomorrow 2004
 <name1>.changeMonth(-1)      //--> moves month back one, to last month
 <name2>.changeMonth(1)      //--> moves to next month in the year 2004
 <name3>.changeYear(-1)      //--> moves to january 2000
 <name1>.changeYear(1)      //--> moves to this month next year
  <name1>.displaymonth();      //--> displays themonth
                                                                                                                    • /

function CalendarMonth(year,month) {

 /**********************************************************
  Get Calendar"s Date (with corrections for Leap year and Y2k)
  Defaults to current month and day...
      **********************************************************/
 var now = new Date();        /// format :: Wed Dec 13 06:49:08 GMT-0800 (Pacific Standard Time) 2000
 this.month = now.getMonth(); /// 0->11
 this.year = now.getYear();   /// # years from 1900
 this.isLeapYear = 0;       /// boolean set by program
 if( this.year < 1000 ) /// if it gives less than 4 digits
 {
   if(this.year > 90) /// if it"s somewhere in the 1990"s
   {
     this.year += 1900
   }
   else /// it"s after 2000
   {
     this.year += 2000
   }
 }
 this.dayOfWeek = now.getDay();
 this.dayOfMonth = now.getDate();
 /**********************************************************
  From the current day of the week, we can determine what
  day of the week the 1st of the month is on (sun->sat).
  Not very straight-forward.
      **********************************************************/
 this.firstOfMonth = ( this.dayOfWeek - ( this.dayOfMonth % 7 ) ) + 1;
   if( this.firstOfMonth < 0 )
   {
     this.firstOfMonth += 7;
   }
 this.lastOfMonth = ( this.firstOfMonth + ( daysInMonth[this.month] % 7 ) ) - 1;
   if( this.lastOfMonth > 6 )
   {
     this.lastOfMonth -= 7;
   }
 /**********************************************************
   if the user has specified a year or month or day
                  in the parameters, change to that date
      **********************************************************/
               if( year)
               {
                       this.changeYear( year - this.year );
                       if( month )
                       {
                               this.changeMonth( (month-1) - this.month );
                       }
               }

} /**********************************************************

CALENDER METHOD DEFINITIONS
                                                                                                                    • /

/**********************************************************

<calendar>.debugInfo()
 Shows all basic object info for debug purposes
                                                                                                                    • /

CalendarMonth.prototype.debugInfo = function() {

       var debug = " \n ";
       debug += "
\nYear = " + this.year; debug += "
\n Month = " + this.month; debug += "
\n Day of Month= " + this.dayOfMonth; debug += "
\n Leap Year? " + this.isLeapYear; debug += "
\n Today\"s Day of Week = " + this.dayOfWeek; debug += "
\n First of Month = " + this.firstOfMonth; debug += "
\n Last Of Month = " + this.lastOfMonth; document.writeln(debug);

} /**********************************************************

<calendar>.correctForLeapYear()
 Sets the number of days in february correctly
                                                                                                                    • /

CalendarMonth.prototype.correctForLeapYear = function() {

 /**********************************************************
   Just some stupid rules I found somewhere.
   I think/hope they are right.
 **********************************************************/
 if(this.year%4 != 0)
 {
   daysInMonth[1] = 28;
   this.isLeapYear = 0;
 }
 else if(this.year%400 == 0)
 {
   daysInMonth[1] = 29;
   this.isLeapYear = 1;
 }
 else if(this.year%100 == 0)
 {
   daysInMonth[1] = 28;
   this.isLeapYear = 0;
 }
 else
 {
   daysInMonth[1] = 29;
   this.isLeapYear = 1;
 }

}

/**********************************************************

<calendar>.lastYear()
 Changes Year back by one.
 just calls changeMonth(-12)
                                                                                                                    • /

CalendarMonth.prototype.lastYear = function() {

 this.changeMonth(-12);

} /**********************************************************

<calendar>.nextYear()
 Changes Year forward by one.
 just calls changeMonth(12)
                                                                                                                    • /

CalendarMonth.prototype.nextYear = function() {

 this.changeMonth(12);

} /**********************************************************

<calendar>.changeYear(x)
 Changes current month by x months.
 Foreward for positive x.
 Backwards for negative X.
                                                                                                                    • /

CalendarMonth.prototype.changeYear = function(x) {

 /**********************************************************
  Just checkin for a correct function call
 **********************************************************/
 if( x )
 {
   /**********************************************************
           Call a movement function x times (regardless of sign)
   **********************************************************/
   for(var i=0; i < Math.abs(x); i++)
   {
     if(x<0)
     {
       this.lastYear();
     }
     else
     {
       this.nextYear();
     }
   }// for
 }// if

}

/**********************************************************

<calendar>.lastMonth()
 Changes Month"s info back by one.
 New info determined from current month"s info.
                                                                                                                    • /

CalendarMonth.prototype.lastMonth = function() {

 this.month--;
 /**********************************************************
         We must take into account a possible year change
 **********************************************************/
 if( this.month < 0 )
 {
   this.month += 12;
   this.year--;
   this.correctForLeapYear();
 }
 /**********************************************************
   Again a kinda wierd determination of the first/last
   of the month. But it works
 **********************************************************/
 this.lastOfMonth = this.firstOfMonth-1;
   if( this.lastOfMonth < 0 )
   {
       this.lastOfMonth += 7;
   }
 this.firstOfMonth = ( this.lastOfMonth - ( daysInMonth[this.month] % 7 ) ) + 1;
   if( this.firstOfMonth > 6 )
   {
     this.firstOfMonth -= 7;
   }
               this.dayOfWeek =  ( this.firstOfMonth + ( this.dayOfMonth % 7 ) ) - 1;
   if( this.dayOfWeek < 0 )
   {
     this.dayOfWeek += 7;
   }
                                 if( this.dayOfWeek > 6 )
   {
     this.dayOfWeek -= 7;
   }

} /**********************************************************

<calendar>.nextMonth()
 Changes Month"s info foreward by one.
 New info determined from current month"s info.
                                                                                                                    • /

CalendarMonth.prototype.nextMonth = function() {

 this.month++;
 /**********************************************************
   We must take into account a possible year change
 **********************************************************/
 if( this.month > 11 )
 {
   this.month -= 12;
   this.year++;
   this.correctForLeapYear();
 }
 /**********************************************************
   Again a kinda wierd determination of the first/last
   of the month. But it works
 **********************************************************/
 this.firstOfMonth = this.lastOfMonth+1;
   if( this.firstOfMonth > 6 )
   {
       this.firstOfMonth -= 7;
   }
 this.lastOfMonth = ( this.firstOfMonth + ( daysInMonth[this.month] % 7 ) ) - 1;
   if( this.firstOfMonth < 0 )
   {
     this.firstOfMonth += 7;
   }
               this.dayOfWeek = ( this.firstOfMonth + ( this.dayOfMonth % 7 ) ) - 1;
   if( this.dayOfWeek < 0 )
   {
     this.dayOfWeek += 7;
   }
                                 if( this.dayOfWeek > 6 )
   {
     this.dayOfWeek -= 7;
   }

} /**********************************************************

<calendar>.changeMonth(x)
 Changes current month by x months.
 Foreward for positive x.
 Backwards for negative X.
                                                                                                                    • /

CalendarMonth.prototype.changeMonth = function(x) {

 /**********************************************************
   Just checkin for a correct function call
 **********************************************************/
 if( x )
 {
   /**********************************************************
     Call a movement function x times (regardless of sign)
   **********************************************************/
   for(var i=0; i < Math.abs(x); i++)
   {
     if(x<0)
     {
       this.lastMonth();
     }
     else
     {
       this.nextMonth();
     }
   }//for
 }//if

} /**********************************************************

<calendar>.yesterday()
 Changes Days back by one.
                                                                                                                    • /

CalendarMonth.prototype.yesterday = function() {

 this.dayOfMonth--;
 /**********************************************************
   We must take into account a possible month change
 **********************************************************/
 if( this.dayOfMonth < 0 )
 {
   this.lastMonth();
   this.dayOfMonth = daysInMonth[this.month];
 }

} /**********************************************************

<calendar>.tomorrow()
 Changes Day forward by one.
                                                                                                                    • /

CalendarMonth.prototype.tomorrow = function() {

 this.dayOfMonth++;
 /**********************************************************
   We must take into account a possible month change
 **********************************************************/
 if( this.dayOfMonth > daysinMonth[this.month] )
 {
   this.nextMonth();
   this.dayOfMonth = 1;
 }

} /**********************************************************

<calendar>.changeDay(x)
 Changes current month by x months.
 Foreward for positive x.
 Backwards for negative X.
                                                                                                                    • /

CalendarMonth.prototype.changeDay = function(x) {

 /**********************************************************
   Just checkin for a correct function call
 **********************************************************/
 if( x )
 {
   /**********************************************************
     Call a movement function x times (regardless of sign)
   **********************************************************/
   for(var i=0; i < Math.abs(x); i++)
   {
     if(x<0)
     {
       this.yesterday();
     }
     else
     {
       this.tomorrow();
     }
   }//for
 }//if

} /**********************************************************

<calendar>.displayMonth(yyyy,m)
       Displays current month when givin no parameters
       If given 1st param in 4 digit year format.. goes to that year
       if given 2nd parameter... goes to that month...
       This prints a self-contained Table that should be positioned
       by positioning the javascript call to displayMonth() itself.
                                                                                                                    • /

CalendarMonth.prototype.displayMonth = function() {

 /**********************************************************
   Must  if we are in the past present or future...
 **********************************************************/
 var now = new Date();
 var currentDayOfMonth = now.getDate();
 var currentMonth = now.getMonth();
 var currentYear = now.getYear();
 if( currentYear < 1000 ) /// if it gives less than 4 digits
 {
   if(currentYear > 90) /// if it"s somewhere in the 1990"s
   {
     currentYear += 1900
   }
   else /// it"s after 2000
   {
     currentYear += 2000
   }
 }
 /**********************************************************
   Boolean variables for location in time...
 **********************************************************/
 var past = 0;
 var present = 1;
 var future = 0;
 if( this.year < currentYear )
 {
   past = 1;
   present = future = 0;
 }
 else if( this.year == currentYear )
 {
   if( this.month < currentMonth )
   {
     past = 1;
     present = future = 0;
   }
   else if( this.month == currentMonth )
   {
     present = 1;
     past = future = 0;
   }
   else if( this.month > currentMonth )
   {
     future = 1;
     past = present = 0;
   }
 }
 else if( this.year > currentYear )
 {
   future = 1;
   past = present = 0;
 }
 /**********************************************************
   Get correct mm format of date
 **********************************************************/
 var mm = this.month+1;
 if( !( /^\d\d$/.test(this.month+1) ) )
 {
   mm = 0 + "" + mm;
 }
 var yyyymm = this.year + "" + mm;
 /**********************************************************
   Draw the table header
 **********************************************************/
 var table = "";
table += "
"; table += " \n"; table += " \n"; table += " \n"; table += " \n"; table += " \n"; table += "<TR align="center"> \n"; /********************************************************** Draw the week"s labels **********************************************************/ for( var weekday = 0; weekday < 7; weekday++) { table += "<TD width="30" class="DayOfWeek">"; table += shortDayOfWeek[weekday]; table += "</TD> \n"; } table += "<TD class="DayOfWeek">"; table += " "; table += "</TD> \n"; table += "</TR> \n"; /********************************************************** Draw the table meat **********************************************************/ var dayCounter = 1; var startDayOfWeek; var startDate; var endDate; /********************************************************** For 6 possible weeks a month may span... think about it **********************************************************/ for( var week=1; week <= 6 && (dayCounter <= daysInMonth[this.month]); week++) { /********************************************************** Figure out the span of days to look at when viewing the whole week at a time.. different for week 1 **********************************************************/ if( week == 1 ) { startDayOfWeek = this.firstOfMonth; startDate = 1; endDate = 7-this.firstOfMonth; } else { startDayOfWeek = 0; startDate = dayCounter; endDate = ( (dayCounter+6) > daysInMonth[this.month] )? daysInMonth[this.month]:(dayCounter+6); } table += "<TR align="center"> \n"; /********************************************************** For each day of the week **********************************************************/ for( weekday = 1; weekday <= 7; weekday++) { /********************************************************** Show empty cells before and after month exists **********************************************************/ if( ((week == 1) && (weekday <= this.firstOfMonth)) || (dayCounter > daysInMonth[this.month]) ) { table += "<TD width="30" class="Blank">"; table += blankString; table += "</TD> \n"; } /********************************************************** Show the date with correct color **********************************************************/ else { var ColorScheme = "Blank"; if( past ) { ColorScheme = "Past"; } else if( present ) { if( dayCounter < currentDayOfMonth ) ///earlier this month { ColorScheme = "Past"; } else if( dayCounter == currentDayOfMonth ) ///today { ColorScheme = "Present"; } else ///later this month { ColorScheme = "Future"; } } else if( future ) { ColorScheme = "Future"; } /********************************************************** Get a two digit dd format of date **********************************************************/ var dd = dayCounter; if( !( /^\d\d$/.test(dayCounter) ) ) { dd = 0 + "" + dd; } var arrayLocation = this.year + "" + mm + "" + dd; var popup = ""; if( Events[arrayLocation] ) { popup = " class="Event" href="javascript:popupDay(" + arrayLocation + ");""; } table += "<TD width="30" class="" + ColorScheme + "">"; table += "<A " + popup + " NAME="" + this.year + "|" + mm + "|" + dayCounter + "">"; table += dayCounter; table += "</A>"; table += "</TD> \n"; dayCounter++; } } table += "<TD width="10" class="Title">"; table += "<A NAME="Week" + week + "" HREF="javascript:popupWeek(" + this.year + "," + this.month + "," + startDayOfWeek + "," + startDate + "," + endDate + ");">"; table += week table += "</A>"; table += "</TD> \n"; table += "</TR> \n"; } /********************************************************** Draw the table footer **********************************************************/ table += "</TABLE> \n"; table += "</DIV> \n"; /// this.debugInfo(); document.writeln(table); } /******************************************************** Event Window used by all popup functions
                                                                                                                  • /
var eventWindow; /******************************************************** popupDay() this function displays a single days events in one newly created window. *********************************************************/ function popupDay( date ) { eventWindow = window.open("","CalendarPopup","width=300,height=330,scrollbars"); /******************************************************** Some Regular expression magic to make YYYYMMDD = YYYY + MM + DD *********************************************************/ date = date + ""; var yyyymmdd = new Array(); yyyymmdd = date.match( /(^\d\d\d\d)(\d\d)(\d\d)/ ); var year= yyyymmdd[1]; var month = yyyymmdd[2]; var day = yyyymmdd[3]; /******************************************************** Some Definitions of the Color Scheme *********************************************************/ var css = ""; css += "<STYLE type="text/css"></STYLE> \n"; /******************************************************** Start page with the close/print buttons *********************************************************/ var popup = ""; popup += "<form> \n"; popup += "<input type="button" value="Close" onClick="self.close();"> \n"; popup += "  &nbsp \n"; popup += "<input type="button" value="Print" onClick="self.print();"> \n"; popup += "</form> \n"; /******************************************************** Display the name of the month at the top *********************************************************/ popup += "
";
 table += "<A NAME="" + yyyymm + "">";
 table +=  fullNameOfMonth[this.month] + ", " + this.year;
 table += "</A>";
table += "
<A HREF="javascript:popupMonth(" + this.year + "," + this.month + ", " + this.firstOfMonth + ")">";
 table += "view all";
table += "</a>
</B>
\n"; popup += " \n";
 /********************************************************
   For each Event that exists for today, display it
 *********************************************************/
 var limit = Events[date].length;
 for( i=0; i < limit;  i++ )
 {
popup += " \n"; popup += " \n" ; popup += " \n";
 }//for
popup += "
" + fullNameOfMonth[month-1] + ", " + day + "  " + year + "
" + Events[date][i].name + "
" + Events[date][i].time + ", " + Events[date][i].location + "
" + Events[date][i].description + "
\n";
 /********************************************************
   Make the call to actually write popup to the new window
   be sure to close the file when you are done
 *********************************************************/
 eventWindow.document.write(css);
 eventWindow.document.write(popup);
 eventWindow.document.close();
 eventWindow.focus();
 return;

} /********************************************************

popupWeek()
 this function displays a weeks events in
 one newly created window.
*********************************************************/

function popupWeek( year, month, startDayOfWeek, startDate, endDate ) {

 /********************************************************
   If the month is not in two digits, make it two digits
 *********************************************************/
 if( !( /^\d\d$/.test(month+1) ) )
 {
   mm = 0 + "" + (month+1);
 } else {
   mm = (month+1);
 }
 /********************************************************
   Open a new window with only scrollbars
 *********************************************************/
 eventWindow = window.open("","CalendarPopup","scrollbars");
 var popup = "";
 popup += "<form> \n";
 popup += "<input type="button" value="Close" onClick="self.close();"> \n";
 popup += "  &nbsp \n";
 popup += "<input type="button" value="Print" onClick="self.print();"> \n";
 popup += "</form> \n";
 /********************************************************
   Write full name of month at top
 *********************************************************/
popup += " \n"; popup += " \n";
 /********************************************************
   For each day in the week write it"s name
 *********************************************************/
 var day = startDate;
popup += ""; for( i=0; (i < 7); i++) { popup += ""; }//for popup += ""; /******************************************************** For each day in the week.. write all of its events *********************************************************/ day = startDate; popup += ""; for( i=0; (i < 7); i++, day++) { /******************************************************** Make sure the day is in two digits so we can access Events array *********************************************************/ if( !( /^\d\d$/.test(day) ) ) { dd = 0 + "" + day; } else { dd = day; } date = year + "" + mm + "" + dd; popup += " \n"; }//for popup += ""; popup += "
" + fullNameOfMonth[month] + ", " + year + "
";
   popup += fullDayOfWeek[i];
   if( (i >= startDayOfWeek) && (day <= daysInMonth[month]) )
   {
     popup += ", " + day;
     day++;
   } else {
     popup += " ";
   }
popup += "
\n"; popup += " \n"; /******************************************************** Write out each event for each day of the week *********************************************************/ if( Events[date] ) { var limit = Events[date].length; for( var j = 0; j < limit; j++ ) { popup += " \n"; popup += " \n" ; popup += " \n";
     }//for
   }
popup += " \n"; popup += "
" + Events[date][j].name + "
" + Events[date][j].time + ", " + Events[date][j].location + "
" + Events[date][j].description + "
 
\n"; popup += "
\n";
 /********************************************************
   Write the css the popup calendar then close the document    
 *********************************************************/
 eventWindow.document.write(css);
 eventWindow.document.write(popup);
 eventWindow.document.close();
 eventWindow.focus();
 return;

} /**********************************************************

popupMonth()
 this function displays a whole month"s events in
 one newly created window.
                                                                                                                    • /

function popupMonth( year, month, startDayOfMonth ) {

 /********************************************************
   If the month is not in two digits, make it two digits
 *********************************************************/
 if( !( /^\d\d$/.test(month+1) ) )
 {
   mm = 0 + "" + (month+1);
 } else {
   mm = (month+1);
 }
 /********************************************************
   Open a new window with only scrollbars
 *********************************************************/
 eventWindow = window.open("","CalendarPopup","scrollbars");
 /********************************************************
   Open a new window with only scrollbars
 *********************************************************/
 var popup = "";
 popup += "<form> \n";
 popup += "<input type="button" value="Close" onClick="self.close();"> \n";
 popup += "  &nbsp \n";
 popup += "<input type="button" value="Print" onClick="self.print();"> \n";
 popup += "</form> \n";
popup += " \n"; popup += " \n";
 var dayCounter = 1;
 /**********************************************************
   For 6 possible weeks a month may span... think about it
 **********************************************************/
 for( var week=1; week <= 6 && (dayCounter <= daysInMonth[month]); week++)
 {
popup += " \n"; /********************************************************** For each day of the week write the date **********************************************************/ var day = dayCounter; for( weekday = 1; weekday <= 7; weekday++) { popup += "\n"; } else { popup += fullDayOfWeek[weekday-1] + ", " + day; popup += "</B></TD>\n"; day++; }//ifelse }//for weekday popup += " \n"; popup += "<TR ALIGN="CENTER"> \n"; /********************************************************** For each day of the week write each event **********************************************************/ for( weekday = 1; weekday <= 7; weekday++) { if( !( /^\d\d$/.test(dayCounter) ) ) { dd = 0 + "" + dayCounter; } else { dd = dayCounter; } date = year + "" + mm + "" + dd; popup += "<TD CLASS="Description" WIDTH="150" ALIGN="CENTER" VALIGN="TOP"> \n"; /********************************************************** Draw events if they exists for the weekday **********************************************************/ if( ((week == 1) && (weekday <= startDayOfMonth)) || (dayCounter > daysInMonth[month]) ) { popup += " "; } else { popup += "
" + fullNameOfMonth[month] + ", " + year + "
\n";
     /**********************************************************
       Draw the date if it exists for the weekday
     **********************************************************/
     if( ((week == 1) && (weekday <= startDayOfMonth)) ||
         (day > daysInMonth[month]) )
     {
       popup += " ";
popup += "
\n"; if( Events[date] ) { var limit = Events[date].length; for( var j = 0; j < limit; j++ ) { popup += " \n"; popup += " \n" ; popup += " \n";
         }//for
       } else {
popup += "
\n";
       }
popup += "
" + Events[date][j].name + "
" + Events[date][j].time + ", " + Events[date][j].location + "
" + Events[date][j].description + "
 
\n";
       dayCounter++;
     }//ifelse
     popup += "</TD> \n";
   }//for weekday
   popup += "</TR> \n";
 }//for week
 
 popup += "</TABLE> \n";
 
 eventWindow.document.write(css);
 eventWindow.document.write(popup);
 eventWindow.document.close();
 eventWindow.focus();
 return;

} /****************************************************************************************

                                                                                                                                                                                • /

</SCRIPT>

<SCRIPT LANGUAGE="JAVASCRIPT"> var evnt = new CalendarEvent(2002,1,15); evnt.name = "NAME"; evnt.time = "TIME"; evnt.location = "LOCATION"; evnt.description = "<a href="#">DESCRIPTION</a>"; evnt.addEvent(); var evnt = new CalendarEvent(2002,1,15); evnt.name = "NAME"; evnt.time = "TIME"; evnt.location = "LOCATION"; evnt.description = "<a href="#">DESCRIPTION</a>"; evnt.addEvent(); var evnt = new CalendarEvent(2002,1,1); evnt.name = "NAME"; evnt.time = "TIME"; evnt.location = "LOCATION"; evnt.description = "DESCRIPTION"; evnt.addEvent(); var evnt = new CalendarEvent(2002,1,11); evnt.name = "NAME"; evnt.time = "TIME"; evnt.location = "LOCATION"; evnt.description = "DESCRIPTION"; evnt.addEvent(); var evnt = new CalendarEvent(2002,2,15); evnt.name = "NAME"; evnt.time = "TIME"; evnt.location = "LOCATION"; evnt.description = "DESCRIPTION"; evnt.addEvent(); var evnt = new CalendarEvent(2002,2,15); evnt.name = "NAME"; evnt.time = "TIME"; evnt.location = "LOCATION"; evnt.description = "DESCRIPTION"; evnt.addEvent(); var evnt = new CalendarEvent(2002,2,15); evnt.name = "NAME"; evnt.time = "TIME"; evnt.location = "LOCATION"; evnt.description = "DESCRIPTION"; evnt.addEvent(); var evnt = new CalendarEvent(2002,2,17); evnt.name = "NAME"; evnt.time = "TIME"; evnt.location = "LOCATION"; evnt.description = "DESCRIPTION"; evnt.addEvent(); var evnt = new CalendarEvent(2002,2,25); evnt.name = "NAME"; evnt.time = "TIME"; evnt.location = "LOCATION"; evnt.description = "DESCRIPTION"; evnt.addEvent(); var evnt = new CalendarEvent(2002,2,8); evnt.name = "NAME"; evnt.time = "TIME"; evnt.location = "LOCATION"; evnt.description = "DESCRIPTION"; evnt.addEvent(); var evnt = new CalendarEvent(2002,3,15); evnt.name = "NAME"; evnt.time = "TIME"; evnt.location = "LOCATION"; evnt.description = "DESCRIPTION"; evnt.addEvent(); var evnt = new CalendarEvent(2002,3,20); evnt.name = "NAME"; evnt.time = "TIME"; evnt.location = "LOCATION"; evnt.description = "DESCRIPTION"; evnt.addEvent();

</SCRIPT> <SCRIPT LANGUAGE="javascript">

 var Month = new Array();
 for ( var i = 2001; i < 2003; i++ ) {
   for ( var j = 1; j < 12; j++ ) {
     Month[Month.length] = new CalendarMonth(i,j);
   }
 }

</SCRIPT></HEAD> <BODY> <SCRIPT LANGUAGE="javascript">

 for ( var i = 0; i < Month.length; i++ ) {
   Month[i].displayMonth();
 }

</SCRIPT> </BODY> </HTML>


 </source>
   
  

<A href="http://www.wbex.ru/Code/JavaScriptDownload/js-events-cal.zip">js-events-cal.zip( 17 k)</a>


Fancy Calendar

   <source lang="html4strict">

<html> <head> <script type="text/javascript" language="JavaScript"> // written by Tan Ling Wee // last updated 28 July 2003 // Web Site: http://64.246.32.44/~admin59/index.htm // email : info@sparrowscripts.ru // url : www.sparrowscripts.ru // TabSize: 4 // // modified by ALQUANTO 30 July 2003 - german language included. // - modified languageLogic with the ISO-2letter-strings // - changes in in showCalendar: defaultLanguage is already set... // - js and html corrected... more xhtml-compliant... simplier css // email: popcalendar@alquanto.de // // modified by PinoToy 25 July 2003 - new logic for multiple languages (English, Spanish and ready for more). // - changes in popUpMonth & popDownMonth methods for hidding popup. // - changes in popDownYear & popDownYear methods for hidding popup. // - new logic for disabling dates in the past. // - new method showCalendar, dynamic configuration of language, enabling past & position. // - changes in the styles. // email  : pinotoy@yahoo.ru

 var language = "en";  // Default Language: en - english ; es - spanish; de - german
 var enablePast = 0;    // 0 - disabled ; 1 - enabled
 var fixedX = -1;    // x position (-1 if to appear below control)
 var fixedY = -1;    // y position (-1 if to appear below control)
 var startAt = 1;    // 0 - sunday ; 1 - monday
 var showWeekNumber = 0;  // 0 - don"t show; 1 - show
 var showToday = 1;    // 0 - don"t show; 1 - show
 var imgDir = "";    // directory for images ... e.g. var imgDir="/img/"
 var dayName = "";
 var gotoString = {
   en : "Go To Current Month",
   es : "Ir al Mes Actual",
   de : "Gehe zu aktuellem Monat"
 };
 var todayString = {
   en : "Today is",
   es : "Hoy es",
   de : "Heute ist"
 };
 var weekString = {
   en : "Wk",
   es : "Sem",
   de : "KW"
 };
 var scrollLeftMessage = {
   en : "Click to scroll to previous month. Hold mouse button to scroll automatically.",
   es : "Presione para pasar al mes anterior. Deje presionado para pasar varios meses.",
   de : "Klicken um zum vorigen Monat zu gelangen. Gedruckt halten, um automatisch weiter zu scrollen."
 };
 var scrollRightMessage = {
   en : "Click to scroll to next month. Hold mouse button to scroll automatically.",
   es : "Presione para pasar al siguiente mes. Deje presionado para pasar varios meses.",
   de : "Klicken um zum nachsten Monat zu gelangen. Gedruckt halten, um automatisch weiter zu scrollen."
 };
 var selectMonthMessage = {
   en : "Click to select a month.",
   es : "Presione para seleccionar un mes",
   de : "Klicken um Monat auszuwahlen"
 };
 var selectYearMessage = {
   en : "Click to select a year.",
   es : "Presione para seleccionar un ano",
   de : "Klicken um Jahr auszuwahlen"
 };
 var selectDateMessage = {    // do not replace [date], it will be replaced by date.
   en : "Select [date] as date.",
   es : "Seleccione [date] como fecha",
   de : "Wahle [date] als Datum."
 };
 var  monthName = {
   en : new Array("January","February","March","April","May","June","July","August","September","October","November","December"),
   es : new Array("Enero","Febrero","Marzo","Abril","Mayo","Junio","Julio","Agosto","Septiembre","Octubre","Noviembre","Diciembre"),
   de : new Array("Januar","Februar","Marz","April","Mai","Juni","Juli","August","September","Oktober","November","Dezember")
 };
 var  monthName2 = {
   en : new Array("JAN","FEB","MAR","APR","MAY","JUN","JUL","AUG","SEP","OCT","NOV","DEC"),
   es : new Array("ENE","FEB","MAR","ABR","MAY","JUN","JUL","AGO","SEP","OCT","NOV","DIC"),
   de : new Array("JAN","FEB","MRZ","APR","MAI","JUN","JUL","AUG","SEP","OKT","NOV","DEZ")
 };
 if (startAt==0) {
   dayName = {
     en : new Array("Sun","Mon","Tue","Wed","Thu","Fri","Sat"),
     es : new Array("Dom","Lun","Mar","Mie","Jue","Vie","Sab"),
     de : new Array("So","Mo","Di","Mi","Do","Fr","Sa")
   };
 } else {
   dayName = {
     en : new Array("Mon","Tue","Wed","Thu","Fri","Sat","Sun"),
     es : new Array("Lun","Mar","Mie","Jue","Vie","Sab","Dom"),
     de : new Array("Mo","Di","Mi","Do","Fr","Sa","So")
   };
 }
 var crossobj, crossMonthObj, crossYearObj, monthSelected, yearSelected, dateSelected, omonthSelected, oyearSelected, odateSelected, monthConstructed, yearConstructed, intervalID1, intervalID2, timeoutID1, timeoutID2, ctlToPlaceValue, ctlNow, dateFormat, nStartingYear, selDayAction, isPast;
 var visYear  = 0;
 var visMonth = 0;
 var bPageLoaded = false;
 var ie  = document.all;
 var dom = document.getElementById;
 var ns4 = document.layers;
 var today    = new Date();
 var dateNow  = today.getDate();
 var monthNow = today.getMonth();
 var yearNow  = today.getYear();
 var imgsrc   = new Array("drop1.gif","drop2.gif","left1.gif","left2.gif","right1.gif","right2.gif");
 var img      = new Array();
 var bShow    = false;
 /* hides <select> and <applet> objects (for IE only) */
 function hideElement( elmID, overDiv ) {
   if(ie) {
     for(i = 0; i < document.all.tags( elmID ).length; i++) {
       obj = document.all.tags( elmID )[i];
       if(!obj || !obj.offsetParent) continue;
       // Find the element"s offsetTop and offsetLeft relative to the BODY tag.
       objLeft   = obj.offsetLeft;
       objTop    = obj.offsetTop;
       objParent = obj.offsetParent;
       while(objParent.tagName.toUpperCase() != "BODY") {
         objLeft  += objParent.offsetLeft;
         objTop   += objParent.offsetTop;
         objParent = objParent.offsetParent;
       }
       objHeight = obj.offsetHeight;
       objWidth  = obj.offsetWidth;
       if((overDiv.offsetLeft + overDiv.offsetWidth) <= objLeft);
       else if((overDiv.offsetTop + overDiv.offsetHeight) <= objTop);
       /* CHANGE by Charlie Roche for nested TDs*/
       else if(overDiv.offsetTop >= (objTop + objHeight + obj.height));
       /* END CHANGE */
       else if(overDiv.offsetLeft >= (objLeft + objWidth));
       else {
         obj.style.visibility = "hidden";
       }
     }
   }
 }
 /*
 * unhides <select> and <applet> objects (for IE only)
 */
 function showElement(elmID) {
   if(ie) {
     for(i = 0; i < document.all.tags( elmID ).length; i++) {
       obj = document.all.tags(elmID)[i];
       if(!obj || !obj.offsetParent) continue;
       obj.style.visibility = "";
     }
   }
 }
 function HolidayRec (d, m, y, desc) {
   this.d = d;
   this.m = m;
   this.y = y;
   this.desc = desc;
 }
 var HolidaysCounter = 0;
 var Holidays = new Array();
 function addHoliday (d, m, y, desc) {
   Holidays[HolidaysCounter++] = new HolidayRec (d, m, y, desc);
 }
 if (dom) {
   for  (i=0;i<imgsrc.length;i++) {
     img[i] = new Image;
     img[i].src = imgDir + imgsrc[i];
   }
document.write ("");
 }
 var  styleAnchor = "text-decoration:none;color:black;";
 var  styleLightBorder = "border:1px solid #a0a0a0;";
 function swapImage(srcImg, destImg) {
   if (ie) document.getElementById(srcImg).setAttribute("src",imgDir + destImg);
 }
 function init() {
   if (!ns4)
   {
     if (!ie) yearNow += 1900;
     crossobj=(dom)?document.getElementById("calendar").style : ie? document.all.calendar : document.calendar;
     hideCalendar();
     crossMonthObj = (dom) ? document.getElementById("selectMonth").style : ie ? document.all.selectMonth : document.selectMonth;
     crossYearObj = (dom) ? document.getElementById("selectYear").style : ie ? document.all.selectYear : document.selectYear;
     monthConstructed = false;
     yearConstructed = false;
     if (showToday == 1) {
       document.getElementById("lblToday").innerHTML =  "" + todayString[language] + " <a onmousemove="window.status=\""+gotoString[language]+"\"" onmouseout="window.status=\"\"" title=""+gotoString[language]+"" style=""+styleAnchor+"" href="javascript:monthSelected=monthNow;yearSelected=yearNow;constructCalendar();">"+dayName[language][(today.getDay()-startAt==-1)?6:(today.getDay()-startAt)]+", " + dateNow + " " + monthName[language][monthNow].substring(0,3) + " " + yearNow + "</a>";
     }
     sHTML1 = "&nbsp<img id="changeLeft" src=""+imgDir+"left1.gif" width="10" height="11" border="0">&nbsp ";
     sHTML1 += "&nbsp<img id="changeRight" src=""+imgDir+"right1.gif" width="10" height="11" border="0">&nbsp ";
     sHTML1 += " ";
     sHTML1 += " ";
     document.getElementById("caption").innerHTML = sHTML1;
     bPageLoaded=true;
   }
 }
 function hideCalendar() {
   crossobj.visibility = "hidden";
   if (crossMonthObj != null) crossMonthObj.visibility = "hidden";
   if (crossYearObj  != null) crossYearObj.visibility = "hidden";
   showElement("SELECT");
   showElement("APPLET");
 }
 function padZero(num) {
   return (num  < 10) ? "0" + num : num;
 }
 function constructDate(d,m,y) {
   sTmp = dateFormat;
   sTmp = sTmp.replace ("dd","<e>");
   sTmp = sTmp.replace ("d","<d>");
   sTmp = sTmp.replace ("<e>",padZero(d));
   sTmp = sTmp.replace ("<d>",d);
sTmp = sTmp.replace ("mmmm","

"); sTmp = sTmp.replace ("mmm","<o>"); sTmp = sTmp.replace ("mm","<n>"); sTmp = sTmp.replace ("m","<m>"); sTmp = sTmp.replace ("<m>",m+1); sTmp = sTmp.replace ("<n>",padZero(m+1)); sTmp = sTmp.replace ("<o>",monthName[language][m]); sTmp = sTmp.replace ("<p>",monthName2[language][m]); sTmp = sTmp.replace ("yyyy",y); return sTmp.replace ("yy",padZero(y%100)); } function closeCalendar() { hideCalendar(); ctlToPlaceValue.value = constructDate(dateSelected,monthSelected,yearSelected); } /*** Month Pulldown ***/ function StartDecMonth() { intervalID1 = setInterval("decMonth()",80); } function StartIncMonth() { intervalID1 = setInterval("incMonth()",80); } function incMonth () { monthSelected++; if (monthSelected > 11) { monthSelected = 0; yearSelected++; } constructCalendar(); } function decMonth () { monthSelected--; if (monthSelected < 0) { monthSelected = 11; yearSelected--; } constructCalendar(); } function constructMonth() { popDownYear() if (!monthConstructed) { sHTML = ""; for (i=0; i<12; i++) { sName = monthName[language][i]; if (i == monthSelected){ sName = "<b>" + sName + "</b>"; } sHTML += "<tr><td id="m" + i + "" onmouseover="this.style.backgroundColor=\"#909090\"" onmouseout="this.style.backgroundColor=\"\"" style="cursor:pointer" onclick="monthConstructed=false;monthSelected=" + i + ";constructCalendar();popDownMonth();event.cancelBubble=true"> " + sName + " </td></tr>"; } document.getElementById("selectMonth").innerHTML = "

" + sHTML + "
";
     monthConstructed = true;
   }
 }
 function popUpMonth() {
   if (visMonth == 1) {
     popDownMonth();
     visMonth--;
   } else {
     constructMonth();
     crossMonthObj.visibility = (dom||ie) ? "visible" : "show";
     crossMonthObj.left = parseInt(crossobj.left) + 50;
     crossMonthObj.top =  parseInt(crossobj.top) + 26;
     hideElement("SELECT", document.getElementById("selectMonth"));
     hideElement("APPLET", document.getElementById("selectMonth"));
     visMonth++;
   }
 }
 function popDownMonth() {
   crossMonthObj.visibility = "hidden";
   visMonth = 0;
 }
 /*** Year Pulldown ***/
 function incYear() {
   for  (i=0; i<7; i++) {
     newYear  = (i + nStartingYear) + 1;
     if (newYear == yearSelected)
       txtYear = " " + newYear + " ";
     else
       txtYear = " " + newYear + " ";
     document.getElementById("y"+i).innerHTML = txtYear;
   }
   nStartingYear++;
   bShow=true;
 }
 function decYear() {
   for  (i=0; i<7; i++) {
     newYear = (i + nStartingYear) - 1;
     if (newYear == yearSelected)
       txtYear = " " + newYear + " ";
     else
       txtYear = " " + newYear + " ";
     document.getElementById("y"+i).innerHTML = txtYear;
   }
   nStartingYear--;
   bShow=true;
 }
 function selectYear(nYear) {
   yearSelected = parseInt(nYear + nStartingYear);
   yearConstructed = false;
   constructCalendar();
   popDownYear();
 }
 function constructYear() {
   popDownMonth();
   sHTML = "";
   if (!yearConstructed) {
     sHTML = "<tr><td align="center" onmouseover="this.style.backgroundColor=\"#909090\"" onmouseout="clearInterval(intervalID1);this.style.backgroundColor=\"\"" style="cursor:pointer" onmousedown="clearInterval(intervalID1);intervalID1=setInterval(\"decYear()\",30)" onmouseup="clearInterval(intervalID1)">-</td></tr>";
     j = 0;
     nStartingYear =  yearSelected - 3;
     for ( i = (yearSelected-3); i <= (yearSelected+3); i++ ) {
       sName = i;
       if (i == yearSelected) sName = "<b>" + sName + "</b>";
       sHTML += "<tr><td id="y" + j + "" onmouseover="this.style.backgroundColor=\"#909090\"" onmouseout="this.style.backgroundColor=\"\"" style="cursor:pointer" onclick="selectYear("+j+");event.cancelBubble=true"> " + sName + " </td></tr>";
       j++;
     }
     sHTML += "<tr><td align="center" onmouseover="this.style.backgroundColor=\"#909090\"" onmouseout="clearInterval(intervalID2);this.style.backgroundColor=\"\"" style="cursor:pointer" onmousedown="clearInterval(intervalID2);intervalID2=setInterval(\"incYear()\",30)" onmouseup="clearInterval(intervalID2)">+</td></tr>";
document.getElementById("selectYear").innerHTML = "" + sHTML + "
";
     yearConstructed = true;
   }
 }
 function popDownYear() {
   clearInterval(intervalID1);
   clearTimeout(timeoutID1);
   clearInterval(intervalID2);
   clearTimeout(timeoutID2);
   crossYearObj.visibility= "hidden";
   visYear = 0;
 }
 function popUpYear() {
   var leftOffset
   if (visYear==1) {
     popDownYear();
     visYear--;
   } else {
     constructYear();
     crossYearObj.visibility  = (dom||ie) ? "visible" : "show";
     leftOffset = parseInt(crossobj.left) + document.getElementById("spanYear").offsetLeft;
     if (ie) leftOffset += 6;
     crossYearObj.left = leftOffset;
     crossYearObj.top = parseInt(crossobj.top) + 26;
     visYear++;
   }
 }
 /*** calendar ***/
 function WeekNbr(n) {
   // Algorithm used:
   // From Klaus Tondering"s Calendar document (The Authority/Guru)
   // http://www.tondering.dk/claus/calendar.html
   // a = (14-month) / 12
   // y = year + 4800 - a
   // m = month + 12a - 3
   // J = day + (153m + 2) / 5 + 365y + y / 4 - y / 100 + y / 400 - 32045
   // d4 = (J + 31741 - (J mod 7)) mod 146097 mod 36524 mod 1461
   // L = d4 / 1460
   // d1 = ((d4 - L) mod 365) + L
   // WeekNumber = d1 / 7 + 1
   year = n.getFullYear();
   month = n.getMonth() + 1;
   if (startAt == 0) {
     day = n.getDate() + 1;
   } else {
     day = n.getDate();
   }
   a = Math.floor((14-month) / 12);
   y = year + 4800 - a;
   m = month + 12 * a - 3;
   b = Math.floor(y/4) - Math.floor(y/100) + Math.floor(y/400);
   J = day + Math.floor((153 * m + 2) / 5) + 365 * y + b - 32045;
   d4 = (((J + 31741 - (J % 7)) % 146097) % 36524) % 1461;
   L = Math.floor(d4 / 1460);
   d1 = ((d4 - L) % 365) + L;
   week = Math.floor(d1/7) + 1;
   return week;
 }
 function constructCalendar () {
   var aNumDays = Array (31,0,31,30,31,30,31,31,30,31,30,31);
   var dateMessage;
   var startDate = new Date (yearSelected,monthSelected,1);
   var endDate;
   if (monthSelected==1) {
     endDate = new Date (yearSelected,monthSelected+1,1);
     endDate = new Date (endDate - (24*60*60*1000));
     numDaysInMonth = endDate.getDate();
   } else {
     numDaysInMonth = aNumDays[monthSelected];
   }
   datePointer = 0;
   dayPointer = startDate.getDay() - startAt;
   
   if (dayPointer<0) dayPointer = 6;
sHTML = ""; if (showWeekNumber == 1) { sHTML += "";
   }
   for (i = 0; i<7; i++) {
sHTML += "";
   }
sHTML += ""; if (showWeekNumber == 1) { sHTML += "";
   }
   for  ( var i=1; i<=dayPointer;i++ ) {
sHTML += "";
   }
 
   for  ( datePointer=1; datePointer <= numDaysInMonth; datePointer++ ) {
     dayPointer++;
sHTML += ""; if ((showWeekNumber == 1) && (datePointer < numDaysInMonth)) { sHTML += "";
       }
     }
   }
   document.getElementById("content").innerHTML   = sHTML
   document.getElementById("spanMonth").innerHTML = " " +  monthName[language][monthSelected] + " <img id="changeMonth" src=""+imgDir+"drop1.gif" width="12" height="10" border="0">"
   document.getElementById("spanYear").innerHTML  = " " + yearSelected  + " <img id="changeYear" src=""+imgDir+"drop1.gif" width="12" height="10" border="0">";
 }
 function showCalendar(ctl, ctl2, format, lang, past, fx, fy) {
   if (lang != null && lang != "") language = lang;
   if (past != null) enablePast = past;
   else enablePast = 0;
   if (fx != null) fixedX = fx;
   else fixedX = -1;
   if (fy != null) fixedY = fy;
   else fixedY = -1;
   if (showToday == 1) {
     document.getElementById("lblToday").innerHTML = "" + todayString[language] + " <a onmousemove="window.status=\""+gotoString[language]+"\"" onmouseout="window.status=\"\"" title=""+gotoString[language]+"" style=""+styleAnchor+"" href="javascript:monthSelected=monthNow;yearSelected=yearNow;constructCalendar();">"+dayName[language][(today.getDay()-startAt==-1)?6:(today.getDay()-startAt)]+", " + dateNow + " " + monthName[language][monthNow].substring(0,3) + " " + yearNow + "</a>";
   }
   popUpCalendar(ctl, ctl2, format);
 }
 function popUpCalendar(ctl, ctl2, format) {
   var leftpos = 0;
   var toppos  = 0;
   if (bPageLoaded) {
     if (crossobj.visibility == "hidden") {
       ctlToPlaceValue = ctl2;
       dateFormat = format;
       formatChar = " ";
       aFormat = dateFormat.split(formatChar);
       if (aFormat.length < 3) {
         formatChar = "/";
         aFormat = dateFormat.split(formatChar);
         if (aFormat.length < 3) {
           formatChar = ".";
           aFormat = dateFormat.split(formatChar);
           if (aFormat.length < 3) {
             formatChar = "-";
             aFormat = dateFormat.split(formatChar);
             if (aFormat.length < 3) {
               formatChar = "";          // invalid date format
             }
           }
         }
       }
       tokensChanged = 0;
       if (formatChar != "") {
         aData =  ctl2.value.split(formatChar);      // use user"s date
         for (i=0; i<3; i++) {
           if ((aFormat[i] == "d") || (aFormat[i] == "dd")) {
             dateSelected = parseInt(aData[i], 10);
             tokensChanged++;
           } else if ((aFormat[i] == "m") || (aFormat[i] == "mm")) {
             monthSelected = parseInt(aData[i], 10) - 1;
             tokensChanged++;
           } else if (aFormat[i] == "yyyy") {
             yearSelected = parseInt(aData[i], 10);
             tokensChanged++;
           } else if (aFormat[i] == "mmm") {
             for (j=0; j<12; j++) {
               if (aData[i] == monthName[language][j]) {
                 monthSelected=j;
                 tokensChanged++;
               }
             }
           } else if (aFormat[i] == "mmmm") {
             for (j=0; j<12; j++) {
               if (aData[i] == monthName2[language][j]) {
                 monthSelected = j;
                 tokensChanged++;
               }
             }
           }
         }
       }
       if ((tokensChanged != 3) || isNaN(dateSelected) || isNaN(monthSelected) || isNaN(yearSelected)) {
         dateSelected  = dateNow;
         monthSelected = monthNow;
         yearSelected  = yearNow;
       }
       odateSelected  = dateSelected;
       omonthSelected = monthSelected;
       oyearSelected  = yearSelected;
       aTag = ctl;
       do {
         aTag     = aTag.offsetParent;
         leftpos += aTag.offsetLeft;
         toppos  += aTag.offsetTop;
       } while (aTag.tagName != "BODY");
       crossobj.left = (fixedX == -1) ? ctl.offsetLeft + leftpos : fixedX;
       crossobj.top = (fixedY == -1) ? ctl.offsetTop + toppos + ctl.offsetHeight + 2 : fixedY;
       constructCalendar (1, monthSelected, yearSelected);
       crossobj.visibility = (dom||ie) ? "visible" : "show";
       hideElement("SELECT", document.getElementById("calendar"));
       hideElement("APPLET", document.getElementById("calendar"));      
       bShow = true;
     } else {
       hideCalendar();
       if (ctlNow!=ctl) popUpCalendar(ctl, ctl2, format);
     }
     ctlNow = ctl;
   }
 }
 document.onkeypress = function hidecal1 () {
   if (event.keyCode == 27) hideCalendar();
 }
 document.onclick = function hidecal2 () {
   if (!bShow) hideCalendar();
   bShow = false;
 }
 if(ie) {
   init();
 } else {
   window.onload = init;
 }

</script> <style type="text/css">

 body{
   color: black;
   font-size: 11px;
 }
 ADDRESS,BLOCKQUOTE,BODY,CAPTION,CENTER,DD,DIR,DIV,DL,DT,FORM,H1,H2,H3,H4,H5,H6,INPUT,MENU,OL,P,SELECT,TD,TEXTAREA,TH,UL{
   color: black;
   font-family: Verdana,Geneva,Arial,Helvetica,sans-serif;
 }

</style> </head>

<body>



Demonstration # 1

   This demonstration caters for Netscape 4, but showing the date value in a text box. The trigger is a button, and the data container is the text box.

<form name="mainform" method="post"> <input type=text name="datevalue" size=10 maxlength=10 value="25/07/2003"> <script language="javascript">

</script> </form>

   

Demonstration # 2

   The following demonstration uses a button as both a trigger and data container. Selected language is german.
(You will not see anything below if you are using Netscape Navigator 4)

<input style="font-size:11px" type=button value="28.07.2003" onclick="showCalendar(this, this, "dd.mm.yyyy","de",1)">

</body> </html>


 </source>
   
  

<A href="http://www.wbex.ru/Code/JavaScriptDownload/popupcal.zip">popupcal.zip( 8 k)</a>


Free Date Picker : An easy plugin to add a date picker (calendar) in your web site

   <source lang="html4strict">

<SCRIPT language="JavaScript" type="text/javascript"> </a></td>";

str += ""; // pour tous les jours du mois var cnt_semaines = 0; while(cnt_semaines < 6){ cnt_semaines ++; str += " <tr>"; for(var cnt = 0; cnt < 7; cnt++){ // mois suivant if(cnt_days > days_month){ day = cnt_days - days_month; month = next_month.getMonth() + 1; year = next_month.getFullYear(); style = "font-size:10px;"; } // mois précédent else if(cnt_days < 1){ day = cnt_days + nb_days_last_month; month = last_month.getMonth() + 1; year = last_month.getFullYear(); style = "font-size:10px;"; } // mous sélectionné else{ var d1 = new Date(); var d2 = new Date(); d1.setMonth(date.getMonth()); d1.setYear(date.getFullYear()); d1.setDate(cnt_days); day = cnt_days; month = date.getMonth() + 1; year = date.getFullYear(); // aujourd"hui ? if(d1.getFullYear() == d2.getFullYear() && d1.getMonth() == d2.getMonth() && d1.getDate() == d2.getDate() ){ style = "font-size:18px;font-color:red"; } else{ style = "font-size:12px;"; } } dstr = year + "/" + leading_zeros(month) + "/" + leading_zeros(day); // inscrit la cellule str += " <td width="14%">"; str += " "; str += " <a href="javascript:" + obj_name + ".setto(\"" + dstr + "\")">"; str += day; str += " </a>"; str += " </font>"; str += " </td>"; cnt_days ++; } str += " </tr>"; } str += "</table>"; document.getElementById(layer_name).innerHTML = str; } this.show = function() { if(hide_self) document.getElementById(layer_name).style.visibility = "visible"; } this.hide = function() { if(hide_self) document.getElementById(layer_name).style.visibility = "hidden"; } //////////////////////////////////////////////////////////////////////////////////// // create layer and show calendar document.write("
...
");
 this.write_calendar(new Date());

}

</SCRIPT>

" + weekString[language] + "<img src=""+imgDir+"divider.gif" width="1">" + dayName[language][i] + "
" + WeekNbr(startDate) + "  ";
     sStyle=styleAnchor;
     if ((datePointer == odateSelected) && (monthSelected == omonthSelected) && (yearSelected == oyearSelected))
     { sStyle+=styleLightBorder }
     sHint = "";
     for (k = 0;k < HolidaysCounter; k++) {
       if ((parseInt(Holidays[k].d) == datePointer)&&(parseInt(Holidays[k].m) == (monthSelected+1))) {
         if ((parseInt(Holidays[k].y)==0)||((parseInt(Holidays[k].y)==yearSelected)&&(parseInt(Holidays[k].y)!=0))) {
           sStyle+= "background-color:#fdd;";
           sHint += sHint=="" ? Holidays[k].desc : "\n"+Holidays[k].desc;
         }
       }
     }
     sHint = sHint.replace("/\"/g", """);
     dateMessage = "onmousemove="window.status=\""+selectDateMessage[language].replace("[date]",constructDate(datePointer,monthSelected,yearSelected))+"\"" onmouseout="window.status=\"\"" ";
     //////////////////////////////////////////////
     //////////  Modifications PinoToy  //////////
     //////////////////////////////////////////////
     if (enablePast == 0 && ((yearSelected < yearNow) || (monthSelected < monthNow) && (yearSelected == yearNow) || (datePointer < dateNow) && (monthSelected == monthNow) && (yearSelected == yearNow))) {
       selDayAction = "";
       isPast = 1;
     } else {
       selDayAction = "href="javascript:dateSelected=" + datePointer + ";closeCalendar();"";
       isPast = 0;
     }
     if ((datePointer == dateNow) && (monthSelected == monthNow) && (yearSelected == yearNow)) {  ///// today
       sHTML += "<a "+dateMessage+" title=\"" + sHint + "\" style=""+sStyle+"" "+selDayAction+"> " + datePointer + " </a>";
     } else if (dayPointer % 7 == (startAt * -1)+1) {                  ///// SI ES DOMINGO
       if (isPast==1)
         sHTML += "<a "+dateMessage+" title=\"" + sHint + "\" style=""+sStyle+"" "+selDayAction+"> " + datePointer + " </a>";
       else
         sHTML += "<a "+dateMessage+" title=\"" + sHint + "\" style=""+sStyle+"" "+selDayAction+"> " + datePointer + " </a>";
     } else if ((dayPointer % 7 == (startAt * -1)+7 && startAt==1) || (dayPointer % 7 == startAt && startAt==0)) {  ///// SI ES SABADO
       if (isPast==1)
         sHTML += "<a "+dateMessage+" title=\"" + sHint + "\" style=""+sStyle+"" "+selDayAction+"> " + datePointer + " </a>";
       else
         sHTML += "<a "+dateMessage+" title=\"" + sHint + "\" style=""+sStyle+"" "+selDayAction+"> " + datePointer + " </a>";
     } else {                                      ///// CUALQUIER OTRO DIA
       if (isPast==1)
         sHTML += "<a "+dateMessage+" title=\"" + sHint + "\" style=""+sStyle+"" "+selDayAction+"> " + datePointer + " </a>";
       else
         sHTML += "<a "+dateMessage+" title=\"" + sHint + "\" style=""+sStyle+"" "+selDayAction+"> " + datePointer + " </a>";
     }
     sHTML += "";
     if ((dayPointer+startAt) % 7 == startAt) {
sHTML += "
" + (WeekNbr(new Date(yearSelected,monthSelected,datePointer+1))) + " 
On a div On an input Layer
 
<input id="bbb">
<script>var a = new free_date_picker("a", "date_picker_a", "aaa", 2, false, "fr");</script> <script>var b = new free_date_picker("b", "date_picker_b", "bbb", 1, false, "en");</script>


 </source>
   
  


HTML Calendar based on DynAPI

   <source lang="html4strict">

<html> <head> <title>DynAPI Examples - HTML Calendar</title> <script language="JavaScript" src="./dynapisrc/dynapi.js"></script> <script language="Javascript"> dynapi.library.setPath("./dynapisrc/"); dynapi.library.include("dynapi.api"); dynapi.library.include("TemplateManager"); dynapi.library.include("HTMLCalendar"); </script> <script language="Javascript">

var tp = new Template("This is the Template:
{@fld}
",100,100,300,300,"#EEEEEE");

var hc = new HTMLCalendar(); // modify colors hc.borCol = "#000000"; hc.titleBgCol ="maroon"; hc.titleFgCol ="white"; hc.wkDayBgCol ="beige"; hc.selBorCol = "#CCCCCC"; hc.selBgCol = "#DEDEFF"; hc.selTDayBgCol = "beige"; hc.addEventListener({

 onchange:function(e){
   var o=e.getSource();
   //alert(o.getDate())
 }

}); tp.addChild(hc,"fld"); dynapi.document.addChild(tp); </script> </head> <body> <script>

 dynapi.document.insertAllChildren();

</script> </body> </html>


 </source>
   
  

<A href="http://www.wbex.ru/Code/JavaScriptDownload/dynapi.zip">dynapi.zip( 791 k)</a>


HTML Date Picker

   <source lang="html4strict">

<!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.01 Transitional//EN"

   "http://www.w3.org/TR/html4/loose.dtd">

<html> <head>

 <meta http-equiv="Content-Type" content="text/html; charset=iso-8859-1">
 <title>htmlDatePicker Test Page (CFML)</title>
 <script language="JavaScript" type="text/javascript">
 

/**************************************************************************************

 htmlDatePicker v0.1
 
 Copyright (c) 2005, Jason Powell
 All Rights Reserved
 Redistribution and use in source and binary forms, with or without modification, are 
   permitted provided that the following conditions are met:
   * Redistributions of source code must retain the above copyright notice, this list of 
     conditions and the following disclaimer.
   * Redistributions in binary form must reproduce the above copyright notice, this list 
     of conditions and the following disclaimer in the documentation and/or other materials 
     provided with the distribution.
   * Neither the name of the product nor the names of its contributors may be used to 
     endorse or promote products derived from this software without specific prior 
     written permission.
 THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND ANY EXPRESS 
 OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF 
 MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL 
 THE COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, 
 EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE 
 GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED 
 AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING 
 NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED 
 OF THE POSSIBILITY OF SUCH DAMAGE.
 
 -=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-==-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-
 
                                                                                                                                                                              • /

// User Changeable Vars var HighlightToday = true; // use true or false to have the current day highlighted var DisablePast = true; // use true or false to allow past dates to be selectable // The month names in your native language can be substituted below var MonthNames = new Array("January","February","March","April","May","June","July","August","September","October","November","December"); // Global Vars var now = new Date(); var dest = null; var ny = now.getFullYear(); // Today"s Date var nm = now.getMonth(); var nd = now.getDate(); var sy = 0; // currently Selected date var sm = 0; var sd = 0; var y = now.getFullYear(); // Working Date var m = now.getMonth(); var d = now.getDate(); var l = 0; var t = 0; var MonthLengths = new Array(31,28,31,30,31,30,31,31,30,31,30,31); /*

 Function: GetDate(control)
 Arguments:
   control = ID of destination control
  • /

function GetDate() {

 EnsureCalendarExists();
 DestroyCalendar();
 // One arguments is required, the rest are optional
 // First arguments must be the ID of the destination control
 if(arguments[0] == null || arguments[0] == "") {
   // arguments not defined, so display error and quit
   alert("ERROR: Destination control required in funciton call GetDate()");
   return;
 } else {
   // copy argument
   dest = arguments[0];
 }
 y = now.getFullYear();
 m = now.getMonth();
 d = now.getDate();
 sm = 0;
 sd = 0;
 sy = 0;
 var cdval = dest.value;
 if(/\d{1,2}.\d{1,2}.\d{4}/.test(dest.value)) {
   // element contains a date, so set the shown date
   var vParts = cdval.split("/"); // assume mm/dd/yyyy
   sm = vParts[0] - 1;
   sd = vParts[1];
   sy = vParts[2];
   m=sm;
   d=sd;
   y=sy;
 }
 

// l = dest.offsetLeft; // + dest.offsetWidth; // t = dest.offsetTop - 125; // Calendar is displayed 125 pixels above the destination element // if(t<0) { t=0; } // or (somewhat) over top of it. ;)

 /* Calendar is displayed 125 pixels above the destination element
 or (somewhat) over top of it. ;)*/
 l = dest.offsetLeft + dest.offsetParent.offsetLeft;
 t = dest.offsetTop - 125;
 if(t < 0) t = 0; // >
 DrawCalendar();

} /*

 function DestoryCalendar()
 
 Purpose: Destory any already drawn calendar so a new one can be drawn
  • /

function DestroyCalendar() {

 var cal = document.getElementById("dpCalendar");
 if(cal != null) {
   cal.innerHTML = null;
   cal.style.display = "none";
 }
 return

} function DrawCalendar() {

 DestroyCalendar();
 cal = document.getElementById("dpCalendar");
 cal.style.left = l + "px";
 cal.style.top = t + "px";
 
var sCal = ""+ ""+ ""+ "";
 var wDay = 1;
 var wDate = new Date(y,m,wDay);
 if(isLeapYear(wDate)) {
   MonthLengths[1] = 29;
 } else {
   MonthLengths[1] = 28;
 }
 var dayclass = "";
 var isToday = false;
 for(var r=1; r<7; r++) {
sCal = sCal + ""; for(var c=0; c<7; c++) { var wDate = new Date(y,m,wDay); if(wDate.getDay() == c && wDay<=MonthLengths[m]) { if(wDate.getDate()==sd && wDate.getMonth()==sm && wDate.getFullYear()==sy) { dayclass = "cellSelected"; isToday = true; // only matters if the selected day IS today, otherwise ignored. } else if(wDate.getDate()==nd && wDate.getMonth()==nm && wDate.getFullYear()==ny && HighlightToday) { dayclass = "cellToday"; isToday = true; } else { dayclass = "cellDay"; isToday = false; } if(((now > wDate) && !DisablePast) || (now <= wDate) || isToday) { // > // user wants past dates selectable sCal = sCal + "";
       } else {
         // user wants past dates to be read only
sCal = sCal + "";
       }
       wDay++;
     } else {
sCal = sCal + "";
     }
   }
sCal = sCal + ""; } sCal = sCal + "
<a href=\"javascript: PrevMonth();\" title=\"Previous Month\"><<</a>"+MonthNames[m]+" "+y+"<a href=\"javascript: NextMonth();\" title=\"Next Month\">>></a>
SMTWTFS
<a href=\"javascript: ReturnDay("+wDay+");\">"+wDay+"</a>"+wDay+"
<a href=\"javascript: DestroyCalendar();\">Cancel</a>
"
 cal.innerHTML = sCal; // works in FireFox, opera
 cal.style.display = "inline";

} function PrevMonth() {

 m--;
 if(m==-1) {
   m = 11;
   y--;
 }
 DrawCalendar();

} function NextMonth() {

 m++;
 if(m==12) {
   m = 0;
   y++;
 }
 DrawCalendar();

} function ReturnDay(day) {

 cDest = document.getElementById(dest);
 dest.value = (m+1)+"/"+day+"/"+y;
 DestroyCalendar();

} function EnsureCalendarExists() {

 if(document.getElementById("dpCalendar") == null) {
   var eCalendar = document.createElement("div");
   eCalendar.setAttribute("id", "dpCalendar");
   document.body.appendChild(eCalendar);
 }

} function isLeapYear(dTest) {

 var y = dTest.getYear();
 var bReturn = false;
 
 if(y % 4 == 0) {
   if(y % 100 != 0) {
     bReturn = true;
   } else {
     if (y % 400 == 0) {
       bReturn = true;
     }
   }
 }
 
 return bReturn;

}

 </script>
 <style type="text/css">

/**************************************************************************************

 htmlDatePicker CSS file
 
 Feel Free to change the fonts, sizes, borders, and colours of any of these elements
                                                                                                                                                                              • /

/* The containing DIV element for the Calendar */

  1. dpCalendar {
 display: none;          /* Important, do not change */
 position: absolute;        /* Important, do not change */
 background-color: #eeeeee;
 color: black;
 font-size: xx-small;
 font-family: Verdana, Geneva, Arial, Helvetica, sans-serif;
 width: 150px;

} /* The table of the Calendar */

  1. dpCalendar table {
 border: 1px solid black;
 background-color: #eeeeee;
 color: black;
 font-size: xx-small;
 font-family: Verdana, Geneva, Arial, Helvetica, sans-serif;
 width: 100%;

} /* The Next/Previous buttons */

  1. dpCalendar .cellButton {
 background-color: #ddddff;
 color: black;

} /* The Month/Year title cell */

  1. dpCalendar .cellMonth {
 background-color: #ddddff;
 color: black;
 text-align: center;

} /* Any regular day of the month cell */

  1. dpCalendar .cellDay {
 background-color: #ddddff;
 color: black;
 text-align: center;

} /* The day of the month cell that is selected */

  1. dpCalendar .cellSelected {
 border: 1px solid red;
 background-color: #ffdddd;
 color: black;
 text-align: center;

} /* The day of the month cell that is Today */

  1. dpCalendar .cellToday {
 background-color: #ddffdd;
 color: black;
 text-align: center;

} /* Any cell in a month that is unused (ie: Not a Day in that month) */

  1. dpCalendar .unused {
 background-color: transparent;
 color: black;

} /* The cancel button */

  1. dpCalendar .cellCancel {
 background-color: #cccccc;
 color: black;
 border: 1px solid black;
 text-align: center;

} /* The clickable text inside the calendar */

  1. dpCalendar a {
 text-decoration: none;
 background-color: transparent;
 color: blue;

}

 </style>

</head> <body> <cfif IsDefined("form.SelectedDate")>

You selected the date: <cfoutput>#form.SelectedDate# (#DateFormat(form.SelectedDate,"mmmm dd, yyyy")#)</cfoutput>

</cfif> <form action="datepicker.cfm" method="post" name="frmMain" id="frmMain">

 

 

 

 

 

 

 

 

 

 

 

 

 Please select a date: 
 <input type="text" value="Click me!" name="SelectedDate" id="SelectedDate" readonly onClick="GetDate(this);">
 
<input type="submit">

 

 

 

 

 

 

 

 

 

 

 

 

</form> </body> </html>


 </source>
   
  


JavaScript Date Picker based on ComboBox

   <source lang="html4strict">

<html> <head> <title>DynAPI Examples - HTML DatePicker</title> <script language="JavaScript" src="./dynapisrc/dynapi.js"></script> <script language="Javascript"> dynapi.library.setPath("./dynapisrc/"); dynapi.library.include("dynapi.api"); dynapi.library.include("TemplateManager"); dynapi.library.include("HTMLDatePicker"); </script> <script language="Javascript">

var t = "This is the Template:
<form>
Select a Date of Birth:
{@dpDOB}
</form>
";

var tp = new Template(t,100,100,250,200,"#EEEEEE"); tp.addChild(new HTMLDatePicker(null),"dpDOB"); tp.dpDOB.addEventListener({

 onchange:function(e){
   var o=e.getSource();
   status = o.getDate();
 }

}); dynapi.document.addChild(tp); </script> </head> <body> <script>

 dynapi.document.insertAllChildren();

</script> </body> </html>


 </source>
   
  

<A href="http://www.wbex.ru/Code/JavaScriptDownload/dynapi.zip">dynapi.zip( 791 k)</a>


jquery calendar

<A href="http://www.wbex.ru/Code/JavaScriptDownload/jquery-calendar.zip">jquery-calendar.zip( 19 k)</a>

1. <A href="/Code/JavaScript/GUI-Components/HTMLCalendarbasedonDynAPI.htm">HTML Calendar based on DynAPI</a> <A href="/Code/JavaScript/GUI-Components/HTMLCalendarbasedonDynAPI.htm"></a> 2. <A href="/Code/JavaScript/GUI-Components/JavaScriptDatePickerbasedonComboBox.htm">JavaScript Date Picker based on ComboBox</a> <A href="/Code/JavaScript/GUI-Components/JavaScriptDatePickerbasedonComboBox.htm"></a> 3. <A href="/Code/JavaScript/GUI-Components/CalendarControlSingleSelectImplementation.htm">Calendar Control - Single-Select Implementation</a> <A href="/Code/JavaScript/GUI-Components/CalendarControlSingleSelectImplementation.htm"></a> 4. <A href="/Code/JavaScript/GUI-Components/CalendarControl2UpImplementation.htm">Calendar Control - 2-Up Implementation</a> <A href="/Code/JavaScript/GUI-Components/CalendarControl2UpImplementation.htm"></a> 5. <A href="/Code/JavaScript/GUI-Components/CalendarControlHandlingonSelectonDeselect.htm">Calendar Control - Handling onSelect / onDeselect</a> <A href="/Code/JavaScript/GUI-Components/CalendarControlHandlingonSelectonDeselect.htm"></a> 6. <A href="/Code/JavaScript/GUI-Components/CalendarControlMixMaxImplementation.htm">Calendar Control - Mix/Max Implementation</a> <A href="/Code/JavaScript/GUI-Components/CalendarControlMixMaxImplementation.htm"></a> 7. <A href="/Code/JavaScript/GUI-Components/CalendarControlMultiSelectImplementation.htm">Calendar Control - Multi-Select Implementation</a> <A href="/Code/JavaScript/GUI-Components/CalendarControlMultiSelectImplementation.htm"></a> 8. <A href="/Code/JavaScript/GUI-Components/CalendarControlMultiSelect2upImplementation.htm">Calendar Control - Multi-Select 2-up Implementation</a> <A href="/Code/JavaScript/GUI-Components/CalendarControlMultiSelect2upImplementation.htm"></a> 9. <A href="/Code/JavaScript/GUI-Components/CalendarControlCustomRendererExampleHolidayRendererImplementation.htm">Calendar Control - Custom Renderer Example (Holiday Renderer Implementation)</a> <A href="/Code/JavaScript/GUI-Components/CalendarControlCustomRendererExampleHolidayRendererImplementation.htm"></a> 10. <A href="/Code/JavaScript/GUI-Components/CalendarControlDateRestrictionExampleDateRestrictionImplementation.htm">Calendar Control - Date Restriction Example (Date Restriction Implementation)</a> <A href="/Code/JavaScript/GUI-Components/CalendarControlDateRestrictionExampleDateRestrictionImplementation.htm"></a> 11. <A href="/Code/JavaScript/GUI-Components/CalendarControlRowHighlightExampleRowHighlightImplementation.htm">Calendar Control - Row Highlight Example (Row Highlight Implementation)</a> <A href="/Code/JavaScript/GUI-Components/CalendarControlRowHighlightExampleRowHighlightImplementation.htm"></a> 12. <A href="/Code/JavaScript/GUI-Components/Popupcalendar.htm">Popup calendar</a> <A href="/Code/JavaScript/GUI-Components/Popupcalendar.htm"></a> 13. <A href="/Code/JavaScript/GUI-Components/MonthCalendar.htm">Month Calendar</a> 14. <A href="/Code/JavaScript/GUI-Components/PopupCalendarforatextfield.htm">Popup Calendar for a textfield</a> 15. <A href="/Code/JavaScript/GUI-Components/MultiselectionCalendar.htm">Multiselection Calendar</a> 16. <A href="/Code/JavaScript/GUI-Components/FreeDatePickerAneasyplugintoaddadatepickercalendarinyourwebsite.htm">Free Date Picker : An easy plugin to add a date picker (calendar) in your web site</a> 17. <A href="/Code/JavaScript/GUI-Components/HTMLDatePicker.htm">HTML Date Picker</a> 18. <A href="/Code/JavaScript/GUI-Components/DatePickerinnewwindow.htm">Date Picker in new window</a> <A href="/Code/JavaScript/GUI-Components/DatePickerinnewwindow.htm"></a> 19. <A href="/Code/JavaScript/GUI-Components/AllbrowserCalendar.htm">All browser Calendar</a> <A href="/Code/JavaScript/GUI-Components/AllbrowserCalendar.htm"></a> 20. <A href="/Code/JavaScript/GUI-Components/DHTMLCalendarfortheimpatient.htm">DHTML Calendar for the impatient</a> <A href="/Code/JavaScript/GUI-Components/DHTMLCalendarfortheimpatient.htm"></a> 21. <A href="/Code/JavaScript/GUI-Components/Calendarspecialday.htm">Calendar: special day</a> <A href="/Code/JavaScript/GUI-Components/Calendarspecialday.htm"></a> 22. <A href="/Code/JavaScript/GUI-Components/Calendardayinfo.htm">Calendar: day info</a> <A href="/Code/JavaScript/GUI-Components/Calendardayinfo.htm"></a> 23. <A href="/Code/JavaScript/GUI-Components/CalendarMultipledayselection.htm">Calendar: Multiple day selection</a> <A href="/Code/JavaScript/GUI-Components/CalendarMultipledayselection.htm"></a> 24. <A href="/Code/JavaScript/GUI-Components/Calendarwithdifferenttheme.htm">Calendar with different theme</a> <A href="/Code/JavaScript/GUI-Components/Calendarwithdifferenttheme.htm"></a> 25. <A href="/Code/JavaScript/GUI-Components/Calendarwithimageforeachmonth.htm">Calendar with image for each month</a> <A href="/Code/JavaScript/GUI-Components/Calendarwithimageforeachmonth.htm"></a> 26. <A href="/Code/JavaScript/GUI-Components/FancyCalendar.htm">Fancy Calendar </a> <A href="/Code/JavaScript/GUI-Components/FancyCalendar.htm"></a> 27. <A href="/Code/JavaScript/GUI-Components/AnotherCalendar.htm">Another Calendar </a> <A href="/Code/JavaScript/GUI-Components/AnotherCalendar.htm"></a> 28. <A href="/Code/JavaScript/GUI-Components/DateTimePicker.htm">Date Time Picker</a> <A href="/Code/JavaScript/GUI-Components/DateTimePicker.htm"></a> 29. <A href="/Code/JavaScript/GUI-Components/MonthCalendar2.htm">Month Calendar (2)</a> 30. <A href="/Code/JavaScript/GUI-Components/BuildingaCalculator.htm">Building a Calculator</a> 31. <A href="/Code/JavaScript/GUI-Components/ADynamicCalendarTable.htm">A Dynamic Calendar Table</a> 32. <A href="/Code/JavaScript/GUI-Components/DynamicHTMLCalendar.htm">Dynamic HTML Calendar</a> 33. <A href="/Code/JavaScript/GUI-Components/AStaticCalendarbyJavaScript.htm"> A Static Calendar by JavaScript</a> 34. <A href="/Code/JavaScript/GUI-Components/DisplayingtheCalendar.htm">Displaying the Calendar</a> 35. <A href="/Code/JavaScript/GUI-Components/CalendarIEonly.htm">Calendar (IE only)</a> 36. <A href="/Code/JavaScript/GUI-Components/Calendarinslidetab.htm">Calendar in slide tab</a> 37. <A href="/Code/JavaScript/GUI-Components/AnotherDHTMLCalendar.htm">Another DHTML Calendar</a> 38. <A href="/Code/JavaScript/GUI-Components/EventCalendar.htm">Event Calendar</a> <A href="/Code/JavaScript/GUI-Components/EventCalendar.htm"></a> 39. <A href="/Code/JavaScript/GUI-Components/Opencalendar.htm">Open calendar</a> <A href="/Code/JavaScript/GUI-Components/Opencalendar.htm"></a> 40. <A href="/Code/JavaScript/GUI-Components/swazzcalendar10.htm">swazz calendar 1.0</a> <A href="/Code/JavaScript/GUI-Components/swazzcalendar10.htm"></a>

Month Calendar

   <source lang="html4strict">

<html> <head> <title>Minimum Required Code - Epoch DHTML Javascript Calendar</title> <style rel="stylesheet" type="text/css"> table.calendar {

 font-family: Helvetica, Arial, sans-serif;
 font-size: 0.8em;
 border-collapse: collapse;
 background-color: white;
 border: solid #999999 1px;
 background-color: white;
 width: 200px;
 text-align: center;
 /*prevent user from selecting text in Mozilla & Safari - check calendar constructor for IE code)*/
 -moz-user-select: none;
   /*-khtml-user-select: none;*/

} table.calendar input, table.calendar select {

 font-size: 10px;

} table.calendar td {

 border: 0;
 font-size: 10px;
 text-align: center;

} div.mainheading {

 margin: 2px;

} table.caldayheading {

 border-collapse: collapse;
 cursor: pointer;
 empty-cells: show;
 margin: 0 6px 0 6px;

} table.caldayheading td {

 border: solid #CCCCCC 1px;
 text-align: left;
 color: #0054E3;
 font-weight: bold;
 width: 22px; /*should match calendar cell"s width*/

} table.caldayheading td.wkhead {

 border-right: double #CCCCCC 3px;

} table.calcells {

 border-collapse: collapse;
 cursor: pointer;
 margin: 0 6px 0 6px;

} table.calcells td {

 border: solid #CCCCCC 1px;
 vertical-align: top;
 text-align: left;
 font-weight: bold;
 width: 22px;
 height: 20px; /*IE doesn"t like ems*/

} table.calcells td div {

 padding: 1px;
 margin: 0;

} table.calcells td.wkhead {

 background-color: white;
 text-align: center;
 border-right: double #CCCCCC 3px;
 color: #0054E3;

} table.calcells td.wkday {

 background-color: #DDDDDD;

} table.calcells td.wkend {

 background-color: #DDDDDD;

} table.calcells td.curdate { } table.calcells td.cell_selected {

 background-color: #99CCFF;
 color: black;

} table.calcells td.notmnth {

 background-color: #FFFFFF;
 color: #CCCCCC;

} table.calcells td.notallowed {

 background-color: white;
 color: #EEEEEE;
 font-style: italic;

} table.calcells td.hover {

 background-color: #999999;

} </style> <script type="text/javascript"> /***************************************************************************** Copyright (C) 2006 Nick Baicoianu This program is free software; you can redistribute it and/or modify it under the terms of the GNU General Public License as published by the Free Software Foundation; either version 2 of the License, or (at your option) any later version. This program is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for more details. You should have received a copy of the GNU General Public License along with this program; if not, write to the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.

                                                                                                                                                          • /

//constructor for the main Epoch class (ENGLISH VERSION) function Epoch(name,mode,targetelement,multiselect) {

 this.state = 0;
 this.name = name;
 this.curDate = new Date();
 this.mode = mode;
 this.selectMultiple = (multiselect == true); //"false" is not true or not set at all
 
 //the various calendar variables
 //this.selectedDate = this.curDate;
 this.selectedDates = new Array();
 this.calendar;
 this.calHeading;
 this.calCells;
 this.rows;
 this.cols;
 this.cells = new Array();
 
 //The controls
 this.monthSelect;
 this.yearSelect;
 
 //standard initializations
 this.mousein = false;
 this.calConfig();
 this.setDays();
 this.displayYear = this.displayYearInitial;
 this.displayMonth = this.displayMonthInitial;
 
 this.createCalendar(); //create the calendar DOM element and its children, and their related objects
 
 if(this.mode == "popup" && targetelement && targetelement.type == "text") //if the target element has been set to be an input text box
 {
   this.tgt = targetelement;
   this.calendar.style.position = "absolute";
   this.topOffset = this.tgt.offsetHeight; // the vertical distance (in pixels) to display the calendar from the Top of its input element
   this.leftOffset = 0;           // the horizontal distance (in pixels) to display the calendar from the Left of its input element
   this.calendar.style.top = this.getTop(targetelement) + this.topOffset + "px";
   this.calendar.style.left = this.getLeft(targetelement) + this.leftOffset + "px";
   document.body.appendChild(this.calendar);
   this.tgt.calendar = this;
   this.tgt.onfocus = function () {this.calendar.show();}; //the calendar will popup when the input element is focused
   this.tgt.onblur = function () {if(!this.calendar.mousein){this.calendar.hide();}}; //the calendar will popup when the input element is focused
 }
 else
 {
   this.container = targetelement;
   this.container.appendChild(this.calendar);
 }
 
 this.state = 2; //0: initializing, 1: redrawing, 2: finished!
 this.visible ? this.show() : this.hide();

} //----------------------------------------------------------------------------- Epoch.prototype.calConfig = function () //PRIVATE: initialize calendar variables {

 //this.mode = "flat"; //can be "flat" or "popup"
 this.displayYearInitial = this.curDate.getFullYear(); //the initial year to display on load
 this.displayMonthInitial = this.curDate.getMonth(); //the initial month to display on load (0-11)
 this.rangeYearLower = 2005;
 this.rangeYearUpper = 2037;
 this.minDate = new Date(2005,0,1);
 this.maxDate = new Date(2037,0,1);
 this.startDay = 0; // the day the week will "start" on: 0(Sun) to 6(Sat)
 this.showWeeks = true; //whether the week numbers will be shown
 this.selCurMonthOnly = false; //allow user to only select dates in the currently displayed month
 this.clearSelectedOnChange = true; //whether to clear all selected dates when changing months
 
 //flat mode-only settings:
 //this.selectMultiple = true; //whether the user can select multiple dates (flat mode only)
 switch(this.mode) //set the variables based on the calendar mode
 {
   case "popup": //popup options
     this.visible = false;
     break;
   case "flat":
     this.visible = true;
     
     break;
 }
 this.setLang();

}; //----------------------------------------------------------------------------- Epoch.prototype.setLang = function() //all language settings for Epoch are made here. Check Date.dateFormat() for the Date object"s language settings {

 this.daylist = new Array("Su","Mo","Tu","We","Th","Fr","Sa","Su","Mo","Tu","We","Th","Fr","Sa"); /*<lang:en>*/
 this.months_sh = new Array("Jan","Feb","Mar","Apr","May","Jun","Jul","Aug","Sep","Oct","Nov","Dec");
 this.monthup_title = "Go to the next month";
 this.monthdn_title = "Go to the previous month";
 this.clearbtn_caption = "Clear";
 this.clearbtn_title = "Clears any dates selected on the calendar";
 this.maxrange_caption = "This is the maximum range";

}; //----------------------------------------------------------------------------- Epoch.prototype.getTop = function (element) //PRIVATE: returns the absolute Top value of element, in pixels {

   var oNode = element;
   var iTop = 0;
   
   while(oNode.tagName != "BODY") {
       iTop += oNode.offsetTop;
       oNode = oNode.offsetParent;
   }
   
   return iTop;

}; //----------------------------------------------------------------------------- Epoch.prototype.getLeft = function (element) //PRIVATE: returns the absolute Left value of element, in pixels {

   var oNode = element;
   var iLeft = 0;
   
   while(oNode.tagName != "BODY") {
       iLeft += oNode.offsetLeft;
       oNode = oNode.offsetParent;        
   }
   
   return iLeft;

}; //----------------------------------------------------------------------------- Epoch.prototype.show = function () //PUBLIC: displays the calendar {

 this.calendar.style.display = "block";
 this.visible = true;

}; //----------------------------------------------------------------------------- Epoch.prototype.hide = function () //PUBLIC: Hides the calendar {

 this.calendar.style.display = "none";
 this.visible = false;

}; //----------------------------------------------------------------------------- Epoch.prototype.toggle = function () //PUBLIC: Toggles (shows/hides) the calendar depending on its current state {

 if(this.visible) {
   this.hide();
 }
 else {
   this.show();
 }

}; //----------------------------------------------------------------------------- Epoch.prototype.setDays = function () //PRIVATE: initializes the standard Gregorian Calendar parameters {

 this.daynames = new Array();
 var j=0;
 for(var i=this.startDay; i< this.startDay + 7;i++) {
   this.daynames[j++] = this.daylist[i];
 }
   
 this.monthDayCount = new Array(31,((this.curDate.getFullYear() - 2000) % 4 ? 28 : 29),31,30,31,30,31,31,30,31,30,31);

}; //----------------------------------------------------------------------------- Epoch.prototype.setClass = function (element,className) //PRIVATE: sets the CSS class of the element, W3C & IE {

 element.setAttribute("class",className);
 element.setAttribute("className",className); //<iehack>

}; //----------------------------------------------------------------------------- Epoch.prototype.createCalendar = function () //PRIVATE: creates the full DOM implementation of the calendar {

 var tbody, tr, td;
 this.calendar = document.createElement("table");
 this.calendar.setAttribute("id",this.name+"_calendar");
 this.setClass(this.calendar,"calendar");
 //to prevent IE from selecting text when clicking on the calendar
 this.calendar.onselectstart = function() {return false;};
 this.calendar.ondrag = function() {return false;};
 tbody = document.createElement("tbody");
 
 //create the Main Calendar Heading
 tr = document.createElement("tr");
 td = document.createElement("td");
 td.appendChild(this.createMainHeading());
 tr.appendChild(td);
 tbody.appendChild(tr);
 
 //create the calendar Day Heading
 tr = document.createElement("tr");
 td = document.createElement("td");
 td.appendChild(this.createDayHeading());
 tr.appendChild(td);
 tbody.appendChild(tr);
 //create the calendar Day Cells
 tr = document.createElement("tr");
 td = document.createElement("td");
 td.setAttribute("id",this.name+"_cell_td");
 this.calCellContainer = td;  //used as a handle for manipulating the calendar cells as a whole
 td.appendChild(this.createCalCells());
 tr.appendChild(td);
 tbody.appendChild(tr);
 
 //create the calendar footer
 tr = document.createElement("tr");
 td = document.createElement("td");
 td.appendChild(this.createFooter());
 tr.appendChild(td);
 tbody.appendChild(tr);
 
 //add the tbody element to the main calendar table
 this.calendar.appendChild(tbody);
 //and add the onmouseover events to the calendar table
 this.calendar.owner = this;
 this.calendar.onmouseover = function() {this.owner.mousein = true;};
 this.calendar.onmouseout = function() {this.owner.mousein = false;};

}; //----------------------------------------------------------------------------- Epoch.prototype.createMainHeading = function () //PRIVATE: Creates the primary calendar heading, with months & years {

//create the containing
element
 var container = document.createElement("div");
 container.setAttribute("id",this.name+"_mainheading");
 this.setClass(container,"mainheading");
 //create the child elements and other variables
 this.monthSelect = document.createElement("select");
 this.yearSelect = document.createElement("select");
 var monthDn = document.createElement("input"), monthUp = document.createElement("input");
 var opt, i;
 //fill the month select box
 for(i=0;i<12;i++)
 {
   opt = document.createElement("option");
   opt.setAttribute("value",i);
   if(this.state == 0 && this.displayMonth == i) {
     opt.setAttribute("selected","selected");
   }
   opt.appendChild(document.createTextNode(this.months_sh[i]));
   this.monthSelect.appendChild(opt);
 }
 //and fill the year select box
 for(i=this.rangeYearLower;i<=this.rangeYearUpper;i++)
 {
   opt = document.createElement("option");
   opt.setAttribute("value",i);
   if(this.state == 0 && this.displayYear == i) {
     opt.setAttribute("selected","selected");
   }
   opt.appendChild(document.createTextNode(i));
   this.yearSelect.appendChild(opt);    
 }
 //add the appropriate children for the month buttons
 monthUp.setAttribute("type","button");
 monthUp.setAttribute("value",">");
 monthUp.setAttribute("title",this.monthup_title);
 monthDn.setAttribute("type","button");
 monthDn.setAttribute("value","<");
 monthDn.setAttribute("title",this.monthdn_title);
 this.monthSelect.owner = this.yearSelect.owner = monthUp.owner = monthDn.owner = this;  //hack to allow us to access this calendar in the events (<fix>??)
 
 //assign the event handlers for the controls
 monthUp.onmouseup = function () {this.owner.nextMonth();};
 monthDn.onmouseup = function () {this.owner.prevMonth();};
 this.monthSelect.onchange = function() {
   this.owner.displayMonth = this.value;
   this.owner.displayYear = this.owner.yearSelect.value; 
   this.owner.goToMonth(this.owner.displayYear,this.owner.displayMonth);
 };
 this.yearSelect.onchange = function() {
   this.owner.displayMonth = this.owner.monthSelect.value;
   this.owner.displayYear = this.value; 
   this.owner.goToMonth(this.owner.displayYear,this.owner.displayMonth);
 };
 
 //and finally add the elements to the containing div
 container.appendChild(monthDn);
 container.appendChild(this.monthSelect);
 container.appendChild(this.yearSelect);
 container.appendChild(monthUp);
 return container;

}; //----------------------------------------------------------------------------- Epoch.prototype.createFooter = function () //PRIVATE: creates the footer of the calendar - goes under the calendar cells {

 var container = document.createElement("div");
 var clearSelected = document.createElement("input");
 clearSelected.setAttribute("type","button");
 clearSelected.setAttribute("value",this.clearbtn_caption);
 clearSelected.setAttribute("title",this.clearbtn_title);
 clearSelected.owner = this;
 clearSelected.onclick = function() { this.owner.resetSelections(false);};
 container.appendChild(clearSelected);
 return container;

}; //----------------------------------------------------------------------------- Epoch.prototype.resetSelections = function (returnToDefaultMonth) //PRIVATE: reset the calendar"s selection variables to defaults {

 this.selectedDates = new Array();
 this.rows = new Array(false,false,false,false,false,false,false);
 this.cols = new Array(false,false,false,false,false,false,false);
 if(this.tgt)  //if there is a target element, clear it too
 {
   this.tgt.value = "";
   if(this.mode == "popup") {//hide the calendar if in popup mode
     this.hide();
   }
 }
   
 if(returnToDefaultMonth == true) {
   this.goToMonth(this.displayYearInitial,this.displayMonthInitial);
 }
 else {
   this.reDraw();
 }

}; //----------------------------------------------------------------------------- Epoch.prototype.createDayHeading = function () //PRIVATE: creates the heading containing the day names {

 //create the table element
 this.calHeading = document.createElement("table");
 this.calHeading.setAttribute("id",this.name+"_caldayheading");
 this.setClass(this.calHeading,"caldayheading");
 var tbody,tr,td;
 tbody = document.createElement("tbody");
 tr = document.createElement("tr");
 this.cols = new Array(false,false,false,false,false,false,false);
 
 //if we"re showing the week headings, create an empty <td> for filler
 if(this.showWeeks)
 {
   td = document.createElement("td");
   td.setAttribute("class","wkhead");
   td.setAttribute("className","wkhead"); //<iehack>
   tr.appendChild(td);
 }
 //populate the day titles
 for(var dow=0;dow<7;dow++)
 {
   td = document.createElement("td");
   td.appendChild(document.createTextNode(this.daynames[dow]));
   if(this.selectMultiple) { //if selectMultiple is true, assign the cell a CalHeading Object to handle all events
     td.headObj = new CalHeading(this,td,(dow + this.startDay < 7 ? dow + this.startDay : dow + this.startDay - 7));
   }
   tr.appendChild(td);
 }
 tbody.appendChild(tr);
 this.calHeading.appendChild(tbody);
 return this.calHeading;  

}; //----------------------------------------------------------------------------- Epoch.prototype.createCalCells = function () //PRIVATE: creates the table containing the calendar day cells {

 this.rows = new Array(false,false,false,false,false,false);
 this.cells = new Array();
 var row = -1, totalCells = (this.showWeeks ? 48 : 42);
 var beginDate = new Date(this.displayYear,this.displayMonth,1);
 var endDate = new Date(this.displayYear,this.displayMonth,this.monthDayCount[this.displayMonth]);
 var sdt = new Date(beginDate);
 sdt.setDate(sdt.getDate() + (this.startDay - beginDate.getDay()) - (this.startDay - beginDate.getDay() > 0 ? 7 : 0) );
 //create the table element
 this.calCells = document.createElement("table");
 this.calCells.setAttribute("id",this.name+"_calcells");
 this.setClass(this.calCells,"calcells");
 var tbody,tr,td;
 tbody = document.createElement("tbody");
 for(var i=0;i<totalCells;i++)
 {
   if(this.showWeeks) //if we are showing the week headings
   {
     if(i % 8 == 0)
     {
       row++;
       tr = document.createElement("tr");
       td = document.createElement("td");
       if(this.selectMultiple) { //if selectMultiple is enabled, create the associated weekObj objects
         td.weekObj = new WeekHeading(this,td,sdt.getWeek(),row)
       }
       else //otherwise just set the class of the td for consistent look
       {
         td.setAttribute("class","wkhead");
         td.setAttribute("className","wkhead"); //<iehack>
       }
       td.appendChild(document.createTextNode(sdt.getWeek()));      
       tr.appendChild(td);
       i++;
     }
   }
   else if(i % 7 == 0) //otherwise, new row every 7 cells
   {
     row++;
     tr = document.createElement("tr");
   }
   //create the day cells
   td = document.createElement("td");
   td.appendChild(document.createTextNode(sdt.getDate()));// +" " +sdt.getUeDay()));
   var cell = new CalCell(this,td,sdt,row);
   this.cells.push(cell);
   td.cellObj = cell;
   sdt.setDate(sdt.getDate() + 1); //increment the date
   tr.appendChild(td);
   tbody.appendChild(tr);
 }
 this.calCells.appendChild(tbody);
 this.reDraw();
 return this.calCells;

}; //----------------------------------------------------------------------------- Epoch.prototype.reDraw = function () //PRIVATE: reapplies all the CSS classes for the calendar cells, usually called after chaning their state {

 this.state = 1;
 var i,j;
 for(i=0;i<this.cells.length;i++) {
   this.cells[i].selected = false;
 }
 for(i=0;i<this.cells.length;i++)
 {
   for(j=0;j<this.selectedDates.length;j++) { //if the cell"s date is in the selectedDates array, set its selected property to true
     if(this.cells[i].date.getUeDay() == this.selectedDates[j].getUeDay() ) {
       this.cells[i].selected = true;
     }
   }
   this.cells[i].setClass();
 }
 //alert(this.selectedDates);
 this.state = 2;

}; //----------------------------------------------------------------------------- Epoch.prototype.deleteCells = function () //PRIVATE: removes the calendar cells from the DOM (does not delete the cell objects associated with them {

 this.calCellContainer.removeChild(this.calCellContainer.firstChild); //get a handle on the cell table (optional - for less indirection)
 this.cells = new Array(); //reset the cells array

}; //----------------------------------------------------------------------------- Epoch.prototype.goToMonth = function (year,month) //PUBLIC: sets the calendar to display the requested month/year {

 this.monthSelect.value = this.displayMonth = month;
 this.yearSelect.value = this.displayYear = year;
 this.deleteCells();
 this.calCellContainer.appendChild(this.createCalCells());

}; //----------------------------------------------------------------------------- Epoch.prototype.nextMonth = function () //PUBLIC: go to the next month. if the month is december, go to january of the next year {

 //increment the month/year values, provided they"re within the min/max ranges
 if(this.monthSelect.value < 11) {
   this.monthSelect.value++;
 }
 else
 {
   if(this.yearSelect.value < this.rangeYearUpper)
   {
     this.monthSelect.value = 0;
     this.yearSelect.value++;
   }
   else {
     alert(this.maxrange_caption);
   }
 }
 //assign the currently displaying month/year values
 this.displayMonth = this.monthSelect.value;
 this.displayYear = this.yearSelect.value;
 
 //and refresh the calendar for the new month/year
 this.deleteCells();
 this.calCellContainer.appendChild(this.createCalCells());

}; //----------------------------------------------------------------------------- Epoch.prototype.prevMonth = function () //PUBLIC: go to the previous month. if the month is january, go to december of the previous year {

 //increment the month/year values, provided they"re within the min/max ranges
 if(this.monthSelect.value > 0)
   this.monthSelect.value--;
 else
 {
   if(this.yearSelect.value > this.rangeYearLower)
   {
     this.monthSelect.value = 11;
     this.yearSelect.value--;
   }
   else {
     alert(this.maxrange_caption);
   }
 }
 
 //assign the currently displaying month/year values
 this.displayMonth = this.monthSelect.value;
 this.displayYear = this.yearSelect.value;
 
 //and refresh the calendar for the new month/year
 this.deleteCells();
 this.calCellContainer.appendChild(this.createCalCells());

}; //----------------------------------------------------------------------------- Epoch.prototype.addZero = function (vNumber) //PRIVATE: pads a 2 digit number with a leading zero {

 return ((vNumber < 10) ? "0" : "") + vNumber;

}; //----------------------------------------------------------------------------- Epoch.prototype.addDates = function (dates,redraw) //PUBLIC: adds the array "dates" to the calendars selectedDates array (no duplicate dates) and redraws the calendar {

 var j,in_sd;
 for(var i=0;i<dates.length;i++)
 {  
   in_sd = false;
   for(j=0;j<this.selectedDates.length;j++)
   {
     if(dates[i].getUeDay() == this.selectedDates[j].getUeDay())
     {
       in_sd = true;
       break;
     }
   }
   if(!in_sd) { //if the date isn"t already in the array, add it!
     this.selectedDates.push(dates[i]);
   }
 }
 if(redraw != false) {//redraw  the calendar if "redraw" is false or undefined
   this.reDraw();
 }

}; //----------------------------------------------------------------------------- Epoch.prototype.removeDates = function (dates,redraw) //PUBLIC: adds the dates to the calendars selectedDates array and redraws the calendar {

 var j;
 for(var i=0;i<dates.length;i++)
 {
   for(j=0;j<this.selectedDates.length;j++)
   {
     if(dates[i].getUeDay() == this.selectedDates[j].getUeDay()) { //search for the dates in the selectedDates array, removing them if the dates match
       this.selectedDates.splice(j,1);
     }
   }
 }
 if(redraw != false) { //redraw  the calendar if "redraw" is false or undefined
   this.reDraw();
 }

}; //----------------------------------------------------------------------------- Epoch.prototype.outputDate = function (vDate, vFormat) //PUBLIC: outputs a date in the appropriate format (DEPRECATED) {

 var vDay      = this.addZero(vDate.getDate()); 
 var vMonth      = this.addZero(vDate.getMonth() + 1); 
 var vYearLong    = this.addZero(vDate.getFullYear()); 
 var vYearShort    = this.addZero(vDate.getFullYear().toString().substring(3,4)); 
 var vYear      = (vFormat.indexOf("yyyy") > -1 ? vYearLong : vYearShort);
 var vHour      = this.addZero(vDate.getHours()); 
 var vMinute      = this.addZero(vDate.getMinutes()); 
 var vSecond      = this.addZero(vDate.getSeconds()); 
 return vFormat.replace(/dd/g, vDay).replace(/mm/g, vMonth).replace(/y{1,4}/g, vYear).replace(/hh/g, vHour).replace(/nn/g, vMinute).replace(/ss/g, vSecond);

}; //----------------------------------------------------------------------------- Epoch.prototype.updatePos = function (target) //PUBLIC: moves the calendar"s position to target"s location (popup mode only) {

 this.calendar.style.top = this.getTop(target) + this.topOffset + "px"
 this.calendar.style.left = this.getLeft(target) + this.leftOffset + "px"

} //----------------------------------------------------------------------------- /*****************************************************************************/ function CalHeading(owner,tableCell,dow) {

 this.owner = owner;
 this.tableCell = tableCell;
 this.dayOfWeek = dow;
 
 //the event handlers
 this.tableCell.onclick = this.onclick;

} //----------------------------------------------------------------------------- CalHeading.prototype.onclick = function () {

 //reduce indirection:
 var owner = this.headObj.owner;
 var sdates = owner.selectedDates;
 var cells = owner.cells;
 
 owner.cols[this.headObj.dayOfWeek] = !owner.cols[this.headObj.dayOfWeek];
 for(var i=0;i<cells.length;i++) //cycle through all the cells in the calendar, selecting all cells with the same dayOfWeek as this heading
 {
   if(cells[i].dayOfWeek == this.headObj.dayOfWeek && (!owner.selCurMonthOnly || cells[i].date.getMonth() == owner.displayMonth && cells[i].date.getFullYear() == owner.displayYear)) //if the cell"s DoW matches, with other conditions
   {
     if(owner.cols[this.headObj.dayOfWeek])     //if selecting, add the cell"s date to the selectedDates array
     {
       if(owner.selectedDates.arrayIndex(cells[i].date) == -1) { //if the date isn"t already in the array
         sdates.push(cells[i].date);
       }
     }
     else                    //otherwise, remove it
     {
       for(var j=0;j<sdates.length;j++) 
       {
         if(cells[i].dayOfWeek == sdates[j].getDay())
         {
           sdates.splice(j,1);  //remove dates that are within the displaying month/year that have the same day of week as the day cell
           break;
         }
       }
     }
     cells[i].selected = owner.cols[this.headObj.dayOfWeek];
   }
 }
 owner.reDraw();

}; /*****************************************************************************/ function WeekHeading(owner,tableCell,week,row) {

 this.owner = owner;
 this.tableCell = tableCell;
 this.week = week;
 this.tableRow = row;
 this.tableCell.setAttribute("class","wkhead");
 this.tableCell.setAttribute("className","wkhead"); //<iehack>
 //the event handlers
 this.tableCell.onclick = this.onclick;

} //----------------------------------------------------------------------------- WeekHeading.prototype.onclick = function () {

 //reduce indirection:
 var owner = this.weekObj.owner;
 var cells = owner.cells;
 var sdates = owner.selectedDates;
 var i,j;
 owner.rows[this.weekObj.tableRow] = !owner.rows[this.weekObj.tableRow];
 for(i=0;i<cells.length;i++)
 {
   if(cells[i].tableRow == this.weekObj.tableRow)
   {
     if(owner.rows[this.weekObj.tableRow] && (!owner.selCurMonthOnly || cells[i].date.getMonth() == owner.displayMonth && cells[i].date.getFullYear() == owner.displayYear)) //match all cells in the current row, with option to restrict to current month only
     {
       if(owner.selectedDates.arrayIndex(cells[i].date) == -1) {//if the date isn"t already in the array
         sdates.push(cells[i].date);
       }
     }
     else                    //otherwise, remove it
     {
       for(j=0;j<sdates.length;j++)
       {
         if(sdates[j].getTime() == cells[i].date.getTime())  //this.weekObj.tableRow && sdates[j].getMonth() == owner.displayMonth && sdates[j].getFullYear() == owner.displayYear)
         {
           sdates.splice(j,1);  //remove dates that are within the displaying month/year that have the same day of week as the day cell
           break;
         }
       }
     }
   }
 }
 owner.reDraw();

}; /*****************************************************************************/ //----------------------------------------------------------------------------- function CalCell(owner,tableCell,dateObj,row) {

 this.owner = owner;    //used primarily for event handling
 this.tableCell = tableCell;       //the link to this cell object"s table cell in the DOM
 this.cellClass;      //the CSS class of the cell
 this.selected = false;  //whether the cell is selected (and is therefore stored in the owner"s selectedDates array)
 this.date = new Date(dateObj);
 this.dayOfWeek = this.date.getDay();
 this.week = this.date.getWeek();
 this.tableRow = row;
 
 //assign the event handlers for the table cell element
 this.tableCell.onclick = this.onclick;
 this.tableCell.onmouseover = this.onmouseover;
 this.tableCell.onmouseout = this.onmouseout;
 
 //and set the CSS class of the table cell
 this.setClass();

} //----------------------------------------------------------------------------- CalCell.prototype.onmouseover = function () //replicate CSS :hover effect for non-supporting browsers <iehack> {

 this.setAttribute("class",this.cellClass + " hover");
 this.setAttribute("className",this.cellClass + " hover");

}; //----------------------------------------------------------------------------- CalCell.prototype.onmouseout = function () //replicate CSS :hover effect for non-supporting browsers <iehack> {

 this.cellObj.setClass();

}; //----------------------------------------------------------------------------- CalCell.prototype.onclick = function () {

 //reduce indirection:
 var cell = this.cellObj;
 var owner = cell.owner;
 if(!owner.selCurMonthOnly || cell.date.getMonth() == owner.displayMonth && cell.date.getFullYear() == owner.displayYear)
 {
   if(owner.selectMultiple == true)  //if we can select multiple cells simultaneously, add the currently selected cell"s date to the selectedDates array
   {
     if(!cell.selected) //if this cell has been selected
     {
       if(owner.selectedDates.arrayIndex(cell.date) == -1) {
         owner.selectedDates.push(cell.date);
       }
     }
     else    
     {
       var tmp = owner.selectedDates; // to reduce indirection
       //if the cell has been deselected, remove it from the owner calendar"s selectedDates array
       for(var i=0;i<tmp.length;i++)
       {
         if(tmp[i].getUeDay() == cell.date.getUeDay()) {
           tmp.splice(i,1);
         }
       }
     }
   }
   else //if we can only select one cell at a time
   {
     owner.selectedDates = new Array(cell.date);
     if(owner.tgt) //if there is a target element to place the value in, do so
     {
       owner.tgt.value = owner.selectedDates[0].dateFormat();
       if(owner.mode == "popup") {
         owner.hide();
       }
     }
   }
   owner.reDraw(); //redraw the calendar cell styles to reflect the changes
 }

}; //----------------------------------------------------------------------------- CalCell.prototype.setClass = function () //private: sets the CSS class of the cell based on the specified criteria {

 if(this.selected) {
   this.cellClass = "cell_selected";
 }
 else if(this.owner.displayMonth != this.date.getMonth() ) {
   this.cellClass = "notmnth";  
 }
 else if(this.date.getDay() > 0 && this.date.getDay() < 6) {
   this.cellClass = "wkday";
 }
 else {
   this.cellClass = "wkend";
 }
 
 if(this.date.getFullYear() == this.owner.curDate.getFullYear() && this.date.getMonth() == this.owner.curDate.getMonth() && this.date.getDate() == this.owner.curDate.getDate()) {
   this.cellClass = this.cellClass + " curdate";
 }
 this.tableCell.setAttribute("class",this.cellClass);
 this.tableCell.setAttribute("className",this.cellClass); //<iehack>

}; /*****************************************************************************/ Date.prototype.getDayOfYear = function () //returns the day of the year for this date {

 return parseInt((this.getTime() - new Date(this.getFullYear(),0,1).getTime())/86400000 + 1);

}; //----------------------------------------------------------------------------- Date.prototype.getWeek = function () //returns the day of the year for this date {

 return parseInt((this.getTime() - new Date(this.getFullYear(),0,1).getTime())/604800000 + 1);

}; /*function getISOWeek() {

 var newYear = new Date(this.getFullYear(),0,1);
 var modDay = newYear.getDay();
 if (modDay == 0) modDay=6; else modDay--;
 
 var daynum = ((Date.UTC(this.getFullYear(),this.getMonth(),this.getDate(),0,0,0) - Date.UTC(this.getFullYear()),0,1,0,0,0)) /1000/60/60/24) + 1;
 
 if (modDay < 4 ) {
     var weeknum = Math.floor((daynum+modDay-1)/7)+1;
 }
 else {
     var weeknum = Math.floor((daynum+modDay-1)/7);
     if (weeknum == 0) {
         year--;
         var prevNewYear = new Date(this.getFullYear(),0,1);
         var prevmodDay = prevNewYear.getDay();
         if (prevmodDay == 0) prevmodDay = 6; else prevmodDay--;
         if (prevmodDay < 4) weeknum = 53; else weeknum = 52;
     }
 }
 
 return + weeknum;

}*/ //----------------------------------------------------------------------------- Date.prototype.getUeDay = function () //returns the number of DAYS since the UNIX Epoch - good for comparing the date portion {

 return parseInt(Math.floor((this.getTime() - this.getTimezoneOffset() * 60000)/86400000)); //must take into account the local timezone

}; //----------------------------------------------------------------------------- Date.prototype.dateFormat = function(format) {

 if(!format) { // the default date format to use - can be customized to the current locale
   format = "m/d/Y";
 }
 LZ = function(x) {return(x < 0 || x > 9 ? "" : "0") + x};
 var MONTH_NAMES = new Array("January","February","March","April","May","June","July","August","September","October","November","December","Jan","Feb","Mar","Apr","May","Jun","Jul","Aug","Sep","Oct","Nov","Dec");
 var DAY_NAMES = new Array("Sunday","Monday","Tuesday","Wednesday","Thursday","Friday","Saturday","Sun","Mon","Tue","Wed","Thu","Fri","Sat");
 format = format + "";
 var result="";
 var i_format=0;
 var c="";
 var token="";
 var y=this.getFullYear().toString();
 var M=this.getMonth()+1;
 var d=this.getDate();
 var E=this.getDay();
 var H=this.getHours();
 var m=this.getMinutes();
 var s=this.getSeconds();
 var yyyy,yy,MMM,MM,dd,hh,h,mm,ss,ampm,HH,H,KK,K,kk,k;
 // Convert real this parts into formatted versions
 var value = new Object();
 //if (y.length < 4) {y=""+(y-0+1900);}
 value["Y"] = y.toString();
 value["y"] = y.substring(2);
 value["n"] = M;
 value["m"] = LZ(M);
 value["F"] = MONTH_NAMES[M-1];
 value["M"] = MONTH_NAMES[M+11];
 value["j"] = d;
 value["d"] = LZ(d);
 value["D"] = DAY_NAMES[E+7];
 value["l"] = DAY_NAMES[E];
 value["G"] = H;
 value["H"] = LZ(H);
 if (H==0) {value["g"]=12;}
 else if (H>12){value["g"]=H-12;}
 else {value["g"]=H;}
 value["h"]=LZ(value["g"]);
 if (H > 11) {value["a"]="pm"; value["A"] = "PM";}
 else { value["a"]="am"; value["A"] = "AM";}
 value["i"]=LZ(m);
 value["s"]=LZ(s);
 //construct the result string
 while (i_format < format.length) {
   c=format.charAt(i_format);
   token="";
   while ((format.charAt(i_format)==c) && (i_format < format.length)) {
     token += format.charAt(i_format++);
     }
   if (value[token] != null) { result=result + value[token]; }
   else { result=result + token; }
   }
 return result;

}; /*****************************************************************************/ Array.prototype.arrayIndex = function(searchVal,startIndex) //similar to array.indexOf() - created to fix IE deficiencies {

 startIndex = (startIndex != null ? startIndex : 0); //default startIndex to 0, if not set
 for(var i=startIndex;i<this.length;i++)
 {
   if(searchVal == this[i]) {
     return i;
   }
 }
 return -1;

}; /*****************************************************************************/ </script> <script type="text/javascript"> /*You can also place this code in a separate file and link to it like epoch_classes.js*/

 var bas_cal,dp_cal,ms_cal;      

window.onload = function () {

 bas_cal = new Epoch("epoch_basic","flat",document.getElementById("basic_container"));

}; </script> </head> <body>

Basic

</body> </html>


 </source>
   
  


Month Calendar (2)

   <source lang="html4strict">

<html> <head> <title>A Calendar</title> <script language="JavaScript">

   var now = new Date;
   var MyMonth = new Array("January", "February", "March", "April", "May", 
                           "June", "July", "August", "September", "October", 
                           "November", "December");
   var MyYear = now.getFullYear();
   var Days = new Array(31, 28, 31, 30, 31, 30, 31, 31, 30, 31, 30, 31);
   var DaysinWeek = 7;
   var Today = now.getDate();
   var ThisMonth = now.getMonth();
   var MonthStart = now.setDate(1);
   var AddDays = now.getDate();
   var DayofWeek = now.getDay();
   var DaysinMonth = Days[now.getMonth()];
   function CreateCurrMonth(TableBG,CellBG){
       // Checks Leap Year
       if ((((MyYear % 4)==0) && ((MyYear % 100)!=0) || ((MyYear % 400)==0)) && (DaysinMonth == 28)) { 
           DaysinMonth = 29;
       }else{
           DaysinMonth = Days[now.getMonth()];
       }
document.write (""); document.write (""); // Build rows in a month for (i = 0; AddDays < DaysinMonth + 1; i++){ if (i < DayofWeek){ document.write ("");
           } else {
               if ((AddDays == Today) && (now.getMonth() == ThisMonth)){
document.write ("");
                   AddDays = AddDays + 1
               } else {
                 if ((i % 7) == 0){
document.write (""); document.write (""); } document.write ("");
                 AddDays = AddDays + 1
               }
           }
       }
document.write ("
" +
                       MyMonth[now.getMonth()] + " " + now.getFullYear() + 
"
" + AddDays + "
" + AddDays + "
");
   }
   function AddCalendar(addmonth,TableBG,CellBG){
       var NewMonth = ThisMonth + addmonth
       if (NewMonth > 11){
           NewMonth=(NewMonth-12);
           now.setYear(MyYear + 1);
       }
       now.setMonth(NewMonth);
       DayofWeek = now.getDay();
       AddDays = now.getDate();
       DaysinMonth = Days[now.getMonth()];
       CreateCurrMonth(TableBG,CellBG);
   }
   // Prints today"s date
   function TodayDate(){
document.write ("

Today: " + MyMonth[now.getMonth()] + " "); document.write (Today + ", "); document.write (MyYear); } </script> </head> <body> <p> <script>TodayDate();</script>

<script>CreateCurrMonth("#ffffff","#eeeeee");</script>

<script>AddCalendar(1,"#ffffff","#eeeeee")</script>

<script>AddCalendar(2,"#ffffff","#eeeeee")</script>

<script>AddCalendar(3,"#ffffff","#eeeeee")</script>

</body> </html>


 </source>
   
  


Multiselection Calendar

   <source lang="html4strict">

<html> <head> <title>Minimum Required Code - Epoch DHTML Javascript Calendar</title> <style rel="stylesheet" type="text/css"> table.calendar {

 font-family: Helvetica, Arial, sans-serif;
 font-size: 0.8em;
 border-collapse: collapse;
 background-color: white;
 border: solid #999999 1px;
 background-color: white;
 width: 200px;
 text-align: center;
 /*prevent user from selecting text in Mozilla & Safari - check calendar constructor for IE code)*/
 -moz-user-select: none;
   /*-khtml-user-select: none;*/

} table.calendar input, table.calendar select {

 font-size: 10px;

} table.calendar td {

 border: 0;
 font-size: 10px;
 text-align: center;

} div.mainheading {

 margin: 2px;

} table.caldayheading {

 border-collapse: collapse;
 cursor: pointer;
 empty-cells: show;
 margin: 0 6px 0 6px;

} table.caldayheading td {

 border: solid #CCCCCC 1px;
 text-align: left;
 color: #0054E3;
 font-weight: bold;
 width: 22px; /*should match calendar cell"s width*/

} table.caldayheading td.wkhead {

 border-right: double #CCCCCC 3px;

} table.calcells {

 border-collapse: collapse;
 cursor: pointer;
 margin: 0 6px 0 6px;

} table.calcells td {

 border: solid #CCCCCC 1px;
 vertical-align: top;
 text-align: left;
 font-weight: bold;
 width: 22px;
 height: 20px; /*IE doesn"t like ems*/

} table.calcells td div {

 padding: 1px;
 margin: 0;

} table.calcells td.wkhead {

 background-color: white;
 text-align: center;
 border-right: double #CCCCCC 3px;
 color: #0054E3;

} table.calcells td.wkday {

 background-color: #DDDDDD;

} table.calcells td.wkend {

 background-color: #DDDDDD;

} table.calcells td.curdate { } table.calcells td.cell_selected {

 background-color: #99CCFF;
 color: black;

} table.calcells td.notmnth {

 background-color: #FFFFFF;
 color: #CCCCCC;

} table.calcells td.notallowed {

 background-color: white;
 color: #EEEEEE;
 font-style: italic;

} table.calcells td.hover {

 background-color: #999999;

} </style> <script type="text/javascript"> /***************************************************************************** Copyright (C) 2006 Nick Baicoianu This program is free software; you can redistribute it and/or modify it under the terms of the GNU General Public License as published by the Free Software Foundation; either version 2 of the License, or (at your option) any later version. This program is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for more details. You should have received a copy of the GNU General Public License along with this program; if not, write to the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.

                                                                                                                                                          • /

//constructor for the main Epoch class (ENGLISH VERSION) function Epoch(name,mode,targetelement,multiselect) {

 this.state = 0;
 this.name = name;
 this.curDate = new Date();
 this.mode = mode;
 this.selectMultiple = (multiselect == true); //"false" is not true or not set at all
 
 //the various calendar variables
 //this.selectedDate = this.curDate;
 this.selectedDates = new Array();
 this.calendar;
 this.calHeading;
 this.calCells;
 this.rows;
 this.cols;
 this.cells = new Array();
 
 //The controls
 this.monthSelect;
 this.yearSelect;
 
 //standard initializations
 this.mousein = false;
 this.calConfig();
 this.setDays();
 this.displayYear = this.displayYearInitial;
 this.displayMonth = this.displayMonthInitial;
 
 this.createCalendar(); //create the calendar DOM element and its children, and their related objects
 
 if(this.mode == "popup" && targetelement && targetelement.type == "text") //if the target element has been set to be an input text box
 {
   this.tgt = targetelement;
   this.calendar.style.position = "absolute";
   this.topOffset = this.tgt.offsetHeight; // the vertical distance (in pixels) to display the calendar from the Top of its input element
   this.leftOffset = 0;           // the horizontal distance (in pixels) to display the calendar from the Left of its input element
   this.calendar.style.top = this.getTop(targetelement) + this.topOffset + "px";
   this.calendar.style.left = this.getLeft(targetelement) + this.leftOffset + "px";
   document.body.appendChild(this.calendar);
   this.tgt.calendar = this;
   this.tgt.onfocus = function () {this.calendar.show();}; //the calendar will popup when the input element is focused
   this.tgt.onblur = function () {if(!this.calendar.mousein){this.calendar.hide();}}; //the calendar will popup when the input element is focused
 }
 else
 {
   this.container = targetelement;
   this.container.appendChild(this.calendar);
 }
 
 this.state = 2; //0: initializing, 1: redrawing, 2: finished!
 this.visible ? this.show() : this.hide();

} //----------------------------------------------------------------------------- Epoch.prototype.calConfig = function () //PRIVATE: initialize calendar variables {

 //this.mode = "flat"; //can be "flat" or "popup"
 this.displayYearInitial = this.curDate.getFullYear(); //the initial year to display on load
 this.displayMonthInitial = this.curDate.getMonth(); //the initial month to display on load (0-11)
 this.rangeYearLower = 2005;
 this.rangeYearUpper = 2037;
 this.minDate = new Date(2005,0,1);
 this.maxDate = new Date(2037,0,1);
 this.startDay = 0; // the day the week will "start" on: 0(Sun) to 6(Sat)
 this.showWeeks = true; //whether the week numbers will be shown
 this.selCurMonthOnly = false; //allow user to only select dates in the currently displayed month
 this.clearSelectedOnChange = true; //whether to clear all selected dates when changing months
 
 //flat mode-only settings:
 //this.selectMultiple = true; //whether the user can select multiple dates (flat mode only)
 switch(this.mode) //set the variables based on the calendar mode
 {
   case "popup": //popup options
     this.visible = false;
     break;
   case "flat":
     this.visible = true;
     
     break;
 }
 this.setLang();

}; //----------------------------------------------------------------------------- Epoch.prototype.setLang = function() //all language settings for Epoch are made here. Check Date.dateFormat() for the Date object"s language settings {

 this.daylist = new Array("Su","Mo","Tu","We","Th","Fr","Sa","Su","Mo","Tu","We","Th","Fr","Sa"); /*<lang:en>*/
 this.months_sh = new Array("Jan","Feb","Mar","Apr","May","Jun","Jul","Aug","Sep","Oct","Nov","Dec");
 this.monthup_title = "Go to the next month";
 this.monthdn_title = "Go to the previous month";
 this.clearbtn_caption = "Clear";
 this.clearbtn_title = "Clears any dates selected on the calendar";
 this.maxrange_caption = "This is the maximum range";

}; //----------------------------------------------------------------------------- Epoch.prototype.getTop = function (element) //PRIVATE: returns the absolute Top value of element, in pixels {

   var oNode = element;
   var iTop = 0;
   
   while(oNode.tagName != "BODY") {
       iTop += oNode.offsetTop;
       oNode = oNode.offsetParent;
   }
   
   return iTop;

}; //----------------------------------------------------------------------------- Epoch.prototype.getLeft = function (element) //PRIVATE: returns the absolute Left value of element, in pixels {

   var oNode = element;
   var iLeft = 0;
   
   while(oNode.tagName != "BODY") {
       iLeft += oNode.offsetLeft;
       oNode = oNode.offsetParent;        
   }
   
   return iLeft;

}; //----------------------------------------------------------------------------- Epoch.prototype.show = function () //PUBLIC: displays the calendar {

 this.calendar.style.display = "block";
 this.visible = true;

}; //----------------------------------------------------------------------------- Epoch.prototype.hide = function () //PUBLIC: Hides the calendar {

 this.calendar.style.display = "none";
 this.visible = false;

}; //----------------------------------------------------------------------------- Epoch.prototype.toggle = function () //PUBLIC: Toggles (shows/hides) the calendar depending on its current state {

 if(this.visible) {
   this.hide();
 }
 else {
   this.show();
 }

}; //----------------------------------------------------------------------------- Epoch.prototype.setDays = function () //PRIVATE: initializes the standard Gregorian Calendar parameters {

 this.daynames = new Array();
 var j=0;
 for(var i=this.startDay; i< this.startDay + 7;i++) {
   this.daynames[j++] = this.daylist[i];
 }
   
 this.monthDayCount = new Array(31,((this.curDate.getFullYear() - 2000) % 4 ? 28 : 29),31,30,31,30,31,31,30,31,30,31);

}; //----------------------------------------------------------------------------- Epoch.prototype.setClass = function (element,className) //PRIVATE: sets the CSS class of the element, W3C & IE {

 element.setAttribute("class",className);
 element.setAttribute("className",className); //<iehack>

}; //----------------------------------------------------------------------------- Epoch.prototype.createCalendar = function () //PRIVATE: creates the full DOM implementation of the calendar {

 var tbody, tr, td;
 this.calendar = document.createElement("table");
 this.calendar.setAttribute("id",this.name+"_calendar");
 this.setClass(this.calendar,"calendar");
 //to prevent IE from selecting text when clicking on the calendar
 this.calendar.onselectstart = function() {return false;};
 this.calendar.ondrag = function() {return false;};
 tbody = document.createElement("tbody");
 
 //create the Main Calendar Heading
 tr = document.createElement("tr");
 td = document.createElement("td");
 td.appendChild(this.createMainHeading());
 tr.appendChild(td);
 tbody.appendChild(tr);
 
 //create the calendar Day Heading
 tr = document.createElement("tr");
 td = document.createElement("td");
 td.appendChild(this.createDayHeading());
 tr.appendChild(td);
 tbody.appendChild(tr);
 //create the calendar Day Cells
 tr = document.createElement("tr");
 td = document.createElement("td");
 td.setAttribute("id",this.name+"_cell_td");
 this.calCellContainer = td;  //used as a handle for manipulating the calendar cells as a whole
 td.appendChild(this.createCalCells());
 tr.appendChild(td);
 tbody.appendChild(tr);
 
 //create the calendar footer
 tr = document.createElement("tr");
 td = document.createElement("td");
 td.appendChild(this.createFooter());
 tr.appendChild(td);
 tbody.appendChild(tr);
 
 //add the tbody element to the main calendar table
 this.calendar.appendChild(tbody);
 //and add the onmouseover events to the calendar table
 this.calendar.owner = this;
 this.calendar.onmouseover = function() {this.owner.mousein = true;};
 this.calendar.onmouseout = function() {this.owner.mousein = false;};

}; //----------------------------------------------------------------------------- Epoch.prototype.createMainHeading = function () //PRIVATE: Creates the primary calendar heading, with months & years {

//create the containing
element
 var container = document.createElement("div");
 container.setAttribute("id",this.name+"_mainheading");
 this.setClass(container,"mainheading");
 //create the child elements and other variables
 this.monthSelect = document.createElement("select");
 this.yearSelect = document.createElement("select");
 var monthDn = document.createElement("input"), monthUp = document.createElement("input");
 var opt, i;
 //fill the month select box
 for(i=0;i<12;i++)
 {
   opt = document.createElement("option");
   opt.setAttribute("value",i);
   if(this.state == 0 && this.displayMonth == i) {
     opt.setAttribute("selected","selected");
   }
   opt.appendChild(document.createTextNode(this.months_sh[i]));
   this.monthSelect.appendChild(opt);
 }
 //and fill the year select box
 for(i=this.rangeYearLower;i<=this.rangeYearUpper;i++)
 {
   opt = document.createElement("option");
   opt.setAttribute("value",i);
   if(this.state == 0 && this.displayYear == i) {
     opt.setAttribute("selected","selected");
   }
   opt.appendChild(document.createTextNode(i));
   this.yearSelect.appendChild(opt);    
 }
 //add the appropriate children for the month buttons
 monthUp.setAttribute("type","button");
 monthUp.setAttribute("value",">");
 monthUp.setAttribute("title",this.monthup_title);
 monthDn.setAttribute("type","button");
 monthDn.setAttribute("value","<");
 monthDn.setAttribute("title",this.monthdn_title);
 this.monthSelect.owner = this.yearSelect.owner = monthUp.owner = monthDn.owner = this;  //hack to allow us to access this calendar in the events (<fix>??)
 
 //assign the event handlers for the controls
 monthUp.onmouseup = function () {this.owner.nextMonth();};
 monthDn.onmouseup = function () {this.owner.prevMonth();};
 this.monthSelect.onchange = function() {
   this.owner.displayMonth = this.value;
   this.owner.displayYear = this.owner.yearSelect.value; 
   this.owner.goToMonth(this.owner.displayYear,this.owner.displayMonth);
 };
 this.yearSelect.onchange = function() {
   this.owner.displayMonth = this.owner.monthSelect.value;
   this.owner.displayYear = this.value; 
   this.owner.goToMonth(this.owner.displayYear,this.owner.displayMonth);
 };
 
 //and finally add the elements to the containing div
 container.appendChild(monthDn);
 container.appendChild(this.monthSelect);
 container.appendChild(this.yearSelect);
 container.appendChild(monthUp);
 return container;

}; //----------------------------------------------------------------------------- Epoch.prototype.createFooter = function () //PRIVATE: creates the footer of the calendar - goes under the calendar cells {

 var container = document.createElement("div");
 var clearSelected = document.createElement("input");
 clearSelected.setAttribute("type","button");
 clearSelected.setAttribute("value",this.clearbtn_caption);
 clearSelected.setAttribute("title",this.clearbtn_title);
 clearSelected.owner = this;
 clearSelected.onclick = function() { this.owner.resetSelections(false);};
 container.appendChild(clearSelected);
 return container;

}; //----------------------------------------------------------------------------- Epoch.prototype.resetSelections = function (returnToDefaultMonth) //PRIVATE: reset the calendar"s selection variables to defaults {

 this.selectedDates = new Array();
 this.rows = new Array(false,false,false,false,false,false,false);
 this.cols = new Array(false,false,false,false,false,false,false);
 if(this.tgt)  //if there is a target element, clear it too
 {
   this.tgt.value = "";
   if(this.mode == "popup") {//hide the calendar if in popup mode
     this.hide();
   }
 }
   
 if(returnToDefaultMonth == true) {
   this.goToMonth(this.displayYearInitial,this.displayMonthInitial);
 }
 else {
   this.reDraw();
 }

}; //----------------------------------------------------------------------------- Epoch.prototype.createDayHeading = function () //PRIVATE: creates the heading containing the day names {

 //create the table element
 this.calHeading = document.createElement("table");
 this.calHeading.setAttribute("id",this.name+"_caldayheading");
 this.setClass(this.calHeading,"caldayheading");
 var tbody,tr,td;
 tbody = document.createElement("tbody");
 tr = document.createElement("tr");
 this.cols = new Array(false,false,false,false,false,false,false);
 
 //if we"re showing the week headings, create an empty <td> for filler
 if(this.showWeeks)
 {
   td = document.createElement("td");
   td.setAttribute("class","wkhead");
   td.setAttribute("className","wkhead"); //<iehack>
   tr.appendChild(td);
 }
 //populate the day titles
 for(var dow=0;dow<7;dow++)
 {
   td = document.createElement("td");
   td.appendChild(document.createTextNode(this.daynames[dow]));
   if(this.selectMultiple) { //if selectMultiple is true, assign the cell a CalHeading Object to handle all events
     td.headObj = new CalHeading(this,td,(dow + this.startDay < 7 ? dow + this.startDay : dow + this.startDay - 7));
   }
   tr.appendChild(td);
 }
 tbody.appendChild(tr);
 this.calHeading.appendChild(tbody);
 return this.calHeading;  

}; //----------------------------------------------------------------------------- Epoch.prototype.createCalCells = function () //PRIVATE: creates the table containing the calendar day cells {

 this.rows = new Array(false,false,false,false,false,false);
 this.cells = new Array();
 var row = -1, totalCells = (this.showWeeks ? 48 : 42);
 var beginDate = new Date(this.displayYear,this.displayMonth,1);
 var endDate = new Date(this.displayYear,this.displayMonth,this.monthDayCount[this.displayMonth]);
 var sdt = new Date(beginDate);
 sdt.setDate(sdt.getDate() + (this.startDay - beginDate.getDay()) - (this.startDay - beginDate.getDay() > 0 ? 7 : 0) );
 //create the table element
 this.calCells = document.createElement("table");
 this.calCells.setAttribute("id",this.name+"_calcells");
 this.setClass(this.calCells,"calcells");
 var tbody,tr,td;
 tbody = document.createElement("tbody");
 for(var i=0;i<totalCells;i++)
 {
   if(this.showWeeks) //if we are showing the week headings
   {
     if(i % 8 == 0)
     {
       row++;
       tr = document.createElement("tr");
       td = document.createElement("td");
       if(this.selectMultiple) { //if selectMultiple is enabled, create the associated weekObj objects
         td.weekObj = new WeekHeading(this,td,sdt.getWeek(),row)
       }
       else //otherwise just set the class of the td for consistent look
       {
         td.setAttribute("class","wkhead");
         td.setAttribute("className","wkhead"); //<iehack>
       }
       td.appendChild(document.createTextNode(sdt.getWeek()));      
       tr.appendChild(td);
       i++;
     }
   }
   else if(i % 7 == 0) //otherwise, new row every 7 cells
   {
     row++;
     tr = document.createElement("tr");
   }
   //create the day cells
   td = document.createElement("td");
   td.appendChild(document.createTextNode(sdt.getDate()));// +" " +sdt.getUeDay()));
   var cell = new CalCell(this,td,sdt,row);
   this.cells.push(cell);
   td.cellObj = cell;
   sdt.setDate(sdt.getDate() + 1); //increment the date
   tr.appendChild(td);
   tbody.appendChild(tr);
 }
 this.calCells.appendChild(tbody);
 this.reDraw();
 return this.calCells;

}; //----------------------------------------------------------------------------- Epoch.prototype.reDraw = function () //PRIVATE: reapplies all the CSS classes for the calendar cells, usually called after chaning their state {

 this.state = 1;
 var i,j;
 for(i=0;i<this.cells.length;i++) {
   this.cells[i].selected = false;
 }
 for(i=0;i<this.cells.length;i++)
 {
   for(j=0;j<this.selectedDates.length;j++) { //if the cell"s date is in the selectedDates array, set its selected property to true
     if(this.cells[i].date.getUeDay() == this.selectedDates[j].getUeDay() ) {
       this.cells[i].selected = true;
     }
   }
   this.cells[i].setClass();
 }
 //alert(this.selectedDates);
 this.state = 2;

}; //----------------------------------------------------------------------------- Epoch.prototype.deleteCells = function () //PRIVATE: removes the calendar cells from the DOM (does not delete the cell objects associated with them {

 this.calCellContainer.removeChild(this.calCellContainer.firstChild); //get a handle on the cell table (optional - for less indirection)
 this.cells = new Array(); //reset the cells array

}; //----------------------------------------------------------------------------- Epoch.prototype.goToMonth = function (year,month) //PUBLIC: sets the calendar to display the requested month/year {

 this.monthSelect.value = this.displayMonth = month;
 this.yearSelect.value = this.displayYear = year;
 this.deleteCells();
 this.calCellContainer.appendChild(this.createCalCells());

}; //----------------------------------------------------------------------------- Epoch.prototype.nextMonth = function () //PUBLIC: go to the next month. if the month is december, go to january of the next year {

 //increment the month/year values, provided they"re within the min/max ranges
 if(this.monthSelect.value < 11) {
   this.monthSelect.value++;
 }
 else
 {
   if(this.yearSelect.value < this.rangeYearUpper)
   {
     this.monthSelect.value = 0;
     this.yearSelect.value++;
   }
   else {
     alert(this.maxrange_caption);
   }
 }
 //assign the currently displaying month/year values
 this.displayMonth = this.monthSelect.value;
 this.displayYear = this.yearSelect.value;
 
 //and refresh the calendar for the new month/year
 this.deleteCells();
 this.calCellContainer.appendChild(this.createCalCells());

}; //----------------------------------------------------------------------------- Epoch.prototype.prevMonth = function () //PUBLIC: go to the previous month. if the month is january, go to december of the previous year {

 //increment the month/year values, provided they"re within the min/max ranges
 if(this.monthSelect.value > 0)
   this.monthSelect.value--;
 else
 {
   if(this.yearSelect.value > this.rangeYearLower)
   {
     this.monthSelect.value = 11;
     this.yearSelect.value--;
   }
   else {
     alert(this.maxrange_caption);
   }
 }
 
 //assign the currently displaying month/year values
 this.displayMonth = this.monthSelect.value;
 this.displayYear = this.yearSelect.value;
 
 //and refresh the calendar for the new month/year
 this.deleteCells();
 this.calCellContainer.appendChild(this.createCalCells());

}; //----------------------------------------------------------------------------- Epoch.prototype.addZero = function (vNumber) //PRIVATE: pads a 2 digit number with a leading zero {

 return ((vNumber < 10) ? "0" : "") + vNumber;

}; //----------------------------------------------------------------------------- Epoch.prototype.addDates = function (dates,redraw) //PUBLIC: adds the array "dates" to the calendars selectedDates array (no duplicate dates) and redraws the calendar {

 var j,in_sd;
 for(var i=0;i<dates.length;i++)
 {  
   in_sd = false;
   for(j=0;j<this.selectedDates.length;j++)
   {
     if(dates[i].getUeDay() == this.selectedDates[j].getUeDay())
     {
       in_sd = true;
       break;
     }
   }
   if(!in_sd) { //if the date isn"t already in the array, add it!
     this.selectedDates.push(dates[i]);
   }
 }
 if(redraw != false) {//redraw  the calendar if "redraw" is false or undefined
   this.reDraw();
 }

}; //----------------------------------------------------------------------------- Epoch.prototype.removeDates = function (dates,redraw) //PUBLIC: adds the dates to the calendars selectedDates array and redraws the calendar {

 var j;
 for(var i=0;i<dates.length;i++)
 {
   for(j=0;j<this.selectedDates.length;j++)
   {
     if(dates[i].getUeDay() == this.selectedDates[j].getUeDay()) { //search for the dates in the selectedDates array, removing them if the dates match
       this.selectedDates.splice(j,1);
     }
   }
 }
 if(redraw != false) { //redraw  the calendar if "redraw" is false or undefined
   this.reDraw();
 }

}; //----------------------------------------------------------------------------- Epoch.prototype.outputDate = function (vDate, vFormat) //PUBLIC: outputs a date in the appropriate format (DEPRECATED) {

 var vDay      = this.addZero(vDate.getDate()); 
 var vMonth      = this.addZero(vDate.getMonth() + 1); 
 var vYearLong    = this.addZero(vDate.getFullYear()); 
 var vYearShort    = this.addZero(vDate.getFullYear().toString().substring(3,4)); 
 var vYear      = (vFormat.indexOf("yyyy") > -1 ? vYearLong : vYearShort);
 var vHour      = this.addZero(vDate.getHours()); 
 var vMinute      = this.addZero(vDate.getMinutes()); 
 var vSecond      = this.addZero(vDate.getSeconds()); 
 return vFormat.replace(/dd/g, vDay).replace(/mm/g, vMonth).replace(/y{1,4}/g, vYear).replace(/hh/g, vHour).replace(/nn/g, vMinute).replace(/ss/g, vSecond);

}; //----------------------------------------------------------------------------- Epoch.prototype.updatePos = function (target) //PUBLIC: moves the calendar"s position to target"s location (popup mode only) {

 this.calendar.style.top = this.getTop(target) + this.topOffset + "px"
 this.calendar.style.left = this.getLeft(target) + this.leftOffset + "px"

} //----------------------------------------------------------------------------- /*****************************************************************************/ function CalHeading(owner,tableCell,dow) {

 this.owner = owner;
 this.tableCell = tableCell;
 this.dayOfWeek = dow;
 
 //the event handlers
 this.tableCell.onclick = this.onclick;

} //----------------------------------------------------------------------------- CalHeading.prototype.onclick = function () {

 //reduce indirection:
 var owner = this.headObj.owner;
 var sdates = owner.selectedDates;
 var cells = owner.cells;
 
 owner.cols[this.headObj.dayOfWeek] = !owner.cols[this.headObj.dayOfWeek];
 for(var i=0;i<cells.length;i++) //cycle through all the cells in the calendar, selecting all cells with the same dayOfWeek as this heading
 {
   if(cells[i].dayOfWeek == this.headObj.dayOfWeek && (!owner.selCurMonthOnly || cells[i].date.getMonth() == owner.displayMonth && cells[i].date.getFullYear() == owner.displayYear)) //if the cell"s DoW matches, with other conditions
   {
     if(owner.cols[this.headObj.dayOfWeek])     //if selecting, add the cell"s date to the selectedDates array
     {
       if(owner.selectedDates.arrayIndex(cells[i].date) == -1) { //if the date isn"t already in the array
         sdates.push(cells[i].date);
       }
     }
     else                    //otherwise, remove it
     {
       for(var j=0;j<sdates.length;j++) 
       {
         if(cells[i].dayOfWeek == sdates[j].getDay())
         {
           sdates.splice(j,1);  //remove dates that are within the displaying month/year that have the same day of week as the day cell
           break;
         }
       }
     }
     cells[i].selected = owner.cols[this.headObj.dayOfWeek];
   }
 }
 owner.reDraw();

}; /*****************************************************************************/ function WeekHeading(owner,tableCell,week,row) {

 this.owner = owner;
 this.tableCell = tableCell;
 this.week = week;
 this.tableRow = row;
 this.tableCell.setAttribute("class","wkhead");
 this.tableCell.setAttribute("className","wkhead"); //<iehack>
 //the event handlers
 this.tableCell.onclick = this.onclick;

} //----------------------------------------------------------------------------- WeekHeading.prototype.onclick = function () {

 //reduce indirection:
 var owner = this.weekObj.owner;
 var cells = owner.cells;
 var sdates = owner.selectedDates;
 var i,j;
 owner.rows[this.weekObj.tableRow] = !owner.rows[this.weekObj.tableRow];
 for(i=0;i<cells.length;i++)
 {
   if(cells[i].tableRow == this.weekObj.tableRow)
   {
     if(owner.rows[this.weekObj.tableRow] && (!owner.selCurMonthOnly || cells[i].date.getMonth() == owner.displayMonth && cells[i].date.getFullYear() == owner.displayYear)) //match all cells in the current row, with option to restrict to current month only
     {
       if(owner.selectedDates.arrayIndex(cells[i].date) == -1) {//if the date isn"t already in the array
         sdates.push(cells[i].date);
       }
     }
     else                    //otherwise, remove it
     {
       for(j=0;j<sdates.length;j++)
       {
         if(sdates[j].getTime() == cells[i].date.getTime())  //this.weekObj.tableRow && sdates[j].getMonth() == owner.displayMonth && sdates[j].getFullYear() == owner.displayYear)
         {
           sdates.splice(j,1);  //remove dates that are within the displaying month/year that have the same day of week as the day cell
           break;
         }
       }
     }
   }
 }
 owner.reDraw();

}; /*****************************************************************************/ //----------------------------------------------------------------------------- function CalCell(owner,tableCell,dateObj,row) {

 this.owner = owner;    //used primarily for event handling
 this.tableCell = tableCell;       //the link to this cell object"s table cell in the DOM
 this.cellClass;      //the CSS class of the cell
 this.selected = false;  //whether the cell is selected (and is therefore stored in the owner"s selectedDates array)
 this.date = new Date(dateObj);
 this.dayOfWeek = this.date.getDay();
 this.week = this.date.getWeek();
 this.tableRow = row;
 
 //assign the event handlers for the table cell element
 this.tableCell.onclick = this.onclick;
 this.tableCell.onmouseover = this.onmouseover;
 this.tableCell.onmouseout = this.onmouseout;
 
 //and set the CSS class of the table cell
 this.setClass();

} //----------------------------------------------------------------------------- CalCell.prototype.onmouseover = function () //replicate CSS :hover effect for non-supporting browsers <iehack> {

 this.setAttribute("class",this.cellClass + " hover");
 this.setAttribute("className",this.cellClass + " hover");

}; //----------------------------------------------------------------------------- CalCell.prototype.onmouseout = function () //replicate CSS :hover effect for non-supporting browsers <iehack> {

 this.cellObj.setClass();

}; //----------------------------------------------------------------------------- CalCell.prototype.onclick = function () {

 //reduce indirection:
 var cell = this.cellObj;
 var owner = cell.owner;
 if(!owner.selCurMonthOnly || cell.date.getMonth() == owner.displayMonth && cell.date.getFullYear() == owner.displayYear)
 {
   if(owner.selectMultiple == true)  //if we can select multiple cells simultaneously, add the currently selected cell"s date to the selectedDates array
   {
     if(!cell.selected) //if this cell has been selected
     {
       if(owner.selectedDates.arrayIndex(cell.date) == -1) {
         owner.selectedDates.push(cell.date);
       }
     }
     else    
     {
       var tmp = owner.selectedDates; // to reduce indirection
       //if the cell has been deselected, remove it from the owner calendar"s selectedDates array
       for(var i=0;i<tmp.length;i++)
       {
         if(tmp[i].getUeDay() == cell.date.getUeDay()) {
           tmp.splice(i,1);
         }
       }
     }
   }
   else //if we can only select one cell at a time
   {
     owner.selectedDates = new Array(cell.date);
     if(owner.tgt) //if there is a target element to place the value in, do so
     {
       owner.tgt.value = owner.selectedDates[0].dateFormat();
       if(owner.mode == "popup") {
         owner.hide();
       }
     }
   }
   owner.reDraw(); //redraw the calendar cell styles to reflect the changes
 }

}; //----------------------------------------------------------------------------- CalCell.prototype.setClass = function () //private: sets the CSS class of the cell based on the specified criteria {

 if(this.selected) {
   this.cellClass = "cell_selected";
 }
 else if(this.owner.displayMonth != this.date.getMonth() ) {
   this.cellClass = "notmnth";  
 }
 else if(this.date.getDay() > 0 && this.date.getDay() < 6) {
   this.cellClass = "wkday";
 }
 else {
   this.cellClass = "wkend";
 }
 
 if(this.date.getFullYear() == this.owner.curDate.getFullYear() && this.date.getMonth() == this.owner.curDate.getMonth() && this.date.getDate() == this.owner.curDate.getDate()) {
   this.cellClass = this.cellClass + " curdate";
 }
 this.tableCell.setAttribute("class",this.cellClass);
 this.tableCell.setAttribute("className",this.cellClass); //<iehack>

}; /*****************************************************************************/ Date.prototype.getDayOfYear = function () //returns the day of the year for this date {

 return parseInt((this.getTime() - new Date(this.getFullYear(),0,1).getTime())/86400000 + 1);

}; //----------------------------------------------------------------------------- Date.prototype.getWeek = function () //returns the day of the year for this date {

 return parseInt((this.getTime() - new Date(this.getFullYear(),0,1).getTime())/604800000 + 1);

}; /*function getISOWeek() {

 var newYear = new Date(this.getFullYear(),0,1);
 var modDay = newYear.getDay();
 if (modDay == 0) modDay=6; else modDay--;
 
 var daynum = ((Date.UTC(this.getFullYear(),this.getMonth(),this.getDate(),0,0,0) - Date.UTC(this.getFullYear()),0,1,0,0,0)) /1000/60/60/24) + 1;
 
 if (modDay < 4 ) {
     var weeknum = Math.floor((daynum+modDay-1)/7)+1;
 }
 else {
     var weeknum = Math.floor((daynum+modDay-1)/7);
     if (weeknum == 0) {
         year--;
         var prevNewYear = new Date(this.getFullYear(),0,1);
         var prevmodDay = prevNewYear.getDay();
         if (prevmodDay == 0) prevmodDay = 6; else prevmodDay--;
         if (prevmodDay < 4) weeknum = 53; else weeknum = 52;
     }
 }
 
 return + weeknum;

}*/ //----------------------------------------------------------------------------- Date.prototype.getUeDay = function () //returns the number of DAYS since the UNIX Epoch - good for comparing the date portion {

 return parseInt(Math.floor((this.getTime() - this.getTimezoneOffset() * 60000)/86400000)); //must take into account the local timezone

}; //----------------------------------------------------------------------------- Date.prototype.dateFormat = function(format) {

 if(!format) { // the default date format to use - can be customized to the current locale
   format = "m/d/Y";
 }
 LZ = function(x) {return(x < 0 || x > 9 ? "" : "0") + x};
 var MONTH_NAMES = new Array("January","February","March","April","May","June","July","August","September","October","November","December","Jan","Feb","Mar","Apr","May","Jun","Jul","Aug","Sep","Oct","Nov","Dec");
 var DAY_NAMES = new Array("Sunday","Monday","Tuesday","Wednesday","Thursday","Friday","Saturday","Sun","Mon","Tue","Wed","Thu","Fri","Sat");
 format = format + "";
 var result="";
 var i_format=0;
 var c="";
 var token="";
 var y=this.getFullYear().toString();
 var M=this.getMonth()+1;
 var d=this.getDate();
 var E=this.getDay();
 var H=this.getHours();
 var m=this.getMinutes();
 var s=this.getSeconds();
 var yyyy,yy,MMM,MM,dd,hh,h,mm,ss,ampm,HH,H,KK,K,kk,k;
 // Convert real this parts into formatted versions
 var value = new Object();
 //if (y.length < 4) {y=""+(y-0+1900);}
 value["Y"] = y.toString();
 value["y"] = y.substring(2);
 value["n"] = M;
 value["m"] = LZ(M);
 value["F"] = MONTH_NAMES[M-1];
 value["M"] = MONTH_NAMES[M+11];
 value["j"] = d;
 value["d"] = LZ(d);
 value["D"] = DAY_NAMES[E+7];
 value["l"] = DAY_NAMES[E];
 value["G"] = H;
 value["H"] = LZ(H);
 if (H==0) {value["g"]=12;}
 else if (H>12){value["g"]=H-12;}
 else {value["g"]=H;}
 value["h"]=LZ(value["g"]);
 if (H > 11) {value["a"]="pm"; value["A"] = "PM";}
 else { value["a"]="am"; value["A"] = "AM";}
 value["i"]=LZ(m);
 value["s"]=LZ(s);
 //construct the result string
 while (i_format < format.length) {
   c=format.charAt(i_format);
   token="";
   while ((format.charAt(i_format)==c) && (i_format < format.length)) {
     token += format.charAt(i_format++);
     }
   if (value[token] != null) { result=result + value[token]; }
   else { result=result + token; }
   }
 return result;

}; /*****************************************************************************/ Array.prototype.arrayIndex = function(searchVal,startIndex) //similar to array.indexOf() - created to fix IE deficiencies {

 startIndex = (startIndex != null ? startIndex : 0); //default startIndex to 0, if not set
 for(var i=startIndex;i<this.length;i++)
 {
   if(searchVal == this[i]) {
     return i;
   }
 }
 return -1;

}; /*****************************************************************************/ </script> <script type="text/javascript"> /*You can also place this code in a separate file and link to it like epoch_classes.js*/

 var bas_cal,dp_cal,ms_cal;      

window.onload = function () {

 ms_cal  = new Epoch("epoch_multi","flat",document.getElementById("multi_container"),true);

}; </script> </head> <body>

Multiselect

</body> </html>


 </source>
   
  


Open calendar

<A href="http://www.wbex.ru/Code/JavaScriptDownload/open_calendar_1.001.zip">open_calendar_1.001.zip( 9 k)</a>

1. <A href="/Code/JavaScript/GUI-Components/HTMLCalendarbasedonDynAPI.htm">HTML Calendar based on DynAPI</a> <A href="/Code/JavaScript/GUI-Components/HTMLCalendarbasedonDynAPI.htm"></a> 2. <A href="/Code/JavaScript/GUI-Components/JavaScriptDatePickerbasedonComboBox.htm">JavaScript Date Picker based on ComboBox</a> <A href="/Code/JavaScript/GUI-Components/JavaScriptDatePickerbasedonComboBox.htm"></a> 3. <A href="/Code/JavaScript/GUI-Components/CalendarControlSingleSelectImplementation.htm">Calendar Control - Single-Select Implementation</a> <A href="/Code/JavaScript/GUI-Components/CalendarControlSingleSelectImplementation.htm"></a> 4. <A href="/Code/JavaScript/GUI-Components/CalendarControl2UpImplementation.htm">Calendar Control - 2-Up Implementation</a> <A href="/Code/JavaScript/GUI-Components/CalendarControl2UpImplementation.htm"></a> 5. <A href="/Code/JavaScript/GUI-Components/CalendarControlHandlingonSelectonDeselect.htm">Calendar Control - Handling onSelect / onDeselect</a> <A href="/Code/JavaScript/GUI-Components/CalendarControlHandlingonSelectonDeselect.htm"></a> 6. <A href="/Code/JavaScript/GUI-Components/CalendarControlMixMaxImplementation.htm">Calendar Control - Mix/Max Implementation</a> <A href="/Code/JavaScript/GUI-Components/CalendarControlMixMaxImplementation.htm"></a> 7. <A href="/Code/JavaScript/GUI-Components/CalendarControlMultiSelectImplementation.htm">Calendar Control - Multi-Select Implementation</a> <A href="/Code/JavaScript/GUI-Components/CalendarControlMultiSelectImplementation.htm"></a> 8. <A href="/Code/JavaScript/GUI-Components/CalendarControlMultiSelect2upImplementation.htm">Calendar Control - Multi-Select 2-up Implementation</a> <A href="/Code/JavaScript/GUI-Components/CalendarControlMultiSelect2upImplementation.htm"></a> 9. <A href="/Code/JavaScript/GUI-Components/CalendarControlCustomRendererExampleHolidayRendererImplementation.htm">Calendar Control - Custom Renderer Example (Holiday Renderer Implementation)</a> <A href="/Code/JavaScript/GUI-Components/CalendarControlCustomRendererExampleHolidayRendererImplementation.htm"></a> 10. <A href="/Code/JavaScript/GUI-Components/CalendarControlDateRestrictionExampleDateRestrictionImplementation.htm">Calendar Control - Date Restriction Example (Date Restriction Implementation)</a> <A href="/Code/JavaScript/GUI-Components/CalendarControlDateRestrictionExampleDateRestrictionImplementation.htm"></a> 11. <A href="/Code/JavaScript/GUI-Components/CalendarControlRowHighlightExampleRowHighlightImplementation.htm">Calendar Control - Row Highlight Example (Row Highlight Implementation)</a> <A href="/Code/JavaScript/GUI-Components/CalendarControlRowHighlightExampleRowHighlightImplementation.htm"></a> 12. <A href="/Code/JavaScript/GUI-Components/Popupcalendar.htm">Popup calendar</a> <A href="/Code/JavaScript/GUI-Components/Popupcalendar.htm"></a> 13. <A href="/Code/JavaScript/GUI-Components/MonthCalendar.htm">Month Calendar</a> 14. <A href="/Code/JavaScript/GUI-Components/PopupCalendarforatextfield.htm">Popup Calendar for a textfield</a> 15. <A href="/Code/JavaScript/GUI-Components/MultiselectionCalendar.htm">Multiselection Calendar</a> 16. <A href="/Code/JavaScript/GUI-Components/FreeDatePickerAneasyplugintoaddadatepickercalendarinyourwebsite.htm">Free Date Picker : An easy plugin to add a date picker (calendar) in your web site</a> 17. <A href="/Code/JavaScript/GUI-Components/HTMLDatePicker.htm">HTML Date Picker</a> 18. <A href="/Code/JavaScript/GUI-Components/DatePickerinnewwindow.htm">Date Picker in new window</a> <A href="/Code/JavaScript/GUI-Components/DatePickerinnewwindow.htm"></a> 19. <A href="/Code/JavaScript/GUI-Components/AllbrowserCalendar.htm">All browser Calendar</a> <A href="/Code/JavaScript/GUI-Components/AllbrowserCalendar.htm"></a> 20. <A href="/Code/JavaScript/GUI-Components/DHTMLCalendarfortheimpatient.htm">DHTML Calendar for the impatient</a> <A href="/Code/JavaScript/GUI-Components/DHTMLCalendarfortheimpatient.htm"></a> 21. <A href="/Code/JavaScript/GUI-Components/Calendarspecialday.htm">Calendar: special day</a> <A href="/Code/JavaScript/GUI-Components/Calendarspecialday.htm"></a> 22. <A href="/Code/JavaScript/GUI-Components/Calendardayinfo.htm">Calendar: day info</a> <A href="/Code/JavaScript/GUI-Components/Calendardayinfo.htm"></a> 23. <A href="/Code/JavaScript/GUI-Components/CalendarMultipledayselection.htm">Calendar: Multiple day selection</a> <A href="/Code/JavaScript/GUI-Components/CalendarMultipledayselection.htm"></a> 24. <A href="/Code/JavaScript/GUI-Components/Calendarwithdifferenttheme.htm">Calendar with different theme</a> <A href="/Code/JavaScript/GUI-Components/Calendarwithdifferenttheme.htm"></a> 25. <A href="/Code/JavaScript/GUI-Components/Calendarwithimageforeachmonth.htm">Calendar with image for each month</a> <A href="/Code/JavaScript/GUI-Components/Calendarwithimageforeachmonth.htm"></a> 26. <A href="/Code/JavaScript/GUI-Components/FancyCalendar.htm">Fancy Calendar </a> <A href="/Code/JavaScript/GUI-Components/FancyCalendar.htm"></a> 27. <A href="/Code/JavaScript/GUI-Components/AnotherCalendar.htm">Another Calendar </a> <A href="/Code/JavaScript/GUI-Components/AnotherCalendar.htm"></a> 28. <A href="/Code/JavaScript/GUI-Components/DateTimePicker.htm">Date Time Picker</a> <A href="/Code/JavaScript/GUI-Components/DateTimePicker.htm"></a> 29. <A href="/Code/JavaScript/GUI-Components/MonthCalendar2.htm">Month Calendar (2)</a> 30. <A href="/Code/JavaScript/GUI-Components/BuildingaCalculator.htm">Building a Calculator</a> 31. <A href="/Code/JavaScript/GUI-Components/ADynamicCalendarTable.htm">A Dynamic Calendar Table</a> 32. <A href="/Code/JavaScript/GUI-Components/DynamicHTMLCalendar.htm">Dynamic HTML Calendar</a> 33. <A href="/Code/JavaScript/GUI-Components/AStaticCalendarbyJavaScript.htm"> A Static Calendar by JavaScript</a> 34. <A href="/Code/JavaScript/GUI-Components/DisplayingtheCalendar.htm">Displaying the Calendar</a> 35. <A href="/Code/JavaScript/GUI-Components/CalendarIEonly.htm">Calendar (IE only)</a> 36. <A href="/Code/JavaScript/GUI-Components/Calendarinslidetab.htm">Calendar in slide tab</a> 37. <A href="/Code/JavaScript/GUI-Components/AnotherDHTMLCalendar.htm">Another DHTML Calendar</a> 38. <A href="/Code/JavaScript/GUI-Components/EventCalendar.htm">Event Calendar</a> <A href="/Code/JavaScript/GUI-Components/EventCalendar.htm"></a> 39. <A href="/Code/JavaScript/GUI-Components/swazzcalendar10.htm">swazz calendar 1.0</a> <A href="/Code/JavaScript/GUI-Components/swazzcalendar10.htm"></a> 40. <A href="/Code/JavaScript/GUI-Components/jquerycalendar.htm">jquery calendar</a> <A href="/Code/JavaScript/GUI-Components/jquerycalendar.htm"></a>

Popup calendar

   <source lang="html4strict">

<html>

 <head>
   <title>Popup Calendar Demo</title>
   <style>
   </style>
   <script language="Javascript">

// {{{ docs <-- this is a VIM (text editor) text fold /**

* Popup Calendar {VERSION}
*
* Summary: Popup Calendar is a date selector script that can be associated with
*          an image next to a text form element that requires a date. The calendar
*          pops up, at which point a date can be selected, and it will close the
*          calendar and pass the date down to the input field. It has customizable
*          colors and full year/month navigation. It works on all browsers (Konqueror,
*          IE, Netscape 4, Mozilla, Opera) and makes choosing dates in forms much more
*          pleasant.
*
* Maintainer: Dan Allen <dan@mojavelinux.ru>
*
* License: LGPL - however, if you use this library, please post to my forum where you
*          use it so that I get a chance to see my baby in action.  If you are doing
*          this for commercial work perhaps you could send me a few Starbucks Coffee
*          gift dollars to encourage future developement (NOT REQUIRED).  E-mail me
*          for and address.
*
* Homepage: http://www.mojavelinux.ru/forum/viewtopic.php?t=6
*
* Freshmeat Project: http://freshmeat.net/projects/popupcalendar/?topic_id=92
*
* Updated: {UPDATED}
*
* Supported Browsers: Mozilla (Gecko), IE 5+, Konqueror, Opera 7, Netscape 4
*
* Usage: 
* Bascially, you need to pay attention to the paths and make sure
* that the function getCalendar is looking in the right place for calendar.html,
* which is the parent frame of calendar_body.html.  
* 
* The colors are configured as an associative array in the parent window.  I
* haven"t had a chance to document this yet, but you should be able to see what I
* am going for in the calendar.js file.  All you have to do when calling
* getCalendar is specify the full object to that form element, such as
* 
* return getCalendar(document.formName.elementName);
* 
* You will need to put killCalendar() in the body to make it go away if it is still open
* when the page changes.
    • /

// }}} // {{{ settings (Editable) var calendarWindow = null; var calendarColors = new Array(); calendarColors["bgColor"] = "#BDC5D0"; calendarColors["borderColor"] = "#333366"; calendarColors["headerBgColor"] = "#143464"; calendarColors["headerColor"] = "#FFFFFF"; calendarColors["dateBgColor"] = "#8493A8"; calendarColors["dateColor"] = "#004080"; calendarColors["dateHoverBgColor"] = "#FFFFFF"; calendarColors["dateHoverColor"] = "#8493A8"; var calendarMonths = new Array("January", "February", "March", "April", "May", "June", "July", "August", "September", "October", "November", "December"); var calendarWeekdays = new Array("S", "M", "T", "W", "T", "F", "S", "S"); var calendarUseToday = true; var calendarFormat = "y/m/d"; var calendarStartMonday = true; var calendarScreenX = 100; // either "auto" or numeric var calendarScreenY = 100; // either "auto" or numeric // }}} // {{{ getCalendar() function getCalendar(in_dateField) {

   if (calendarWindow && !calendarWindow.closed) {
       alert("Calendar window already open.  Attempting focus...");
       try {
           calendarWindow.focus();
       }
       catch(e) {}
       
       return false;
   }
   var cal_width = 415;
   var cal_height = 310;
   // IE needs less space to make this thing
   if ((document.all) && (navigator.userAgent.indexOf("Konqueror") == -1)) {
       cal_width = 410;
   }
   calendarTarget = in_dateField;
   calendarWindow = window.open("calendar.html", "dateSelectorPopup","toolbar=no,location=no,directories=no,status=no,menubar=no,scrollbars=no,resizable=0,dependent=no,width="+cal_width+",height="+cal_height + (calendarScreenX != "auto" ? ",screenX=" + calendarScreenX : "") + (calendarScreenY != "auto" ? ",screenY=" + calendarScreenY : ""));
   return false;

} // }}} // {{{ killCalendar() function killCalendar() {

   if (calendarWindow && !calendarWindow.closed) {
       calendarWindow.close();
   }

} // }}}

   </script>
 </head>
 <body>
   <form name="foo">
     <input type="text" name="bar" /><a href="#" onclick="return getCalendar(document.foo.bar);"><img src="calendar.png" border="0" /></a>
   </form>
 </body>

</html>


 </source>
   
  

<A href="http://www.wbex.ru/Code/JavaScriptDownload/popupcalendar-2.0.6.zip">popupcalendar-2.0.6.zip( 23 k)</a>


Popup Calendar for a textfield

   <source lang="html4strict">

<html> <head> <title>Minimum Required Code - Epoch DHTML Javascript Calendar</title> <style rel="stylesheet" type="text/css"> table.calendar {

 font-family: Helvetica, Arial, sans-serif;
 font-size: 0.8em;
 border-collapse: collapse;
 background-color: white;
 border: solid #999999 1px;
 background-color: white;
 width: 200px;
 text-align: center;
 /*prevent user from selecting text in Mozilla & Safari - check calendar constructor for IE code)*/
 -moz-user-select: none;
   /*-khtml-user-select: none;*/

} table.calendar input, table.calendar select {

 font-size: 10px;

} table.calendar td {

 border: 0;
 font-size: 10px;
 text-align: center;

} div.mainheading {

 margin: 2px;

} table.caldayheading {

 border-collapse: collapse;
 cursor: pointer;
 empty-cells: show;
 margin: 0 6px 0 6px;

} table.caldayheading td {

 border: solid #CCCCCC 1px;
 text-align: left;
 color: #0054E3;
 font-weight: bold;
 width: 22px; /*should match calendar cell"s width*/

} table.caldayheading td.wkhead {

 border-right: double #CCCCCC 3px;

} table.calcells {

 border-collapse: collapse;
 cursor: pointer;
 margin: 0 6px 0 6px;

} table.calcells td {

 border: solid #CCCCCC 1px;
 vertical-align: top;
 text-align: left;
 font-weight: bold;
 width: 22px;
 height: 20px; /*IE doesn"t like ems*/

} table.calcells td div {

 padding: 1px;
 margin: 0;

} table.calcells td.wkhead {

 background-color: white;
 text-align: center;
 border-right: double #CCCCCC 3px;
 color: #0054E3;

} table.calcells td.wkday {

 background-color: #DDDDDD;

} table.calcells td.wkend {

 background-color: #DDDDDD;

} table.calcells td.curdate { } table.calcells td.cell_selected {

 background-color: #99CCFF;
 color: black;

} table.calcells td.notmnth {

 background-color: #FFFFFF;
 color: #CCCCCC;

} table.calcells td.notallowed {

 background-color: white;
 color: #EEEEEE;
 font-style: italic;

} table.calcells td.hover {

 background-color: #999999;

} </style> <script type="text/javascript"> /***************************************************************************** Copyright (C) 2006 Nick Baicoianu This program is free software; you can redistribute it and/or modify it under the terms of the GNU General Public License as published by the Free Software Foundation; either version 2 of the License, or (at your option) any later version. This program is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for more details. You should have received a copy of the GNU General Public License along with this program; if not, write to the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.

                                                                                                                                                          • /

//constructor for the main Epoch class (ENGLISH VERSION) function Epoch(name,mode,targetelement,multiselect) {

 this.state = 0;
 this.name = name;
 this.curDate = new Date();
 this.mode = mode;
 this.selectMultiple = (multiselect == true); //"false" is not true or not set at all
 
 //the various calendar variables
 //this.selectedDate = this.curDate;
 this.selectedDates = new Array();
 this.calendar;
 this.calHeading;
 this.calCells;
 this.rows;
 this.cols;
 this.cells = new Array();
 
 //The controls
 this.monthSelect;
 this.yearSelect;
 
 //standard initializations
 this.mousein = false;
 this.calConfig();
 this.setDays();
 this.displayYear = this.displayYearInitial;
 this.displayMonth = this.displayMonthInitial;
 
 this.createCalendar(); //create the calendar DOM element and its children, and their related objects
 
 if(this.mode == "popup" && targetelement && targetelement.type == "text") //if the target element has been set to be an input text box
 {
   this.tgt = targetelement;
   this.calendar.style.position = "absolute";
   this.topOffset = this.tgt.offsetHeight; // the vertical distance (in pixels) to display the calendar from the Top of its input element
   this.leftOffset = 0;           // the horizontal distance (in pixels) to display the calendar from the Left of its input element
   this.calendar.style.top = this.getTop(targetelement) + this.topOffset + "px";
   this.calendar.style.left = this.getLeft(targetelement) + this.leftOffset + "px";
   document.body.appendChild(this.calendar);
   this.tgt.calendar = this;
   this.tgt.onfocus = function () {this.calendar.show();}; //the calendar will popup when the input element is focused
   this.tgt.onblur = function () {if(!this.calendar.mousein){this.calendar.hide();}}; //the calendar will popup when the input element is focused
 }
 else
 {
   this.container = targetelement;
   this.container.appendChild(this.calendar);
 }
 
 this.state = 2; //0: initializing, 1: redrawing, 2: finished!
 this.visible ? this.show() : this.hide();

} //----------------------------------------------------------------------------- Epoch.prototype.calConfig = function () //PRIVATE: initialize calendar variables {

 //this.mode = "flat"; //can be "flat" or "popup"
 this.displayYearInitial = this.curDate.getFullYear(); //the initial year to display on load
 this.displayMonthInitial = this.curDate.getMonth(); //the initial month to display on load (0-11)
 this.rangeYearLower = 2005;
 this.rangeYearUpper = 2037;
 this.minDate = new Date(2005,0,1);
 this.maxDate = new Date(2037,0,1);
 this.startDay = 0; // the day the week will "start" on: 0(Sun) to 6(Sat)
 this.showWeeks = true; //whether the week numbers will be shown
 this.selCurMonthOnly = false; //allow user to only select dates in the currently displayed month
 this.clearSelectedOnChange = true; //whether to clear all selected dates when changing months
 
 //flat mode-only settings:
 //this.selectMultiple = true; //whether the user can select multiple dates (flat mode only)
 switch(this.mode) //set the variables based on the calendar mode
 {
   case "popup": //popup options
     this.visible = false;
     break;
   case "flat":
     this.visible = true;
     
     break;
 }
 this.setLang();

}; //----------------------------------------------------------------------------- Epoch.prototype.setLang = function() //all language settings for Epoch are made here. Check Date.dateFormat() for the Date object"s language settings {

 this.daylist = new Array("Su","Mo","Tu","We","Th","Fr","Sa","Su","Mo","Tu","We","Th","Fr","Sa"); /*<lang:en>*/
 this.months_sh = new Array("Jan","Feb","Mar","Apr","May","Jun","Jul","Aug","Sep","Oct","Nov","Dec");
 this.monthup_title = "Go to the next month";
 this.monthdn_title = "Go to the previous month";
 this.clearbtn_caption = "Clear";
 this.clearbtn_title = "Clears any dates selected on the calendar";
 this.maxrange_caption = "This is the maximum range";

}; //----------------------------------------------------------------------------- Epoch.prototype.getTop = function (element) //PRIVATE: returns the absolute Top value of element, in pixels {

   var oNode = element;
   var iTop = 0;
   
   while(oNode.tagName != "BODY") {
       iTop += oNode.offsetTop;
       oNode = oNode.offsetParent;
   }
   
   return iTop;

}; //----------------------------------------------------------------------------- Epoch.prototype.getLeft = function (element) //PRIVATE: returns the absolute Left value of element, in pixels {

   var oNode = element;
   var iLeft = 0;
   
   while(oNode.tagName != "BODY") {
       iLeft += oNode.offsetLeft;
       oNode = oNode.offsetParent;        
   }
   
   return iLeft;

}; //----------------------------------------------------------------------------- Epoch.prototype.show = function () //PUBLIC: displays the calendar {

 this.calendar.style.display = "block";
 this.visible = true;

}; //----------------------------------------------------------------------------- Epoch.prototype.hide = function () //PUBLIC: Hides the calendar {

 this.calendar.style.display = "none";
 this.visible = false;

}; //----------------------------------------------------------------------------- Epoch.prototype.toggle = function () //PUBLIC: Toggles (shows/hides) the calendar depending on its current state {

 if(this.visible) {
   this.hide();
 }
 else {
   this.show();
 }

}; //----------------------------------------------------------------------------- Epoch.prototype.setDays = function () //PRIVATE: initializes the standard Gregorian Calendar parameters {

 this.daynames = new Array();
 var j=0;
 for(var i=this.startDay; i< this.startDay + 7;i++) {
   this.daynames[j++] = this.daylist[i];
 }
   
 this.monthDayCount = new Array(31,((this.curDate.getFullYear() - 2000) % 4 ? 28 : 29),31,30,31,30,31,31,30,31,30,31);

}; //----------------------------------------------------------------------------- Epoch.prototype.setClass = function (element,className) //PRIVATE: sets the CSS class of the element, W3C & IE {

 element.setAttribute("class",className);
 element.setAttribute("className",className); //<iehack>

}; //----------------------------------------------------------------------------- Epoch.prototype.createCalendar = function () //PRIVATE: creates the full DOM implementation of the calendar {

 var tbody, tr, td;
 this.calendar = document.createElement("table");
 this.calendar.setAttribute("id",this.name+"_calendar");
 this.setClass(this.calendar,"calendar");
 //to prevent IE from selecting text when clicking on the calendar
 this.calendar.onselectstart = function() {return false;};
 this.calendar.ondrag = function() {return false;};
 tbody = document.createElement("tbody");
 
 //create the Main Calendar Heading
 tr = document.createElement("tr");
 td = document.createElement("td");
 td.appendChild(this.createMainHeading());
 tr.appendChild(td);
 tbody.appendChild(tr);
 
 //create the calendar Day Heading
 tr = document.createElement("tr");
 td = document.createElement("td");
 td.appendChild(this.createDayHeading());
 tr.appendChild(td);
 tbody.appendChild(tr);
 //create the calendar Day Cells
 tr = document.createElement("tr");
 td = document.createElement("td");
 td.setAttribute("id",this.name+"_cell_td");
 this.calCellContainer = td;  //used as a handle for manipulating the calendar cells as a whole
 td.appendChild(this.createCalCells());
 tr.appendChild(td);
 tbody.appendChild(tr);
 
 //create the calendar footer
 tr = document.createElement("tr");
 td = document.createElement("td");
 td.appendChild(this.createFooter());
 tr.appendChild(td);
 tbody.appendChild(tr);
 
 //add the tbody element to the main calendar table
 this.calendar.appendChild(tbody);
 //and add the onmouseover events to the calendar table
 this.calendar.owner = this;
 this.calendar.onmouseover = function() {this.owner.mousein = true;};
 this.calendar.onmouseout = function() {this.owner.mousein = false;};

}; //----------------------------------------------------------------------------- Epoch.prototype.createMainHeading = function () //PRIVATE: Creates the primary calendar heading, with months & years {

//create the containing
element
 var container = document.createElement("div");
 container.setAttribute("id",this.name+"_mainheading");
 this.setClass(container,"mainheading");
 //create the child elements and other variables
 this.monthSelect = document.createElement("select");
 this.yearSelect = document.createElement("select");
 var monthDn = document.createElement("input"), monthUp = document.createElement("input");
 var opt, i;
 //fill the month select box
 for(i=0;i<12;i++)
 {
   opt = document.createElement("option");
   opt.setAttribute("value",i);
   if(this.state == 0 && this.displayMonth == i) {
     opt.setAttribute("selected","selected");
   }
   opt.appendChild(document.createTextNode(this.months_sh[i]));
   this.monthSelect.appendChild(opt);
 }
 //and fill the year select box
 for(i=this.rangeYearLower;i<=this.rangeYearUpper;i++)
 {
   opt = document.createElement("option");
   opt.setAttribute("value",i);
   if(this.state == 0 && this.displayYear == i) {
     opt.setAttribute("selected","selected");
   }
   opt.appendChild(document.createTextNode(i));
   this.yearSelect.appendChild(opt);    
 }
 //add the appropriate children for the month buttons
 monthUp.setAttribute("type","button");
 monthUp.setAttribute("value",">");
 monthUp.setAttribute("title",this.monthup_title);
 monthDn.setAttribute("type","button");
 monthDn.setAttribute("value","<");
 monthDn.setAttribute("title",this.monthdn_title);
 this.monthSelect.owner = this.yearSelect.owner = monthUp.owner = monthDn.owner = this;  //hack to allow us to access this calendar in the events (<fix>??)
 
 //assign the event handlers for the controls
 monthUp.onmouseup = function () {this.owner.nextMonth();};
 monthDn.onmouseup = function () {this.owner.prevMonth();};
 this.monthSelect.onchange = function() {
   this.owner.displayMonth = this.value;
   this.owner.displayYear = this.owner.yearSelect.value; 
   this.owner.goToMonth(this.owner.displayYear,this.owner.displayMonth);
 };
 this.yearSelect.onchange = function() {
   this.owner.displayMonth = this.owner.monthSelect.value;
   this.owner.displayYear = this.value; 
   this.owner.goToMonth(this.owner.displayYear,this.owner.displayMonth);
 };
 
 //and finally add the elements to the containing div
 container.appendChild(monthDn);
 container.appendChild(this.monthSelect);
 container.appendChild(this.yearSelect);
 container.appendChild(monthUp);
 return container;

}; //----------------------------------------------------------------------------- Epoch.prototype.createFooter = function () //PRIVATE: creates the footer of the calendar - goes under the calendar cells {

 var container = document.createElement("div");
 var clearSelected = document.createElement("input");
 clearSelected.setAttribute("type","button");
 clearSelected.setAttribute("value",this.clearbtn_caption);
 clearSelected.setAttribute("title",this.clearbtn_title);
 clearSelected.owner = this;
 clearSelected.onclick = function() { this.owner.resetSelections(false);};
 container.appendChild(clearSelected);
 return container;

}; //----------------------------------------------------------------------------- Epoch.prototype.resetSelections = function (returnToDefaultMonth) //PRIVATE: reset the calendar"s selection variables to defaults {

 this.selectedDates = new Array();
 this.rows = new Array(false,false,false,false,false,false,false);
 this.cols = new Array(false,false,false,false,false,false,false);
 if(this.tgt)  //if there is a target element, clear it too
 {
   this.tgt.value = "";
   if(this.mode == "popup") {//hide the calendar if in popup mode
     this.hide();
   }
 }
   
 if(returnToDefaultMonth == true) {
   this.goToMonth(this.displayYearInitial,this.displayMonthInitial);
 }
 else {
   this.reDraw();
 }

}; //----------------------------------------------------------------------------- Epoch.prototype.createDayHeading = function () //PRIVATE: creates the heading containing the day names {

 //create the table element
 this.calHeading = document.createElement("table");
 this.calHeading.setAttribute("id",this.name+"_caldayheading");
 this.setClass(this.calHeading,"caldayheading");
 var tbody,tr,td;
 tbody = document.createElement("tbody");
 tr = document.createElement("tr");
 this.cols = new Array(false,false,false,false,false,false,false);
 
 //if we"re showing the week headings, create an empty <td> for filler
 if(this.showWeeks)
 {
   td = document.createElement("td");
   td.setAttribute("class","wkhead");
   td.setAttribute("className","wkhead"); //<iehack>
   tr.appendChild(td);
 }
 //populate the day titles
 for(var dow=0;dow<7;dow++)
 {
   td = document.createElement("td");
   td.appendChild(document.createTextNode(this.daynames[dow]));
   if(this.selectMultiple) { //if selectMultiple is true, assign the cell a CalHeading Object to handle all events
     td.headObj = new CalHeading(this,td,(dow + this.startDay < 7 ? dow + this.startDay : dow + this.startDay - 7));
   }
   tr.appendChild(td);
 }
 tbody.appendChild(tr);
 this.calHeading.appendChild(tbody);
 return this.calHeading;  

}; //----------------------------------------------------------------------------- Epoch.prototype.createCalCells = function () //PRIVATE: creates the table containing the calendar day cells {

 this.rows = new Array(false,false,false,false,false,false);
 this.cells = new Array();
 var row = -1, totalCells = (this.showWeeks ? 48 : 42);
 var beginDate = new Date(this.displayYear,this.displayMonth,1);
 var endDate = new Date(this.displayYear,this.displayMonth,this.monthDayCount[this.displayMonth]);
 var sdt = new Date(beginDate);
 sdt.setDate(sdt.getDate() + (this.startDay - beginDate.getDay()) - (this.startDay - beginDate.getDay() > 0 ? 7 : 0) );
 //create the table element
 this.calCells = document.createElement("table");
 this.calCells.setAttribute("id",this.name+"_calcells");
 this.setClass(this.calCells,"calcells");
 var tbody,tr,td;
 tbody = document.createElement("tbody");
 for(var i=0;i<totalCells;i++)
 {
   if(this.showWeeks) //if we are showing the week headings
   {
     if(i % 8 == 0)
     {
       row++;
       tr = document.createElement("tr");
       td = document.createElement("td");
       if(this.selectMultiple) { //if selectMultiple is enabled, create the associated weekObj objects
         td.weekObj = new WeekHeading(this,td,sdt.getWeek(),row)
       }
       else //otherwise just set the class of the td for consistent look
       {
         td.setAttribute("class","wkhead");
         td.setAttribute("className","wkhead"); //<iehack>
       }
       td.appendChild(document.createTextNode(sdt.getWeek()));      
       tr.appendChild(td);
       i++;
     }
   }
   else if(i % 7 == 0) //otherwise, new row every 7 cells
   {
     row++;
     tr = document.createElement("tr");
   }
   //create the day cells
   td = document.createElement("td");
   td.appendChild(document.createTextNode(sdt.getDate()));// +" " +sdt.getUeDay()));
   var cell = new CalCell(this,td,sdt,row);
   this.cells.push(cell);
   td.cellObj = cell;
   sdt.setDate(sdt.getDate() + 1); //increment the date
   tr.appendChild(td);
   tbody.appendChild(tr);
 }
 this.calCells.appendChild(tbody);
 this.reDraw();
 return this.calCells;

}; //----------------------------------------------------------------------------- Epoch.prototype.reDraw = function () //PRIVATE: reapplies all the CSS classes for the calendar cells, usually called after chaning their state {

 this.state = 1;
 var i,j;
 for(i=0;i<this.cells.length;i++) {
   this.cells[i].selected = false;
 }
 for(i=0;i<this.cells.length;i++)
 {
   for(j=0;j<this.selectedDates.length;j++) { //if the cell"s date is in the selectedDates array, set its selected property to true
     if(this.cells[i].date.getUeDay() == this.selectedDates[j].getUeDay() ) {
       this.cells[i].selected = true;
     }
   }
   this.cells[i].setClass();
 }
 //alert(this.selectedDates);
 this.state = 2;

}; //----------------------------------------------------------------------------- Epoch.prototype.deleteCells = function () //PRIVATE: removes the calendar cells from the DOM (does not delete the cell objects associated with them {

 this.calCellContainer.removeChild(this.calCellContainer.firstChild); //get a handle on the cell table (optional - for less indirection)
 this.cells = new Array(); //reset the cells array

}; //----------------------------------------------------------------------------- Epoch.prototype.goToMonth = function (year,month) //PUBLIC: sets the calendar to display the requested month/year {

 this.monthSelect.value = this.displayMonth = month;
 this.yearSelect.value = this.displayYear = year;
 this.deleteCells();
 this.calCellContainer.appendChild(this.createCalCells());

}; //----------------------------------------------------------------------------- Epoch.prototype.nextMonth = function () //PUBLIC: go to the next month. if the month is december, go to january of the next year {

 //increment the month/year values, provided they"re within the min/max ranges
 if(this.monthSelect.value < 11) {
   this.monthSelect.value++;
 }
 else
 {
   if(this.yearSelect.value < this.rangeYearUpper)
   {
     this.monthSelect.value = 0;
     this.yearSelect.value++;
   }
   else {
     alert(this.maxrange_caption);
   }
 }
 //assign the currently displaying month/year values
 this.displayMonth = this.monthSelect.value;
 this.displayYear = this.yearSelect.value;
 
 //and refresh the calendar for the new month/year
 this.deleteCells();
 this.calCellContainer.appendChild(this.createCalCells());

}; //----------------------------------------------------------------------------- Epoch.prototype.prevMonth = function () //PUBLIC: go to the previous month. if the month is january, go to december of the previous year {

 //increment the month/year values, provided they"re within the min/max ranges
 if(this.monthSelect.value > 0)
   this.monthSelect.value--;
 else
 {
   if(this.yearSelect.value > this.rangeYearLower)
   {
     this.monthSelect.value = 11;
     this.yearSelect.value--;
   }
   else {
     alert(this.maxrange_caption);
   }
 }
 
 //assign the currently displaying month/year values
 this.displayMonth = this.monthSelect.value;
 this.displayYear = this.yearSelect.value;
 
 //and refresh the calendar for the new month/year
 this.deleteCells();
 this.calCellContainer.appendChild(this.createCalCells());

}; //----------------------------------------------------------------------------- Epoch.prototype.addZero = function (vNumber) //PRIVATE: pads a 2 digit number with a leading zero {

 return ((vNumber < 10) ? "0" : "") + vNumber;

}; //----------------------------------------------------------------------------- Epoch.prototype.addDates = function (dates,redraw) //PUBLIC: adds the array "dates" to the calendars selectedDates array (no duplicate dates) and redraws the calendar {

 var j,in_sd;
 for(var i=0;i<dates.length;i++)
 {  
   in_sd = false;
   for(j=0;j<this.selectedDates.length;j++)
   {
     if(dates[i].getUeDay() == this.selectedDates[j].getUeDay())
     {
       in_sd = true;
       break;
     }
   }
   if(!in_sd) { //if the date isn"t already in the array, add it!
     this.selectedDates.push(dates[i]);
   }
 }
 if(redraw != false) {//redraw  the calendar if "redraw" is false or undefined
   this.reDraw();
 }

}; //----------------------------------------------------------------------------- Epoch.prototype.removeDates = function (dates,redraw) //PUBLIC: adds the dates to the calendars selectedDates array and redraws the calendar {

 var j;
 for(var i=0;i<dates.length;i++)
 {
   for(j=0;j<this.selectedDates.length;j++)
   {
     if(dates[i].getUeDay() == this.selectedDates[j].getUeDay()) { //search for the dates in the selectedDates array, removing them if the dates match
       this.selectedDates.splice(j,1);
     }
   }
 }
 if(redraw != false) { //redraw  the calendar if "redraw" is false or undefined
   this.reDraw();
 }

}; //----------------------------------------------------------------------------- Epoch.prototype.outputDate = function (vDate, vFormat) //PUBLIC: outputs a date in the appropriate format (DEPRECATED) {

 var vDay      = this.addZero(vDate.getDate()); 
 var vMonth      = this.addZero(vDate.getMonth() + 1); 
 var vYearLong    = this.addZero(vDate.getFullYear()); 
 var vYearShort    = this.addZero(vDate.getFullYear().toString().substring(3,4)); 
 var vYear      = (vFormat.indexOf("yyyy") > -1 ? vYearLong : vYearShort);
 var vHour      = this.addZero(vDate.getHours()); 
 var vMinute      = this.addZero(vDate.getMinutes()); 
 var vSecond      = this.addZero(vDate.getSeconds()); 
 return vFormat.replace(/dd/g, vDay).replace(/mm/g, vMonth).replace(/y{1,4}/g, vYear).replace(/hh/g, vHour).replace(/nn/g, vMinute).replace(/ss/g, vSecond);

}; //----------------------------------------------------------------------------- Epoch.prototype.updatePos = function (target) //PUBLIC: moves the calendar"s position to target"s location (popup mode only) {

 this.calendar.style.top = this.getTop(target) + this.topOffset + "px"
 this.calendar.style.left = this.getLeft(target) + this.leftOffset + "px"

} //----------------------------------------------------------------------------- /*****************************************************************************/ function CalHeading(owner,tableCell,dow) {

 this.owner = owner;
 this.tableCell = tableCell;
 this.dayOfWeek = dow;
 
 //the event handlers
 this.tableCell.onclick = this.onclick;

} //----------------------------------------------------------------------------- CalHeading.prototype.onclick = function () {

 //reduce indirection:
 var owner = this.headObj.owner;
 var sdates = owner.selectedDates;
 var cells = owner.cells;
 
 owner.cols[this.headObj.dayOfWeek] = !owner.cols[this.headObj.dayOfWeek];
 for(var i=0;i<cells.length;i++) //cycle through all the cells in the calendar, selecting all cells with the same dayOfWeek as this heading
 {
   if(cells[i].dayOfWeek == this.headObj.dayOfWeek && (!owner.selCurMonthOnly || cells[i].date.getMonth() == owner.displayMonth && cells[i].date.getFullYear() == owner.displayYear)) //if the cell"s DoW matches, with other conditions
   {
     if(owner.cols[this.headObj.dayOfWeek])     //if selecting, add the cell"s date to the selectedDates array
     {
       if(owner.selectedDates.arrayIndex(cells[i].date) == -1) { //if the date isn"t already in the array
         sdates.push(cells[i].date);
       }
     }
     else                    //otherwise, remove it
     {
       for(var j=0;j<sdates.length;j++) 
       {
         if(cells[i].dayOfWeek == sdates[j].getDay())
         {
           sdates.splice(j,1);  //remove dates that are within the displaying month/year that have the same day of week as the day cell
           break;
         }
       }
     }
     cells[i].selected = owner.cols[this.headObj.dayOfWeek];
   }
 }
 owner.reDraw();

}; /*****************************************************************************/ function WeekHeading(owner,tableCell,week,row) {

 this.owner = owner;
 this.tableCell = tableCell;
 this.week = week;
 this.tableRow = row;
 this.tableCell.setAttribute("class","wkhead");
 this.tableCell.setAttribute("className","wkhead"); //<iehack>
 //the event handlers
 this.tableCell.onclick = this.onclick;

} //----------------------------------------------------------------------------- WeekHeading.prototype.onclick = function () {

 //reduce indirection:
 var owner = this.weekObj.owner;
 var cells = owner.cells;
 var sdates = owner.selectedDates;
 var i,j;
 owner.rows[this.weekObj.tableRow] = !owner.rows[this.weekObj.tableRow];
 for(i=0;i<cells.length;i++)
 {
   if(cells[i].tableRow == this.weekObj.tableRow)
   {
     if(owner.rows[this.weekObj.tableRow] && (!owner.selCurMonthOnly || cells[i].date.getMonth() == owner.displayMonth && cells[i].date.getFullYear() == owner.displayYear)) //match all cells in the current row, with option to restrict to current month only
     {
       if(owner.selectedDates.arrayIndex(cells[i].date) == -1) {//if the date isn"t already in the array
         sdates.push(cells[i].date);
       }
     }
     else                    //otherwise, remove it
     {
       for(j=0;j<sdates.length;j++)
       {
         if(sdates[j].getTime() == cells[i].date.getTime())  //this.weekObj.tableRow && sdates[j].getMonth() == owner.displayMonth && sdates[j].getFullYear() == owner.displayYear)
         {
           sdates.splice(j,1);  //remove dates that are within the displaying month/year that have the same day of week as the day cell
           break;
         }
       }
     }
   }
 }
 owner.reDraw();

}; /*****************************************************************************/ //----------------------------------------------------------------------------- function CalCell(owner,tableCell,dateObj,row) {

 this.owner = owner;    //used primarily for event handling
 this.tableCell = tableCell;       //the link to this cell object"s table cell in the DOM
 this.cellClass;      //the CSS class of the cell
 this.selected = false;  //whether the cell is selected (and is therefore stored in the owner"s selectedDates array)
 this.date = new Date(dateObj);
 this.dayOfWeek = this.date.getDay();
 this.week = this.date.getWeek();
 this.tableRow = row;
 
 //assign the event handlers for the table cell element
 this.tableCell.onclick = this.onclick;
 this.tableCell.onmouseover = this.onmouseover;
 this.tableCell.onmouseout = this.onmouseout;
 
 //and set the CSS class of the table cell
 this.setClass();

} //----------------------------------------------------------------------------- CalCell.prototype.onmouseover = function () //replicate CSS :hover effect for non-supporting browsers <iehack> {

 this.setAttribute("class",this.cellClass + " hover");
 this.setAttribute("className",this.cellClass + " hover");

}; //----------------------------------------------------------------------------- CalCell.prototype.onmouseout = function () //replicate CSS :hover effect for non-supporting browsers <iehack> {

 this.cellObj.setClass();

}; //----------------------------------------------------------------------------- CalCell.prototype.onclick = function () {

 //reduce indirection:
 var cell = this.cellObj;
 var owner = cell.owner;
 if(!owner.selCurMonthOnly || cell.date.getMonth() == owner.displayMonth && cell.date.getFullYear() == owner.displayYear)
 {
   if(owner.selectMultiple == true)  //if we can select multiple cells simultaneously, add the currently selected cell"s date to the selectedDates array
   {
     if(!cell.selected) //if this cell has been selected
     {
       if(owner.selectedDates.arrayIndex(cell.date) == -1) {
         owner.selectedDates.push(cell.date);
       }
     }
     else    
     {
       var tmp = owner.selectedDates; // to reduce indirection
       //if the cell has been deselected, remove it from the owner calendar"s selectedDates array
       for(var i=0;i<tmp.length;i++)
       {
         if(tmp[i].getUeDay() == cell.date.getUeDay()) {
           tmp.splice(i,1);
         }
       }
     }
   }
   else //if we can only select one cell at a time
   {
     owner.selectedDates = new Array(cell.date);
     if(owner.tgt) //if there is a target element to place the value in, do so
     {
       owner.tgt.value = owner.selectedDates[0].dateFormat();
       if(owner.mode == "popup") {
         owner.hide();
       }
     }
   }
   owner.reDraw(); //redraw the calendar cell styles to reflect the changes
 }

}; //----------------------------------------------------------------------------- CalCell.prototype.setClass = function () //private: sets the CSS class of the cell based on the specified criteria {

 if(this.selected) {
   this.cellClass = "cell_selected";
 }
 else if(this.owner.displayMonth != this.date.getMonth() ) {
   this.cellClass = "notmnth";  
 }
 else if(this.date.getDay() > 0 && this.date.getDay() < 6) {
   this.cellClass = "wkday";
 }
 else {
   this.cellClass = "wkend";
 }
 
 if(this.date.getFullYear() == this.owner.curDate.getFullYear() && this.date.getMonth() == this.owner.curDate.getMonth() && this.date.getDate() == this.owner.curDate.getDate()) {
   this.cellClass = this.cellClass + " curdate";
 }
 this.tableCell.setAttribute("class",this.cellClass);
 this.tableCell.setAttribute("className",this.cellClass); //<iehack>

}; /*****************************************************************************/ Date.prototype.getDayOfYear = function () //returns the day of the year for this date {

 return parseInt((this.getTime() - new Date(this.getFullYear(),0,1).getTime())/86400000 + 1);

}; //----------------------------------------------------------------------------- Date.prototype.getWeek = function () //returns the day of the year for this date {

 return parseInt((this.getTime() - new Date(this.getFullYear(),0,1).getTime())/604800000 + 1);

}; /*function getISOWeek() {

 var newYear = new Date(this.getFullYear(),0,1);
 var modDay = newYear.getDay();
 if (modDay == 0) modDay=6; else modDay--;
 
 var daynum = ((Date.UTC(this.getFullYear(),this.getMonth(),this.getDate(),0,0,0) - Date.UTC(this.getFullYear()),0,1,0,0,0)) /1000/60/60/24) + 1;
 
 if (modDay < 4 ) {
     var weeknum = Math.floor((daynum+modDay-1)/7)+1;
 }
 else {
     var weeknum = Math.floor((daynum+modDay-1)/7);
     if (weeknum == 0) {
         year--;
         var prevNewYear = new Date(this.getFullYear(),0,1);
         var prevmodDay = prevNewYear.getDay();
         if (prevmodDay == 0) prevmodDay = 6; else prevmodDay--;
         if (prevmodDay < 4) weeknum = 53; else weeknum = 52;
     }
 }
 
 return + weeknum;

}*/ //----------------------------------------------------------------------------- Date.prototype.getUeDay = function () //returns the number of DAYS since the UNIX Epoch - good for comparing the date portion {

 return parseInt(Math.floor((this.getTime() - this.getTimezoneOffset() * 60000)/86400000)); //must take into account the local timezone

}; //----------------------------------------------------------------------------- Date.prototype.dateFormat = function(format) {

 if(!format) { // the default date format to use - can be customized to the current locale
   format = "m/d/Y";
 }
 LZ = function(x) {return(x < 0 || x > 9 ? "" : "0") + x};
 var MONTH_NAMES = new Array("January","February","March","April","May","June","July","August","September","October","November","December","Jan","Feb","Mar","Apr","May","Jun","Jul","Aug","Sep","Oct","Nov","Dec");
 var DAY_NAMES = new Array("Sunday","Monday","Tuesday","Wednesday","Thursday","Friday","Saturday","Sun","Mon","Tue","Wed","Thu","Fri","Sat");
 format = format + "";
 var result="";
 var i_format=0;
 var c="";
 var token="";
 var y=this.getFullYear().toString();
 var M=this.getMonth()+1;
 var d=this.getDate();
 var E=this.getDay();
 var H=this.getHours();
 var m=this.getMinutes();
 var s=this.getSeconds();
 var yyyy,yy,MMM,MM,dd,hh,h,mm,ss,ampm,HH,H,KK,K,kk,k;
 // Convert real this parts into formatted versions
 var value = new Object();
 //if (y.length < 4) {y=""+(y-0+1900);}
 value["Y"] = y.toString();
 value["y"] = y.substring(2);
 value["n"] = M;
 value["m"] = LZ(M);
 value["F"] = MONTH_NAMES[M-1];
 value["M"] = MONTH_NAMES[M+11];
 value["j"] = d;
 value["d"] = LZ(d);
 value["D"] = DAY_NAMES[E+7];
 value["l"] = DAY_NAMES[E];
 value["G"] = H;
 value["H"] = LZ(H);
 if (H==0) {value["g"]=12;}
 else if (H>12){value["g"]=H-12;}
 else {value["g"]=H;}
 value["h"]=LZ(value["g"]);
 if (H > 11) {value["a"]="pm"; value["A"] = "PM";}
 else { value["a"]="am"; value["A"] = "AM";}
 value["i"]=LZ(m);
 value["s"]=LZ(s);
 //construct the result string
 while (i_format < format.length) {
   c=format.charAt(i_format);
   token="";
   while ((format.charAt(i_format)==c) && (i_format < format.length)) {
     token += format.charAt(i_format++);
     }
   if (value[token] != null) { result=result + value[token]; }
   else { result=result + token; }
   }
 return result;

}; /*****************************************************************************/ Array.prototype.arrayIndex = function(searchVal,startIndex) //similar to array.indexOf() - created to fix IE deficiencies {

 startIndex = (startIndex != null ? startIndex : 0); //default startIndex to 0, if not set
 for(var i=startIndex;i<this.length;i++)
 {
   if(searchVal == this[i]) {
     return i;
   }
 }
 return -1;

}; /*****************************************************************************/ </script> <script type="text/javascript"> /*You can also place this code in a separate file and link to it like epoch_classes.js*/

 var bas_cal,dp_cal,ms_cal;      

window.onload = function () {

 dp_cal  = new Epoch("epoch_popup","popup",document.getElementById("popup_container"));

}; </script> </head> <body>

Popup

<form id="placeholder" method="get" action="#">

 <input id="popup_container" type="text" />

</form> </body> </html>


 </source>
   
  


swazz calendar 1.0

<A href="http://www.wbex.ru/Code/JavaScriptDownload/swazzcalendar1.0.zip">swazzcalendar1.0.zip( 4 k)</a>

1. <A href="/Code/JavaScript/GUI-Components/HTMLCalendarbasedonDynAPI.htm">HTML Calendar based on DynAPI</a> <A href="/Code/JavaScript/GUI-Components/HTMLCalendarbasedonDynAPI.htm"></a> 2. <A href="/Code/JavaScript/GUI-Components/JavaScriptDatePickerbasedonComboBox.htm">JavaScript Date Picker based on ComboBox</a> <A href="/Code/JavaScript/GUI-Components/JavaScriptDatePickerbasedonComboBox.htm"></a> 3. <A href="/Code/JavaScript/GUI-Components/CalendarControlSingleSelectImplementation.htm">Calendar Control - Single-Select Implementation</a> <A href="/Code/JavaScript/GUI-Components/CalendarControlSingleSelectImplementation.htm"></a> 4. <A href="/Code/JavaScript/GUI-Components/CalendarControl2UpImplementation.htm">Calendar Control - 2-Up Implementation</a> <A href="/Code/JavaScript/GUI-Components/CalendarControl2UpImplementation.htm"></a> 5. <A href="/Code/JavaScript/GUI-Components/CalendarControlHandlingonSelectonDeselect.htm">Calendar Control - Handling onSelect / onDeselect</a> <A href="/Code/JavaScript/GUI-Components/CalendarControlHandlingonSelectonDeselect.htm"></a> 6. <A href="/Code/JavaScript/GUI-Components/CalendarControlMixMaxImplementation.htm">Calendar Control - Mix/Max Implementation</a> <A href="/Code/JavaScript/GUI-Components/CalendarControlMixMaxImplementation.htm"></a> 7. <A href="/Code/JavaScript/GUI-Components/CalendarControlMultiSelectImplementation.htm">Calendar Control - Multi-Select Implementation</a> <A href="/Code/JavaScript/GUI-Components/CalendarControlMultiSelectImplementation.htm"></a> 8. <A href="/Code/JavaScript/GUI-Components/CalendarControlMultiSelect2upImplementation.htm">Calendar Control - Multi-Select 2-up Implementation</a> <A href="/Code/JavaScript/GUI-Components/CalendarControlMultiSelect2upImplementation.htm"></a> 9. <A href="/Code/JavaScript/GUI-Components/CalendarControlCustomRendererExampleHolidayRendererImplementation.htm">Calendar Control - Custom Renderer Example (Holiday Renderer Implementation)</a> <A href="/Code/JavaScript/GUI-Components/CalendarControlCustomRendererExampleHolidayRendererImplementation.htm"></a> 10. <A href="/Code/JavaScript/GUI-Components/CalendarControlDateRestrictionExampleDateRestrictionImplementation.htm">Calendar Control - Date Restriction Example (Date Restriction Implementation)</a> <A href="/Code/JavaScript/GUI-Components/CalendarControlDateRestrictionExampleDateRestrictionImplementation.htm"></a> 11. <A href="/Code/JavaScript/GUI-Components/CalendarControlRowHighlightExampleRowHighlightImplementation.htm">Calendar Control - Row Highlight Example (Row Highlight Implementation)</a> <A href="/Code/JavaScript/GUI-Components/CalendarControlRowHighlightExampleRowHighlightImplementation.htm"></a> 12. <A href="/Code/JavaScript/GUI-Components/Popupcalendar.htm">Popup calendar</a> <A href="/Code/JavaScript/GUI-Components/Popupcalendar.htm"></a> 13. <A href="/Code/JavaScript/GUI-Components/MonthCalendar.htm">Month Calendar</a> 14. <A href="/Code/JavaScript/GUI-Components/PopupCalendarforatextfield.htm">Popup Calendar for a textfield</a> 15. <A href="/Code/JavaScript/GUI-Components/MultiselectionCalendar.htm">Multiselection Calendar</a> 16. <A href="/Code/JavaScript/GUI-Components/FreeDatePickerAneasyplugintoaddadatepickercalendarinyourwebsite.htm">Free Date Picker : An easy plugin to add a date picker (calendar) in your web site</a> 17. <A href="/Code/JavaScript/GUI-Components/HTMLDatePicker.htm">HTML Date Picker</a> 18. <A href="/Code/JavaScript/GUI-Components/DatePickerinnewwindow.htm">Date Picker in new window</a> <A href="/Code/JavaScript/GUI-Components/DatePickerinnewwindow.htm"></a> 19. <A href="/Code/JavaScript/GUI-Components/AllbrowserCalendar.htm">All browser Calendar</a> <A href="/Code/JavaScript/GUI-Components/AllbrowserCalendar.htm"></a> 20. <A href="/Code/JavaScript/GUI-Components/DHTMLCalendarfortheimpatient.htm">DHTML Calendar for the impatient</a> <A href="/Code/JavaScript/GUI-Components/DHTMLCalendarfortheimpatient.htm"></a> 21. <A href="/Code/JavaScript/GUI-Components/Calendarspecialday.htm">Calendar: special day</a> <A href="/Code/JavaScript/GUI-Components/Calendarspecialday.htm"></a> 22. <A href="/Code/JavaScript/GUI-Components/Calendardayinfo.htm">Calendar: day info</a> <A href="/Code/JavaScript/GUI-Components/Calendardayinfo.htm"></a> 23. <A href="/Code/JavaScript/GUI-Components/CalendarMultipledayselection.htm">Calendar: Multiple day selection</a> <A href="/Code/JavaScript/GUI-Components/CalendarMultipledayselection.htm"></a> 24. <A href="/Code/JavaScript/GUI-Components/Calendarwithdifferenttheme.htm">Calendar with different theme</a> <A href="/Code/JavaScript/GUI-Components/Calendarwithdifferenttheme.htm"></a> 25. <A href="/Code/JavaScript/GUI-Components/Calendarwithimageforeachmonth.htm">Calendar with image for each month</a> <A href="/Code/JavaScript/GUI-Components/Calendarwithimageforeachmonth.htm"></a> 26. <A href="/Code/JavaScript/GUI-Components/FancyCalendar.htm">Fancy Calendar </a> <A href="/Code/JavaScript/GUI-Components/FancyCalendar.htm"></a> 27. <A href="/Code/JavaScript/GUI-Components/AnotherCalendar.htm">Another Calendar </a> <A href="/Code/JavaScript/GUI-Components/AnotherCalendar.htm"></a> 28. <A href="/Code/JavaScript/GUI-Components/DateTimePicker.htm">Date Time Picker</a> <A href="/Code/JavaScript/GUI-Components/DateTimePicker.htm"></a> 29. <A href="/Code/JavaScript/GUI-Components/MonthCalendar2.htm">Month Calendar (2)</a> 30. <A href="/Code/JavaScript/GUI-Components/BuildingaCalculator.htm">Building a Calculator</a> 31. <A href="/Code/JavaScript/GUI-Components/ADynamicCalendarTable.htm">A Dynamic Calendar Table</a> 32. <A href="/Code/JavaScript/GUI-Components/DynamicHTMLCalendar.htm">Dynamic HTML Calendar</a> 33. <A href="/Code/JavaScript/GUI-Components/AStaticCalendarbyJavaScript.htm"> A Static Calendar by JavaScript</a> 34. <A href="/Code/JavaScript/GUI-Components/DisplayingtheCalendar.htm">Displaying the Calendar</a> 35. <A href="/Code/JavaScript/GUI-Components/CalendarIEonly.htm">Calendar (IE only)</a> 36. <A href="/Code/JavaScript/GUI-Components/Calendarinslidetab.htm">Calendar in slide tab</a> 37. <A href="/Code/JavaScript/GUI-Components/AnotherDHTMLCalendar.htm">Another DHTML Calendar</a> 38. <A href="/Code/JavaScript/GUI-Components/EventCalendar.htm">Event Calendar</a> <A href="/Code/JavaScript/GUI-Components/EventCalendar.htm"></a> 39. <A href="/Code/JavaScript/GUI-Components/Opencalendar.htm">Open calendar</a> <A href="/Code/JavaScript/GUI-Components/Opencalendar.htm"></a> 40. <A href="/Code/JavaScript/GUI-Components/jquerycalendar.htm">jquery calendar</a>

<A href="/Code/JavaScript/GUI-Components/jquerycalendar.htm"></a>