(file) Return to calendar.js CVS log (file) (dir) Up to [RizwankCVS] / geekymedia_web / twiki / pub / TWiki / EditTablePlugin

   1 rizwank 1.1 /*  Copyright Mihai Bazon, 2002, 2003  |  http://dynarch.com/mishoo/
   2              * ------------------------------------------------------------------
   3              *
   4              * The DHTML Calendar, version 0.9.5 "Your favorite time, bis"
   5              *
   6              * Details and latest version at:
   7              * http://dynarch.com/mishoo/calendar.epl
   8              *
   9              * This script is distributed under the GNU Lesser General Public License.
  10              * Read the entire license text here: http://www.gnu.org/licenses/lgpl.html
  11              */
  12             
  13             // $Id: calendar.js,v 1.22 2003/11/05 17:30:12 mishoo Exp $
  14             
  15             /** The Calendar object constructor. */
  16             Calendar = function (mondayFirst, dateStr, onSelected, onClose) {
  17             	// member variables
  18             	this.activeDiv = null;
  19             	this.currentDateEl = null;
  20             	this.getDateStatus = null;
  21             	this.timeout = null;
  22 rizwank 1.1 	this.onSelected = onSelected || null;
  23             	this.onClose = onClose || null;
  24             	this.dragging = false;
  25             	this.hidden = false;
  26             	this.minYear = 1970;
  27             	this.maxYear = 2050;
  28             	this.dateFormat = Calendar._TT["DEF_DATE_FORMAT"];
  29             	this.ttDateFormat = Calendar._TT["TT_DATE_FORMAT"];
  30             	this.isPopup = true;
  31             	this.weekNumbers = true;
  32             	this.mondayFirst = mondayFirst;
  33             	this.dateStr = dateStr;
  34             	this.ar_days = null;
  35             	this.showsTime = false;
  36             	this.time24 = true;
  37             	// HTML elements
  38             	this.table = null;
  39             	this.element = null;
  40             	this.tbody = null;
  41             	this.firstdayname = null;
  42             	// Combo boxes
  43 rizwank 1.1 	this.monthsCombo = null;
  44             	this.yearsCombo = null;
  45             	this.hilitedMonth = null;
  46             	this.activeMonth = null;
  47             	this.hilitedYear = null;
  48             	this.activeYear = null;
  49             	// Information
  50             	this.dateClicked = false;
  51             
  52             	// one-time initializations
  53             	if (typeof Calendar._SDN == "undefined") {
  54             		// table of short day names
  55             		if (typeof Calendar._SDN_len == "undefined")
  56             			Calendar._SDN_len = 3;
  57             		var ar = new Array();
  58             		for (var i = 8; i > 0;) {
  59             			ar[--i] = Calendar._DN[i].substr(0, Calendar._SDN_len);
  60             		}
  61             		Calendar._SDN = ar;
  62             		// table of short month names
  63             		if (typeof Calendar._SMN_len == "undefined")
  64 rizwank 1.1 			Calendar._SMN_len = 3;
  65             		ar = new Array();
  66             		for (var i = 12; i > 0;) {
  67             			ar[--i] = Calendar._MN[i].substr(0, Calendar._SMN_len);
  68             		}
  69             		Calendar._SMN = ar;
  70             	}
  71             };
  72             
  73             // ** constants
  74             
  75             /// "static", needed for event handlers.
  76             Calendar._C = null;
  77             
  78             /// detect a special case of "web browser"
  79             Calendar.is_ie = ( /msie/i.test(navigator.userAgent) &&
  80             		   !/opera/i.test(navigator.userAgent) );
  81             
  82             /// detect Opera browser
  83             Calendar.is_opera = /opera/i.test(navigator.userAgent);
  84             
  85 rizwank 1.1 /// detect KHTML-based browsers
  86             Calendar.is_khtml = /Konqueror|Safari|KHTML/i.test(navigator.userAgent);
  87             
  88             // BEGIN: UTILITY FUNCTIONS; beware that these might be moved into a separate
  89             //        library, at some point.
  90             
  91             Calendar.getAbsolutePos = function(el) {
  92             	var SL = 0, ST = 0;
  93             	var is_div = /^div$/i.test(el.tagName);
  94             	if (is_div && el.scrollLeft)
  95             		SL = el.scrollLeft;
  96             	if (is_div && el.scrollTop)
  97             		ST = el.scrollTop;
  98             	var r = { x: el.offsetLeft - SL, y: el.offsetTop - ST };
  99             	if (el.offsetParent) {
 100             		var tmp = Calendar.getAbsolutePos(el.offsetParent);
 101             		r.x += tmp.x;
 102             		r.y += tmp.y;
 103             	}
 104             	return r;
 105             };
 106 rizwank 1.1 
 107             Calendar.isRelated = function (el, evt) {
 108             	var related = evt.relatedTarget;
 109             	if (!related) {
 110             		var type = evt.type;
 111             		if (type == "mouseover") {
 112             			related = evt.fromElement;
 113             		} else if (type == "mouseout") {
 114             			related = evt.toElement;
 115             		}
 116             	}
 117             	while (related) {
 118             		if (related == el) {
 119             			return true;
 120             		}
 121             		related = related.parentNode;
 122             	}
 123             	return false;
 124             };
 125             
 126             Calendar.removeClass = function(el, className) {
 127 rizwank 1.1 	if (!(el && el.className)) {
 128             		return;
 129             	}
 130             	var cls = el.className.split(" ");
 131             	var ar = new Array();
 132             	for (var i = cls.length; i > 0;) {
 133             		if (cls[--i] != className) {
 134             			ar[ar.length] = cls[i];
 135             		}
 136             	}
 137             	el.className = ar.join(" ");
 138             };
 139             
 140             Calendar.addClass = function(el, className) {
 141             	Calendar.removeClass(el, className);
 142             	el.className += " " + className;
 143             };
 144             
 145             Calendar.getElement = function(ev) {
 146             	if (Calendar.is_ie) {
 147             		return window.event.srcElement;
 148 rizwank 1.1 	} else {
 149             		return ev.currentTarget;
 150             	}
 151             };
 152             
 153             Calendar.getTargetElement = function(ev) {
 154             	if (Calendar.is_ie) {
 155             		return window.event.srcElement;
 156             	} else {
 157             		return ev.target;
 158             	}
 159             };
 160             
 161             Calendar.stopEvent = function(ev) {
 162             	ev || (ev = window.event);
 163             	if (Calendar.is_ie) {
 164             		ev.cancelBubble = true;
 165             		ev.returnValue = false;
 166             	} else {
 167             		ev.preventDefault();
 168             		ev.stopPropagation();
 169 rizwank 1.1 	}
 170             	return false;
 171             };
 172             
 173             Calendar.addEvent = function(el, evname, func) {
 174             	if (el.attachEvent) { // IE
 175             		el.attachEvent("on" + evname, func);
 176             	} else if (el.addEventListener) { // Gecko / W3C
 177             		el.addEventListener(evname, func, true);
 178             	} else {
 179             		el["on" + evname] = func;
 180             	}
 181             };
 182             
 183             Calendar.removeEvent = function(el, evname, func) {
 184             	if (el.detachEvent) { // IE
 185             		el.detachEvent("on" + evname, func);
 186             	} else if (el.removeEventListener) { // Gecko / W3C
 187             		el.removeEventListener(evname, func, true);
 188             	} else {
 189             		el["on" + evname] = null;
 190 rizwank 1.1 	}
 191             };
 192             
 193             Calendar.createElement = function(type, parent) {
 194             	var el = null;
 195             	if (document.createElementNS) {
 196             		// use the XHTML namespace; IE won't normally get here unless
 197             		// _they_ "fix" the DOM2 implementation.
 198             		el = document.createElementNS("http://www.w3.org/1999/xhtml", type);
 199             	} else {
 200             		el = document.createElement(type);
 201             	}
 202             	if (typeof parent != "undefined") {
 203             		parent.appendChild(el);
 204             	}
 205             	return el;
 206             };
 207             
 208             // END: UTILITY FUNCTIONS
 209             
 210             // BEGIN: CALENDAR STATIC FUNCTIONS
 211 rizwank 1.1 
 212             /** Internal -- adds a set of events to make some element behave like a button. */
 213             Calendar._add_evs = function(el) {
 214             	with (Calendar) {
 215             		addEvent(el, "mouseover", dayMouseOver);
 216             		addEvent(el, "mousedown", dayMouseDown);
 217             		addEvent(el, "mouseout", dayMouseOut);
 218             		if (is_ie) {
 219             			addEvent(el, "dblclick", dayMouseDblClick);
 220             			el.setAttribute("unselectable", true);
 221             		}
 222             	}
 223             };
 224             
 225             Calendar.findMonth = function(el) {
 226             	if (typeof el.month != "undefined") {
 227             		return el;
 228             	} else if (typeof el.parentNode.month != "undefined") {
 229             		return el.parentNode;
 230             	}
 231             	return null;
 232 rizwank 1.1 };
 233             
 234             Calendar.findYear = function(el) {
 235             	if (typeof el.year != "undefined") {
 236             		return el;
 237             	} else if (typeof el.parentNode.year != "undefined") {
 238             		return el.parentNode;
 239             	}
 240             	return null;
 241             };
 242             
 243             Calendar.showMonthsCombo = function () {
 244             	var cal = Calendar._C;
 245             	if (!cal) {
 246             		return false;
 247             	}
 248             	var cal = cal;
 249             	var cd = cal.activeDiv;
 250             	var mc = cal.monthsCombo;
 251             	if (cal.hilitedMonth) {
 252             		Calendar.removeClass(cal.hilitedMonth, "hilite");
 253 rizwank 1.1 	}
 254             	if (cal.activeMonth) {
 255             		Calendar.removeClass(cal.activeMonth, "active");
 256             	}
 257             	var mon = cal.monthsCombo.getElementsByTagName("div")[cal.date.getMonth()];
 258             	Calendar.addClass(mon, "active");
 259             	cal.activeMonth = mon;
 260             	var s = mc.style;
 261             	s.display = "block";
 262             	if (cd.navtype < 0)
 263             		s.left = cd.offsetLeft + "px";
 264             	else
 265             		s.left = (cd.offsetLeft + cd.offsetWidth - mc.offsetWidth) + "px";
 266             	s.top = (cd.offsetTop + cd.offsetHeight) + "px";
 267             };
 268             
 269             Calendar.showYearsCombo = function (fwd) {
 270             	var cal = Calendar._C;
 271             	if (!cal) {
 272             		return false;
 273             	}
 274 rizwank 1.1 	var cal = cal;
 275             	var cd = cal.activeDiv;
 276             	var yc = cal.yearsCombo;
 277             	if (cal.hilitedYear) {
 278             		Calendar.removeClass(cal.hilitedYear, "hilite");
 279             	}
 280             	if (cal.activeYear) {
 281             		Calendar.removeClass(cal.activeYear, "active");
 282             	}
 283             	cal.activeYear = null;
 284             	var Y = cal.date.getFullYear() + (fwd ? 1 : -1);
 285             	var yr = yc.firstChild;
 286             	var show = false;
 287             	for (var i = 12; i > 0; --i) {
 288             		if (Y >= cal.minYear && Y <= cal.maxYear) {
 289             			yr.firstChild.data = Y;
 290             			yr.year = Y;
 291             			yr.style.display = "block";
 292             			show = true;
 293             		} else {
 294             			yr.style.display = "none";
 295 rizwank 1.1 		}
 296             		yr = yr.nextSibling;
 297             		Y += fwd ? 2 : -2;
 298             	}
 299             	if (show) {
 300             		var s = yc.style;
 301             		s.display = "block";
 302             		if (cd.navtype < 0)
 303             			s.left = cd.offsetLeft + "px";
 304             		else
 305             			s.left = (cd.offsetLeft + cd.offsetWidth - yc.offsetWidth) + "px";
 306             		s.top = (cd.offsetTop + cd.offsetHeight) + "px";
 307             	}
 308             };
 309             
 310             // event handlers
 311             
 312             Calendar.tableMouseUp = function(ev) {
 313             	var cal = Calendar._C;
 314             	if (!cal) {
 315             		return false;
 316 rizwank 1.1 	}
 317             	if (cal.timeout) {
 318             		clearTimeout(cal.timeout);
 319             	}
 320             	var el = cal.activeDiv;
 321             	if (!el) {
 322             		return false;
 323             	}
 324             	var target = Calendar.getTargetElement(ev);
 325             	ev || (ev = window.event);
 326             	Calendar.removeClass(el, "active");
 327             	if (target == el || target.parentNode == el) {
 328             		Calendar.cellClick(el, ev);
 329             	}
 330             	var mon = Calendar.findMonth(target);
 331             	var date = null;
 332             	if (mon) {
 333             		date = new Date(cal.date);
 334             		if (mon.month != date.getMonth()) {
 335             			date.setMonth(mon.month);
 336             			cal.setDate(date);
 337 rizwank 1.1 			cal.dateClicked = false;
 338             			cal.callHandler();
 339             		}
 340             	} else {
 341             		var year = Calendar.findYear(target);
 342             		if (year) {
 343             			date = new Date(cal.date);
 344             			if (year.year != date.getFullYear()) {
 345             				date.setFullYear(year.year);
 346             				cal.setDate(date);
 347             				cal.dateClicked = false;
 348             				cal.callHandler();
 349             			}
 350             		}
 351             	}
 352             	with (Calendar) {
 353             		removeEvent(document, "mouseup", tableMouseUp);
 354             		removeEvent(document, "mouseover", tableMouseOver);
 355             		removeEvent(document, "mousemove", tableMouseOver);
 356             		cal._hideCombos();
 357             		_C = null;
 358 rizwank 1.1 		return stopEvent(ev);
 359             	}
 360             };
 361             
 362             Calendar.tableMouseOver = function (ev) {
 363             	var cal = Calendar._C;
 364             	if (!cal) {
 365             		return;
 366             	}
 367             	var el = cal.activeDiv;
 368             	var target = Calendar.getTargetElement(ev);
 369             	if (target == el || target.parentNode == el) {
 370             		Calendar.addClass(el, "hilite active");
 371             		Calendar.addClass(el.parentNode, "rowhilite");
 372             	} else {
 373             		if (typeof el.navtype == "undefined" || (el.navtype != 50 && (el.navtype == 0 || Math.abs(el.navtype) > 2)))
 374             			Calendar.removeClass(el, "active");
 375             		Calendar.removeClass(el, "hilite");
 376             		Calendar.removeClass(el.parentNode, "rowhilite");
 377             	}
 378             	ev || (ev = window.event);
 379 rizwank 1.1 	if (el.navtype == 50 && target != el) {
 380             		var pos = Calendar.getAbsolutePos(el);
 381             		var w = el.offsetWidth;
 382             		var x = ev.clientX;
 383             		var dx;
 384             		var decrease = true;
 385             		if (x > pos.x + w) {
 386             			dx = x - pos.x - w;
 387             			decrease = false;
 388             		} else
 389             			dx = pos.x - x;
 390             
 391             		if (dx < 0) dx = 0;
 392             		var range = el._range;
 393             		var current = el._current;
 394             		var count = Math.floor(dx / 10) % range.length;
 395             		for (var i = range.length; --i >= 0;)
 396             			if (range[i] == current)
 397             				break;
 398             		while (count-- > 0)
 399             			if (decrease) {
 400 rizwank 1.1 				if (!(--i in range))
 401             					i = range.length - 1;
 402             			} else if (!(++i in range))
 403             				i = 0;
 404             		var newval = range[i];
 405             		el.firstChild.data = newval;
 406             
 407             		cal.onUpdateTime();
 408             	}
 409             	var mon = Calendar.findMonth(target);
 410             	if (mon) {
 411             		if (mon.month != cal.date.getMonth()) {
 412             			if (cal.hilitedMonth) {
 413             				Calendar.removeClass(cal.hilitedMonth, "hilite");
 414             			}
 415             			Calendar.addClass(mon, "hilite");
 416             			cal.hilitedMonth = mon;
 417             		} else if (cal.hilitedMonth) {
 418             			Calendar.removeClass(cal.hilitedMonth, "hilite");
 419             		}
 420             	} else {
 421 rizwank 1.1 		if (cal.hilitedMonth) {
 422             			Calendar.removeClass(cal.hilitedMonth, "hilite");
 423             		}
 424             		var year = Calendar.findYear(target);
 425             		if (year) {
 426             			if (year.year != cal.date.getFullYear()) {
 427             				if (cal.hilitedYear) {
 428             					Calendar.removeClass(cal.hilitedYear, "hilite");
 429             				}
 430             				Calendar.addClass(year, "hilite");
 431             				cal.hilitedYear = year;
 432             			} else if (cal.hilitedYear) {
 433             				Calendar.removeClass(cal.hilitedYear, "hilite");
 434             			}
 435             		} else if (cal.hilitedYear) {
 436             			Calendar.removeClass(cal.hilitedYear, "hilite");
 437             		}
 438             	}
 439             	return Calendar.stopEvent(ev);
 440             };
 441             
 442 rizwank 1.1 Calendar.tableMouseDown = function (ev) {
 443             	if (Calendar.getTargetElement(ev) == Calendar.getElement(ev)) {
 444             		return Calendar.stopEvent(ev);
 445             	}
 446             };
 447             
 448             Calendar.calDragIt = function (ev) {
 449             	var cal = Calendar._C;
 450             	if (!(cal && cal.dragging)) {
 451             		return false;
 452             	}
 453             	var posX;
 454             	var posY;
 455             	if (Calendar.is_ie) {
 456             		posY = window.event.clientY + document.body.scrollTop;
 457             		posX = window.event.clientX + document.body.scrollLeft;
 458             	} else {
 459             		posX = ev.pageX;
 460             		posY = ev.pageY;
 461             	}
 462             	cal.hideShowCovered();
 463 rizwank 1.1 	var st = cal.element.style;
 464             	st.left = (posX - cal.xOffs) + "px";
 465             	st.top = (posY - cal.yOffs) + "px";
 466             	return Calendar.stopEvent(ev);
 467             };
 468             
 469             Calendar.calDragEnd = function (ev) {
 470             	var cal = Calendar._C;
 471             	if (!cal) {
 472             		return false;
 473             	}
 474             	cal.dragging = false;
 475             	with (Calendar) {
 476             		removeEvent(document, "mousemove", calDragIt);
 477             		removeEvent(document, "mouseover", stopEvent);
 478             		removeEvent(document, "mouseup", calDragEnd);
 479             		tableMouseUp(ev);
 480             	}
 481             	cal.hideShowCovered();
 482             };
 483             
 484 rizwank 1.1 Calendar.dayMouseDown = function(ev) {
 485             	var el = Calendar.getElement(ev);
 486             	if (el.disabled) {
 487             		return false;
 488             	}
 489             	var cal = el.calendar;
 490             	cal.activeDiv = el;
 491             	Calendar._C = cal;
 492             	if (el.navtype != 300) with (Calendar) {
 493             		if (el.navtype == 50)
 494             			el._current = el.firstChild.data;
 495             		addClass(el, "hilite active");
 496             		addEvent(document, "mouseover", tableMouseOver);
 497             		addEvent(document, "mousemove", tableMouseOver);
 498             		addEvent(document, "mouseup", tableMouseUp);
 499             	} else if (cal.isPopup) {
 500             		cal._dragStart(ev);
 501             	}
 502             	if (el.navtype == -1 || el.navtype == 1) {
 503             		if (cal.timeout) clearTimeout(cal.timeout);
 504             		cal.timeout = setTimeout("Calendar.showMonthsCombo()", 250);
 505 rizwank 1.1 	} else if (el.navtype == -2 || el.navtype == 2) {
 506             		if (cal.timeout) clearTimeout(cal.timeout);
 507             		cal.timeout = setTimeout((el.navtype > 0) ? "Calendar.showYearsCombo(true)" : "Calendar.showYearsCombo(false)", 250);
 508             	} else {
 509             		cal.timeout = null;
 510             	}
 511             	return Calendar.stopEvent(ev);
 512             };
 513             
 514             Calendar.dayMouseDblClick = function(ev) {
 515             	Calendar.cellClick(Calendar.getElement(ev), ev || window.event);
 516             	if (Calendar.is_ie) {
 517             		document.selection.empty();
 518             	}
 519             };
 520             
 521             Calendar.dayMouseOver = function(ev) {
 522             	var el = Calendar.getElement(ev);
 523             	if (Calendar.isRelated(el, ev) || Calendar._C || el.disabled) {
 524             		return false;
 525             	}
 526 rizwank 1.1 	if (el.ttip) {
 527             		if (el.ttip.substr(0, 1) == "_") {
 528             			var date = null;
 529             			with (el.calendar.date) {
 530             				date = new Date(getFullYear(), getMonth(), el.caldate);
 531             			}
 532             			el.ttip = date.print(el.calendar.ttDateFormat) + el.ttip.substr(1);
 533             		}
 534             		el.calendar.tooltips.firstChild.data = el.ttip;
 535             	}
 536             	if (el.navtype != 300) {
 537             		Calendar.addClass(el, "hilite");
 538             		if (el.caldate) {
 539             			Calendar.addClass(el.parentNode, "rowhilite");
 540             		}
 541             	}
 542             	return Calendar.stopEvent(ev);
 543             };
 544             
 545             Calendar.dayMouseOut = function(ev) {
 546             	with (Calendar) {
 547 rizwank 1.1 		var el = getElement(ev);
 548             		if (isRelated(el, ev) || _C || el.disabled) {
 549             			return false;
 550             		}
 551             		removeClass(el, "hilite");
 552             		if (el.caldate) {
 553             			removeClass(el.parentNode, "rowhilite");
 554             		}
 555             		el.calendar.tooltips.firstChild.data = _TT["SEL_DATE"];
 556             		return stopEvent(ev);
 557             	}
 558             };
 559             
 560             /**
 561              *  A generic "click" handler :) handles all types of buttons defined in this
 562              *  calendar.
 563              */
 564             Calendar.cellClick = function(el, ev) {
 565             	var cal = el.calendar;
 566             	var closing = false;
 567             	var newdate = false;
 568 rizwank 1.1 	var date = null;
 569             	if (typeof el.navtype == "undefined") {
 570             		Calendar.removeClass(cal.currentDateEl, "selected");
 571             		Calendar.addClass(el, "selected");
 572             		closing = (cal.currentDateEl == el);
 573             		if (!closing) {
 574             			cal.currentDateEl = el;
 575             		}
 576             		cal.date.setDate(el.caldate);
 577             		date = cal.date;
 578             		newdate = true;
 579             		// a date was clicked
 580             		cal.dateClicked = true;
 581             	} else {
 582             		if (el.navtype == 200) {
 583             			Calendar.removeClass(el, "hilite");
 584             			cal.callCloseHandler();
 585             			return;
 586             		}
 587             		date = (el.navtype == 0) ? new Date() : new Date(cal.date);
 588             		// unless "today" was clicked, we assume no date was clicked so
 589 rizwank 1.1 		// the selected handler will know not to close the calenar when
 590             		// in single-click mode.
 591             		// cal.dateClicked = (el.navtype == 0);
 592             		cal.dateClicked = false;
 593             		var year = date.getFullYear();
 594             		var mon = date.getMonth();
 595             		function setMonth(m) {
 596             			var day = date.getDate();
 597             			var max = date.getMonthDays(m);
 598             			if (day > max) {
 599             				date.setDate(max);
 600             			}
 601             			date.setMonth(m);
 602             		};
 603             		switch (el.navtype) {
 604             		    case 400:
 605             			Calendar.removeClass(el, "hilite");
 606             			var text = Calendar._TT["ABOUT"];
 607             			if (typeof text != "undefined") {
 608             				text += cal.showsTime ? Calendar._TT["ABOUT_TIME"] : "";
 609             			} else {
 610 rizwank 1.1 				// FIXME: this should be removed as soon as lang files get updated!
 611             				text = "Help and about box text is not translated into this language.\n" +
 612             					"If you know this language and you feel generous please update\n" +
 613             					"the corresponding file in \"lang\" subdir to match calendar-en.js\n" +
 614             					"and send it back to <mishoo@infoiasi.ro> to get it into the distribution  ;-)\n\n" +
 615             					"Thank you!\n" +
 616             					"http://dynarch.com/mishoo/calendar.epl\n";
 617             			}
 618             			alert(text);
 619             			return;
 620             		    case -2:
 621             			if (year > cal.minYear) {
 622             				date.setFullYear(year - 1);
 623             			}
 624             			break;
 625             		    case -1:
 626             			if (mon > 0) {
 627             				setMonth(mon - 1);
 628             			} else if (year-- > cal.minYear) {
 629             				date.setFullYear(year);
 630             				setMonth(11);
 631 rizwank 1.1 			}
 632             			break;
 633             		    case 1:
 634             			if (mon < 11) {
 635             				setMonth(mon + 1);
 636             			} else if (year < cal.maxYear) {
 637             				date.setFullYear(year + 1);
 638             				setMonth(0);
 639             			}
 640             			break;
 641             		    case 2:
 642             			if (year < cal.maxYear) {
 643             				date.setFullYear(year + 1);
 644             			}
 645             			break;
 646             		    case 100:
 647             			cal.setMondayFirst(!cal.mondayFirst);
 648             			return;
 649             		    case 50:
 650             			var range = el._range;
 651             			var current = el.firstChild.data;
 652 rizwank 1.1 			for (var i = range.length; --i >= 0;)
 653             				if (range[i] == current)
 654             					break;
 655             			if (ev && ev.shiftKey) {
 656             				if (!(--i in range))
 657             					i = range.length - 1;
 658             			} else if (!(++i in range))
 659             				i = 0;
 660             			var newval = range[i];
 661             			el.firstChild.data = newval;
 662             			cal.onUpdateTime();
 663             			return;
 664             		    case 0:
 665             			// TODAY will bring us here
 666             			if ((typeof cal.getDateStatus == "function") && cal.getDateStatus(date, date.getFullYear(), date.getMonth(), date.getDate())) {
 667             				// remember, "date" was previously set to new
 668             				// Date() if TODAY was clicked; thus, it
 669             				// contains today date.
 670             				return false;
 671             			}
 672             			break;
 673 rizwank 1.1 		}
 674             		if (!date.equalsTo(cal.date)) {
 675             			cal.setDate(date);
 676             			newdate = true;
 677             		}
 678             	}
 679             	if (newdate) {
 680             		cal.callHandler();
 681             	}
 682             	if (closing) {
 683             		Calendar.removeClass(el, "hilite");
 684             		cal.callCloseHandler();
 685             	}
 686             };
 687             
 688             // END: CALENDAR STATIC FUNCTIONS
 689             
 690             // BEGIN: CALENDAR OBJECT FUNCTIONS
 691             
 692             /**
 693              *  This function creates the calendar inside the given parent.  If _par is
 694 rizwank 1.1  *  null than it creates a popup calendar inside the BODY element.  If _par is
 695              *  an element, be it BODY, then it creates a non-popup calendar (still
 696              *  hidden).  Some properties need to be set before calling this function.
 697              */
 698             Calendar.prototype.create = function (_par) {
 699             	var parent = null;
 700             	if (! _par) {
 701             		// default parent is the document body, in which case we create
 702             		// a popup calendar.
 703             		parent = document.getElementsByTagName("body")[0];
 704             		this.isPopup = true;
 705             	} else {
 706             		parent = _par;
 707             		this.isPopup = false;
 708             	}
 709             	this.date = this.dateStr ? new Date(this.dateStr) : new Date();
 710             
 711             	var table = Calendar.createElement("table");
 712             	this.table = table;
 713             	table.cellSpacing = 0;
 714             	table.cellPadding = 0;
 715 rizwank 1.1 	table.calendar = this;
 716             	Calendar.addEvent(table, "mousedown", Calendar.tableMouseDown);
 717             
 718             	var div = Calendar.createElement("div");
 719             	this.element = div;
 720             	div.className = "calendar";
 721             	if (this.isPopup) {
 722             		div.style.position = "absolute";
 723             		div.style.display = "none";
 724             	}
 725             	div.appendChild(table);
 726             
 727             	var thead = Calendar.createElement("thead", table);
 728             	var cell = null;
 729             	var row = null;
 730             
 731             	var cal = this;
 732             	var hh = function (text, cs, navtype) {
 733             		cell = Calendar.createElement("td", row);
 734             		cell.colSpan = cs;
 735             		cell.className = "button";
 736 rizwank 1.1 		if (navtype != 0 && Math.abs(navtype) <= 2)
 737             			cell.className += " nav";
 738             		Calendar._add_evs(cell);
 739             		cell.calendar = cal;
 740             		cell.navtype = navtype;
 741             		if (text.substr(0, 1) != "&") {
 742             			cell.appendChild(document.createTextNode(text));
 743             		}
 744             		else {
 745             			// FIXME: dirty hack for entities
 746             			cell.innerHTML = text;
 747             		}
 748             		return cell;
 749             	};
 750             
 751             	row = Calendar.createElement("tr", thead);
 752             	var title_length = 6;
 753             	(this.isPopup) && --title_length;
 754             	(this.weekNumbers) && ++title_length;
 755             
 756             	hh("?", 1, 400).ttip = Calendar._TT["INFO"];
 757 rizwank 1.1 	this.title = hh("", title_length, 300);
 758             	this.title.className = "title";
 759             	if (this.isPopup) {
 760             		this.title.ttip = Calendar._TT["DRAG_TO_MOVE"];
 761             		this.title.style.cursor = "move";
 762             		hh("&#x00d7;", 1, 200).ttip = Calendar._TT["CLOSE"];
 763             	}
 764             
 765             	row = Calendar.createElement("tr", thead);
 766             	row.className = "headrow";
 767             
 768             	this._nav_py = hh("&#x00ab;", 1, -2);
 769             	this._nav_py.ttip = Calendar._TT["PREV_YEAR"];
 770             
 771             	this._nav_pm = hh("&#x2039;", 1, -1);
 772             	this._nav_pm.ttip = Calendar._TT["PREV_MONTH"];
 773             
 774             	this._nav_now = hh(Calendar._TT["TODAY"], this.weekNumbers ? 4 : 3, 0);
 775             	this._nav_now.ttip = Calendar._TT["GO_TODAY"];
 776             
 777             	this._nav_nm = hh("&#x203a;", 1, 1);
 778 rizwank 1.1 	this._nav_nm.ttip = Calendar._TT["NEXT_MONTH"];
 779             
 780             	this._nav_ny = hh("&#x00bb;", 1, 2);
 781             	this._nav_ny.ttip = Calendar._TT["NEXT_YEAR"];
 782             
 783             	// day names
 784             	row = Calendar.createElement("tr", thead);
 785             	row.className = "daynames";
 786             	if (this.weekNumbers) {
 787             		cell = Calendar.createElement("td", row);
 788             		cell.className = "name wn";
 789             		cell.appendChild(document.createTextNode(Calendar._TT["WK"]));
 790             	}
 791             	for (var i = 7; i > 0; --i) {
 792             		cell = Calendar.createElement("td", row);
 793             		cell.appendChild(document.createTextNode(""));
 794             		if (!i) {
 795             			cell.navtype = 100;
 796             			cell.calendar = this;
 797             			Calendar._add_evs(cell);
 798             		}
 799 rizwank 1.1 	}
 800             	this.firstdayname = (this.weekNumbers) ? row.firstChild.nextSibling : row.firstChild;
 801             	this._displayWeekdays();
 802             
 803             	var tbody = Calendar.createElement("tbody", table);
 804             	this.tbody = tbody;
 805             
 806             	for (i = 6; i > 0; --i) {
 807             		row = Calendar.createElement("tr", tbody);
 808             		if (this.weekNumbers) {
 809             			cell = Calendar.createElement("td", row);
 810             			cell.appendChild(document.createTextNode(""));
 811             		}
 812             		for (var j = 7; j > 0; --j) {
 813             			cell = Calendar.createElement("td", row);
 814             			cell.appendChild(document.createTextNode(""));
 815             			cell.calendar = this;
 816             			Calendar._add_evs(cell);
 817             		}
 818             	}
 819             
 820 rizwank 1.1 	if (this.showsTime) {
 821             		row = Calendar.createElement("tr", tbody);
 822             		row.className = "time";
 823             
 824             		cell = Calendar.createElement("td", row);
 825             		cell.className = "time";
 826             		cell.colSpan = 2;
 827             		cell.innerHTML = "&nbsp;";
 828             
 829             		cell = Calendar.createElement("td", row);
 830             		cell.className = "time";
 831             		cell.colSpan = this.weekNumbers ? 4 : 3;
 832             
 833             		(function(){
 834             			function makeTimePart(className, init, range_start, range_end) {
 835             				var part = Calendar.createElement("span", cell);
 836             				part.className = className;
 837             				part.appendChild(document.createTextNode(init));
 838             				part.calendar = cal;
 839             				part.ttip = Calendar._TT["TIME_PART"];
 840             				part.navtype = 50;
 841 rizwank 1.1 				part._range = [];
 842             				if (typeof range_start != "number")
 843             					part._range = range_start;
 844             				else {
 845             					for (var i = range_start; i <= range_end; ++i) {
 846             						var txt;
 847             						if (i < 10 && range_end >= 10) txt = '0' + i;
 848             						else txt = '' + i;
 849             						part._range[part._range.length] = txt;
 850             					}
 851             				}
 852             				Calendar._add_evs(part);
 853             				return part;
 854             			};
 855             			var hrs = cal.date.getHours();
 856             			var mins = cal.date.getMinutes();
 857             			var t12 = !cal.time24;
 858             			var pm = (hrs > 12);
 859             			if (t12 && pm) hrs -= 12;
 860             			var H = makeTimePart("hour", hrs, t12 ? 1 : 0, t12 ? 12 : 23);
 861             			var span = Calendar.createElement("span", cell);
 862 rizwank 1.1 			span.appendChild(document.createTextNode(":"));
 863             			span.className = "colon";
 864             			var M = makeTimePart("minute", mins, 0, 59);
 865             			var AP = null;
 866             			cell = Calendar.createElement("td", row);
 867             			cell.className = "time";
 868             			cell.colSpan = 2;
 869             			if (t12)
 870             				AP = makeTimePart("ampm", pm ? "pm" : "am", ["am", "pm"]);
 871             			else
 872             				cell.innerHTML = "&nbsp;";
 873             
 874             			cal.onSetTime = function() {
 875             				var hrs = this.date.getHours();
 876             				var mins = this.date.getMinutes();
 877             				var pm = (hrs > 12);
 878             				if (pm && t12) hrs -= 12;
 879             				H.firstChild.data = (hrs < 10) ? ("0" + hrs) : hrs;
 880             				M.firstChild.data = (mins < 10) ? ("0" + mins) : mins;
 881             				if (t12)
 882             					AP.firstChild.data = pm ? "pm" : "am";
 883 rizwank 1.1 			};
 884             
 885             			cal.onUpdateTime = function() {
 886             				var date = this.date;
 887             				var h = parseInt(H.firstChild.data, 10);
 888             				if (t12) {
 889             					if (/pm/i.test(AP.firstChild.data) && h < 12)
 890             						h += 12;
 891             					else if (/am/i.test(AP.firstChild.data) && h == 12)
 892             						h = 0;
 893             				}
 894             				var d = date.getDate();
 895             				var m = date.getMonth();
 896             				var y = date.getFullYear();
 897             				date.setHours(h);
 898             				date.setMinutes(parseInt(M.firstChild.data, 10));
 899             				date.setFullYear(y);
 900             				date.setMonth(m);
 901             				date.setDate(d);
 902             				this.dateClicked = false;
 903             				this.callHandler();
 904 rizwank 1.1 			};
 905             		})();
 906             	} else {
 907             		this.onSetTime = this.onUpdateTime = function() {};
 908             	}
 909             
 910             	var tfoot = Calendar.createElement("tfoot", table);
 911             
 912             	row = Calendar.createElement("tr", tfoot);
 913             	row.className = "footrow";
 914             
 915             	cell = hh(Calendar._TT["SEL_DATE"], this.weekNumbers ? 8 : 7, 300);
 916             	cell.className = "ttip";
 917             	if (this.isPopup) {
 918             		cell.ttip = Calendar._TT["DRAG_TO_MOVE"];
 919             		cell.style.cursor = "move";
 920             	}
 921             	this.tooltips = cell;
 922             
 923             	div = Calendar.createElement("div", this.element);
 924             	this.monthsCombo = div;
 925 rizwank 1.1 	div.className = "combo";
 926             	for (i = 0; i < Calendar._MN.length; ++i) {
 927             		var mn = Calendar.createElement("div");
 928             		mn.className = Calendar.is_ie ? "label-IEfix" : "label";
 929             		mn.month = i;
 930             		mn.appendChild(document.createTextNode(Calendar._SMN[i]));
 931             		div.appendChild(mn);
 932             	}
 933             
 934             	div = Calendar.createElement("div", this.element);
 935             	this.yearsCombo = div;
 936             	div.className = "combo";
 937             	for (i = 12; i > 0; --i) {
 938             		var yr = Calendar.createElement("div");
 939             		yr.className = Calendar.is_ie ? "label-IEfix" : "label";
 940             		yr.appendChild(document.createTextNode(""));
 941             		div.appendChild(yr);
 942             	}
 943             
 944             	this._init(this.mondayFirst, this.date);
 945             	parent.appendChild(this.element);
 946 rizwank 1.1 };
 947             
 948             /** keyboard navigation, only for popup calendars */
 949             Calendar._keyEvent = function(ev) {
 950             	if (!window.calendar) {
 951             		return false;
 952             	}
 953             	(Calendar.is_ie) && (ev = window.event);
 954             	var cal = window.calendar;
 955             	var act = (Calendar.is_ie || ev.type == "keypress");
 956             	if (ev.ctrlKey) {
 957             		switch (ev.keyCode) {
 958             		    case 37: // KEY left
 959             			act && Calendar.cellClick(cal._nav_pm);
 960             			break;
 961             		    case 38: // KEY up
 962             			act && Calendar.cellClick(cal._nav_py);
 963             			break;
 964             		    case 39: // KEY right
 965             			act && Calendar.cellClick(cal._nav_nm);
 966             			break;
 967 rizwank 1.1 		    case 40: // KEY down
 968             			act && Calendar.cellClick(cal._nav_ny);
 969             			break;
 970             		    default:
 971             			return false;
 972             		}
 973             	} else switch (ev.keyCode) {
 974             	    case 32: // KEY space (now)
 975             		Calendar.cellClick(cal._nav_now);
 976             		break;
 977             	    case 27: // KEY esc
 978             		act && cal.hide();
 979             		break;
 980             	    case 37: // KEY left
 981             	    case 38: // KEY up
 982             	    case 39: // KEY right
 983             	    case 40: // KEY down
 984             		if (act) {
 985             			var date = cal.date.getDate() - 1;
 986             			var el = cal.currentDateEl;
 987             			var ne = null;
 988 rizwank 1.1 			var prev = (ev.keyCode == 37) || (ev.keyCode == 38);
 989             			switch (ev.keyCode) {
 990             			    case 37: // KEY left
 991             				(--date >= 0) && (ne = cal.ar_days[date]);
 992             				break;
 993             			    case 38: // KEY up
 994             				date -= 7;
 995             				(date >= 0) && (ne = cal.ar_days[date]);
 996             				break;
 997             			    case 39: // KEY right
 998             				(++date < cal.ar_days.length) && (ne = cal.ar_days[date]);
 999             				break;
1000             			    case 40: // KEY down
1001             				date += 7;
1002             				(date < cal.ar_days.length) && (ne = cal.ar_days[date]);
1003             				break;
1004             			}
1005             			if (!ne) {
1006             				if (prev) {
1007             					Calendar.cellClick(cal._nav_pm);
1008             				} else {
1009 rizwank 1.1 					Calendar.cellClick(cal._nav_nm);
1010             				}
1011             				date = (prev) ? cal.date.getMonthDays() : 1;
1012             				el = cal.currentDateEl;
1013             				ne = cal.ar_days[date - 1];
1014             			}
1015             			Calendar.removeClass(el, "selected");
1016             			Calendar.addClass(ne, "selected");
1017             			cal.date.setDate(ne.caldate);
1018             			cal.callHandler();
1019             			cal.currentDateEl = ne;
1020             		}
1021             		break;
1022             	    case 13: // KEY enter
1023             		if (act) {
1024             			cal.callHandler();
1025             			cal.hide();
1026             		}
1027             		break;
1028             	    default:
1029             		return false;
1030 rizwank 1.1 	}
1031             	return Calendar.stopEvent(ev);
1032             };
1033             
1034             /**
1035              *  (RE)Initializes the calendar to the given date and style (if mondayFirst is
1036              *  true it makes Monday the first day of week, otherwise the weeks start on
1037              *  Sunday.
1038              */
1039             Calendar.prototype._init = function (mondayFirst, date) {
1040             	var today = new Date();
1041             	var year = date.getFullYear();
1042             	if (year < this.minYear) {
1043             		year = this.minYear;
1044             		date.setFullYear(year);
1045             	} else if (year > this.maxYear) {
1046             		year = this.maxYear;
1047             		date.setFullYear(year);
1048             	}
1049             	this.mondayFirst = mondayFirst;
1050             	this.date = new Date(date);
1051 rizwank 1.1 	var month = date.getMonth();
1052             	var mday = date.getDate();
1053             	var no_days = date.getMonthDays();
1054             	date.setDate(1);
1055             	var wday = date.getDay();
1056             	var MON = mondayFirst ? 1 : 0;
1057             	var SAT = mondayFirst ? 5 : 6;
1058             	var SUN = mondayFirst ? 6 : 0;
1059             	if (mondayFirst) {
1060             		wday = (wday > 0) ? (wday - 1) : 6;
1061             	}
1062             	var iday = 1;
1063             	var row = this.tbody.firstChild;
1064             	var MN = Calendar._SMN[month];
1065             	var hasToday = ((today.getFullYear() == year) && (today.getMonth() == month));
1066             	var todayDate = today.getDate();
1067             	var week_number = date.getWeekNumber();
1068             	var ar_days = new Array();
1069             	for (var i = 0; i < 6; ++i) {
1070             		if (iday > no_days) {
1071             			row.className = "emptyrow";
1072 rizwank 1.1 			row = row.nextSibling;
1073             			continue;
1074             		}
1075             		var cell = row.firstChild;
1076             		if (this.weekNumbers) {
1077             			cell.className = "day wn";
1078             			cell.firstChild.data = week_number;
1079             			cell = cell.nextSibling;
1080             		}
1081             		++week_number;
1082             		row.className = "daysrow";
1083             		for (var j = 0; j < 7; ++j) {
1084             			cell.className = "day";
1085             			if ((!i && j < wday) || iday > no_days) {
1086             				// cell.className = "emptycell";
1087             				cell.innerHTML = "&nbsp;";
1088             				cell.disabled = true;
1089             				cell = cell.nextSibling;
1090             				continue;
1091             			}
1092             			cell.disabled = false;
1093 rizwank 1.1 			cell.firstChild.data = iday;
1094             			if (typeof this.getDateStatus == "function") {
1095             				date.setDate(iday);
1096             				var status = this.getDateStatus(date, year, month, iday);
1097             				if (status === true) {
1098             					cell.className += " disabled";
1099             					cell.disabled = true;
1100             				} else {
1101             					if (/disabled/i.test(status))
1102             						cell.disabled = true;
1103             					cell.className += " " + status;
1104             				}
1105             			}
1106             			if (!cell.disabled) {
1107             				ar_days[ar_days.length] = cell;
1108             				cell.caldate = iday;
1109             				cell.ttip = "_";
1110             				if (iday == mday) {
1111             					cell.className += " selected";
1112             					this.currentDateEl = cell;
1113             				}
1114 rizwank 1.1 				if (hasToday && (iday == todayDate)) {
1115             					cell.className += " today";
1116             					cell.ttip += Calendar._TT["PART_TODAY"];
1117             				}
1118             				if (wday == SAT || wday == SUN) {
1119             					cell.className += " weekend";
1120             				}
1121             			}
1122             			++iday;
1123             			((++wday) ^ 7) || (wday = 0);
1124             			cell = cell.nextSibling;
1125             		}
1126             		row = row.nextSibling;
1127             	}
1128             	this.ar_days = ar_days;
1129             	this.title.firstChild.data = Calendar._MN[month] + ", " + year;
1130             	this.onSetTime();
1131             	// PROFILE
1132             	// this.tooltips.firstChild.data = "Generated in " + ((new Date()) - today) + " ms";
1133             };
1134             
1135 rizwank 1.1 /**
1136              *  Calls _init function above for going to a certain date (but only if the
1137              *  date is different than the currently selected one).
1138              */
1139             Calendar.prototype.setDate = function (date) {
1140             	if (!date.equalsTo(this.date)) {
1141             		this._init(this.mondayFirst, date);
1142             	}
1143             };
1144             
1145             /**
1146              *  Refreshes the calendar.  Useful if the "disabledHandler" function is
1147              *  dynamic, meaning that the list of disabled date can change at runtime.
1148              *  Just * call this function if you think that the list of disabled dates
1149              *  should * change.
1150              */
1151             Calendar.prototype.refresh = function () {
1152             	this._init(this.mondayFirst, this.date);
1153             };
1154             
1155             /** Modifies the "mondayFirst" parameter (EU/US style). */
1156 rizwank 1.1 Calendar.prototype.setMondayFirst = function (mondayFirst) {
1157             	this._init(mondayFirst, this.date);
1158             	this._displayWeekdays();
1159             };
1160             
1161             /**
1162              *  Allows customization of what dates are enabled.  The "unaryFunction"
1163              *  parameter must be a function object that receives the date (as a JS Date
1164              *  object) and returns a boolean value.  If the returned value is true then
1165              *  the passed date will be marked as disabled.
1166              */
1167             Calendar.prototype.setDateStatusHandler = Calendar.prototype.setDisabledHandler = function (unaryFunction) {
1168             	this.getDateStatus = unaryFunction;
1169             };
1170             
1171             /** Customization of allowed year range for the calendar. */
1172             Calendar.prototype.setRange = function (a, z) {
1173             	this.minYear = a;
1174             	this.maxYear = z;
1175             };
1176             
1177 rizwank 1.1 /** Calls the first user handler (selectedHandler). */
1178             Calendar.prototype.callHandler = function () {
1179             	if (this.onSelected) {
1180             		this.onSelected(this, this.date.print(this.dateFormat));
1181             	}
1182             };
1183             
1184             /** Calls the second user handler (closeHandler). */
1185             Calendar.prototype.callCloseHandler = function () {
1186             	if (this.onClose) {
1187             		this.onClose(this);
1188             	}
1189             	this.hideShowCovered();
1190             };
1191             
1192             /** Removes the calendar object from the DOM tree and destroys it. */
1193             Calendar.prototype.destroy = function () {
1194             	var el = this.element.parentNode;
1195             	el.removeChild(this.element);
1196             	Calendar._C = null;
1197             	window.calendar = null;
1198 rizwank 1.1 };
1199             
1200             /**
1201              *  Moves the calendar element to a different section in the DOM tree (changes
1202              *  its parent).
1203              */
1204             Calendar.prototype.reparent = function (new_parent) {
1205             	var el = this.element;
1206             	el.parentNode.removeChild(el);
1207             	new_parent.appendChild(el);
1208             };
1209             
1210             // This gets called when the user presses a mouse button anywhere in the
1211             // document, if the calendar is shown.  If the click was outside the open
1212             // calendar this function closes it.
1213             Calendar._checkCalendar = function(ev) {
1214             	if (!window.calendar) {
1215             		return false;
1216             	}
1217             	var el = Calendar.is_ie ? Calendar.getElement(ev) : Calendar.getTargetElement(ev);
1218             	for (; el != null && el != calendar.element; el = el.parentNode);
1219 rizwank 1.1 	if (el == null) {
1220             		// calls closeHandler which should hide the calendar.
1221             		window.calendar.callCloseHandler();
1222             		return Calendar.stopEvent(ev);
1223             	}
1224             };
1225             
1226             /** Shows the calendar. */
1227             Calendar.prototype.show = function () {
1228             	var rows = this.table.getElementsByTagName("tr");
1229             	for (var i = rows.length; i > 0;) {
1230             		var row = rows[--i];
1231             		Calendar.removeClass(row, "rowhilite");
1232             		var cells = row.getElementsByTagName("td");
1233             		for (var j = cells.length; j > 0;) {
1234             			var cell = cells[--j];
1235             			Calendar.removeClass(cell, "hilite");
1236             			Calendar.removeClass(cell, "active");
1237             		}
1238             	}
1239             	this.element.style.display = "block";
1240 rizwank 1.1 	this.hidden = false;
1241             	if (this.isPopup) {
1242             		window.calendar = this;
1243             		Calendar.addEvent(document, "keydown", Calendar._keyEvent);
1244             		Calendar.addEvent(document, "keypress", Calendar._keyEvent);
1245             		Calendar.addEvent(document, "mousedown", Calendar._checkCalendar);
1246             	}
1247             	this.hideShowCovered();
1248             };
1249             
1250             /**
1251              *  Hides the calendar.  Also removes any "hilite" from the class of any TD
1252              *  element.
1253              */
1254             Calendar.prototype.hide = function () {
1255             	if (this.isPopup) {
1256             		Calendar.removeEvent(document, "keydown", Calendar._keyEvent);
1257             		Calendar.removeEvent(document, "keypress", Calendar._keyEvent);
1258             		Calendar.removeEvent(document, "mousedown", Calendar._checkCalendar);
1259             	}
1260             	this.element.style.display = "none";
1261 rizwank 1.1 	this.hidden = true;
1262             	this.hideShowCovered();
1263             };
1264             
1265             /**
1266              *  Shows the calendar at a given absolute position (beware that, depending on
1267              *  the calendar element style -- position property -- this might be relative
1268              *  to the parent's containing rectangle).
1269              */
1270             Calendar.prototype.showAt = function (x, y) {
1271             	var s = this.element.style;
1272             	s.left = x + "px";
1273             	s.top = y + "px";
1274             	this.show();
1275             };
1276             
1277             /** Shows the calendar near a given element. */
1278             Calendar.prototype.showAtElement = function (el, opts) {
1279             	var self = this;
1280             	var p = Calendar.getAbsolutePos(el);
1281             	if (!opts || typeof opts != "string") {
1282 rizwank 1.1 		this.showAt(p.x, p.y + el.offsetHeight);
1283             		return true;
1284             	}
1285             	this.element.style.display = "block";
1286             	Calendar.continuation_for_the_fucking_khtml_browser = function() {
1287             		var w = self.element.offsetWidth;
1288             		var h = self.element.offsetHeight;
1289             		self.element.style.display = "none";
1290             		var valign = opts.substr(0, 1);
1291             		var halign = "l";
1292             		if (opts.length > 1) {
1293             			halign = opts.substr(1, 1);
1294             		}
1295             		// vertical alignment
1296             		switch (valign) {
1297             		    case "T": p.y -= h; break;
1298             		    case "B": p.y += el.offsetHeight; break;
1299             		    case "C": p.y += (el.offsetHeight - h) / 2; break;
1300             		    case "t": p.y += el.offsetHeight - h; break;
1301             		    case "b": break; // already there
1302             		}
1303 rizwank 1.1 		// horizontal alignment
1304             		switch (halign) {
1305             		    case "L": p.x -= w; break;
1306             		    case "R": p.x += el.offsetWidth; break;
1307             		    case "C": p.x += (el.offsetWidth - w) / 2; break;
1308             		    case "r": p.x += el.offsetWidth - w; break;
1309             		    case "l": break; // already there
1310             		}
1311             		self.showAt(p.x, p.y);
1312             	};
1313             	if (Calendar.is_khtml)
1314             		setTimeout("Calendar.continuation_for_the_fucking_khtml_browser()", 10);
1315             	else
1316             		Calendar.continuation_for_the_fucking_khtml_browser();
1317             };
1318             
1319             /** Customizes the date format. */
1320             Calendar.prototype.setDateFormat = function (str) {
1321             	this.dateFormat = str;
1322             };
1323             
1324 rizwank 1.1 /** Customizes the tooltip date format. */
1325             Calendar.prototype.setTtDateFormat = function (str) {
1326             	this.ttDateFormat = str;
1327             };
1328             
1329             /**
1330              *  Tries to identify the date represented in a string.  If successful it also
1331              *  calls this.setDate which moves the calendar to the given date.
1332              */
1333             Calendar.prototype.parseDate = function (str, fmt) {
1334             	var y = 0;
1335             	var m = -1;
1336             	var d = 0;
1337             	var a = str.split(/\W+/);
1338             	if (!fmt) {
1339             		fmt = this.dateFormat;
1340             	}
1341             	var b = [];
1342             	fmt.replace(/(%.)/g, function(str, par) {
1343             		return b[b.length] = par;
1344             	});
1345 rizwank 1.1 	var i = 0, j = 0;
1346             	var hr = 0;
1347             	var min = 0;
1348             	for (i = 0; i < a.length; ++i) {
1349             		if (b[i] == "%a" || b[i] == "%A") {
1350             			continue;
1351             		}
1352             		if (b[i] == "%d" || b[i] == "%e") {
1353             			d = parseInt(a[i], 10);
1354             		}
1355             		if (b[i] == "%m") {
1356             			m = parseInt(a[i], 10) - 1;
1357             		}
1358             		if (b[i] == "%Y" || b[i] == "%y") {
1359             			y = parseInt(a[i], 10);
1360             			(y < 100) && (y += (y > 29) ? 1900 : 2000);
1361             		}
1362             		if (b[i] == "%b" || b[i] == "%B") {
1363             			for (j = 0; j < 12; ++j) {
1364             				if (Calendar._MN[j].substr(0, a[i].length).toLowerCase() == a[i].toLowerCase()) { m = j; break; }
1365             			}
1366 rizwank 1.1 		} else if (/%[HIkl]/.test(b[i])) {
1367             			hr = parseInt(a[i], 10);
1368             		} else if (/%[pP]/.test(b[i])) {
1369             			if (/pm/i.test(a[i]) && hr < 12)
1370             				hr += 12;
1371             		} else if (b[i] == "%M") {
1372             			min = parseInt(a[i], 10);
1373             		}
1374             	}
1375             	if (y != 0 && m != -1 && d != 0) {
1376             		this.setDate(new Date(y, m, d, hr, min, 0));
1377             		return;
1378             	}
1379             	y = 0; m = -1; d = 0;
1380             	for (i = 0; i < a.length; ++i) {
1381             		if (a[i].search(/[a-zA-Z]+/) != -1) {
1382             			var t = -1;
1383             			for (j = 0; j < 12; ++j) {
1384             				if (Calendar._MN[j].substr(0, a[i].length).toLowerCase() == a[i].toLowerCase()) { t = j; break; }
1385             			}
1386             			if (t != -1) {
1387 rizwank 1.1 				if (m != -1) {
1388             					d = m+1;
1389             				}
1390             				m = t;
1391             			}
1392             		} else if (parseInt(a[i], 10) <= 12 && m == -1) {
1393             			m = a[i]-1;
1394             		} else if (parseInt(a[i], 10) > 31 && y == 0) {
1395             			y = parseInt(a[i], 10);
1396             			(y < 100) && (y += (y > 29) ? 1900 : 2000);
1397             		} else if (d == 0) {
1398             			d = a[i];
1399             		}
1400             	}
1401             	if (y == 0) {
1402             		var today = new Date();
1403             		y = today.getFullYear();
1404             	}
1405             	if (m != -1 && d != 0) {
1406             		this.setDate(new Date(y, m, d, hr, min, 0));
1407             	}
1408 rizwank 1.1 };
1409             
1410             Calendar.prototype.hideShowCovered = function () {
1411             	var self = this;
1412             	Calendar.continuation_for_the_fucking_khtml_browser = function() {
1413             		function getVisib(obj){
1414             			var value = obj.style.visibility;
1415             			if (!value) {
1416             				if (document.defaultView && typeof (document.defaultView.getComputedStyle) == "function") { // Gecko, W3C
1417             					if (!Calendar.is_khtml)
1418             						value = document.defaultView.
1419             							getComputedStyle(obj, "").getPropertyValue("visibility");
1420             					else
1421             						value = '';
1422             				} else if (obj.currentStyle) { // IE
1423             					value = obj.currentStyle.visibility;
1424             				} else
1425             					value = '';
1426             			}
1427             			return value;
1428             		};
1429 rizwank 1.1 
1430             		var tags = new Array("applet", "iframe", "select");
1431             		var el = self.element;
1432             
1433             		var p = Calendar.getAbsolutePos(el);
1434             		var EX1 = p.x;
1435             		var EX2 = el.offsetWidth + EX1;
1436             		var EY1 = p.y;
1437             		var EY2 = el.offsetHeight + EY1;
1438             
1439             		for (var k = tags.length; k > 0; ) {
1440             			var ar = document.getElementsByTagName(tags[--k]);
1441             			var cc = null;
1442             
1443             			for (var i = ar.length; i > 0;) {
1444             				cc = ar[--i];
1445             
1446             				p = Calendar.getAbsolutePos(cc);
1447             				var CX1 = p.x;
1448             				var CX2 = cc.offsetWidth + CX1;
1449             				var CY1 = p.y;
1450 rizwank 1.1 				var CY2 = cc.offsetHeight + CY1;
1451             
1452             				if (self.hidden || (CX1 > EX2) || (CX2 < EX1) || (CY1 > EY2) || (CY2 < EY1)) {
1453             					if (!cc.__msh_save_visibility) {
1454             						cc.__msh_save_visibility = getVisib(cc);
1455             					}
1456             					cc.style.visibility = cc.__msh_save_visibility;
1457             				} else {
1458             					if (!cc.__msh_save_visibility) {
1459             						cc.__msh_save_visibility = getVisib(cc);
1460             					}
1461             					cc.style.visibility = "hidden";
1462             				}
1463             			}
1464             		}
1465             	};
1466             	if (Calendar.is_khtml)
1467             		setTimeout("Calendar.continuation_for_the_fucking_khtml_browser()", 10);
1468             	else
1469             		Calendar.continuation_for_the_fucking_khtml_browser();
1470             };
1471 rizwank 1.1 
1472             /** Internal function; it displays the bar with the names of the weekday. */
1473             Calendar.prototype._displayWeekdays = function () {
1474             	var MON = this.mondayFirst ? 0 : 1;
1475             	var SUN = this.mondayFirst ? 6 : 0;
1476             	var SAT = this.mondayFirst ? 5 : 6;
1477             	var cell = this.firstdayname;
1478             	for (var i = 0; i < 7; ++i) {
1479             		cell.className = "day name";
1480             		if (!i) {
1481             			cell.ttip = this.mondayFirst ? Calendar._TT["SUN_FIRST"] : Calendar._TT["MON_FIRST"];
1482             			cell.navtype = 100;
1483             			cell.calendar = this;
1484             			Calendar._add_evs(cell);
1485             		}
1486             		if (i == SUN || i == SAT) {
1487             			Calendar.addClass(cell, "weekend");
1488             		}
1489             		cell.firstChild.data = Calendar._SDN[i + 1 - MON];
1490             		cell = cell.nextSibling;
1491             	}
1492 rizwank 1.1 };
1493             
1494             /** Internal function.  Hides all combo boxes that might be displayed. */
1495             Calendar.prototype._hideCombos = function () {
1496             	this.monthsCombo.style.display = "none";
1497             	this.yearsCombo.style.display = "none";
1498             };
1499             
1500             /** Internal function.  Starts dragging the element. */
1501             Calendar.prototype._dragStart = function (ev) {
1502             	if (this.dragging) {
1503             		return;
1504             	}
1505             	this.dragging = true;
1506             	var posX;
1507             	var posY;
1508             	if (Calendar.is_ie) {
1509             		posY = window.event.clientY + document.body.scrollTop;
1510             		posX = window.event.clientX + document.body.scrollLeft;
1511             	} else {
1512             		posY = ev.clientY + window.scrollY;
1513 rizwank 1.1 		posX = ev.clientX + window.scrollX;
1514             	}
1515             	var st = this.element.style;
1516             	this.xOffs = posX - parseInt(st.left);
1517             	this.yOffs = posY - parseInt(st.top);
1518             	with (Calendar) {
1519             		addEvent(document, "mousemove", calDragIt);
1520             		addEvent(document, "mouseover", stopEvent);
1521             		addEvent(document, "mouseup", calDragEnd);
1522             	}
1523             };
1524             
1525             // BEGIN: DATE OBJECT PATCHES
1526             
1527             /** Adds the number of days array to the Date object. */
1528             Date._MD = new Array(31,28,31,30,31,30,31,31,30,31,30,31);
1529             
1530             /** Constants used for time computations */
1531             Date.SECOND = 1000 /* milliseconds */;
1532             Date.MINUTE = 60 * Date.SECOND;
1533             Date.HOUR   = 60 * Date.MINUTE;
1534 rizwank 1.1 Date.DAY    = 24 * Date.HOUR;
1535             Date.WEEK   =  7 * Date.DAY;
1536             
1537             /** Returns the number of days in the current month */
1538             Date.prototype.getMonthDays = function(month) {
1539             	var year = this.getFullYear();
1540             	if (typeof month == "undefined") {
1541             		month = this.getMonth();
1542             	}
1543             	if (((0 == (year%4)) && ( (0 != (year%100)) || (0 == (year%400)))) && month == 1) {
1544             		return 29;
1545             	} else {
1546             		return Date._MD[month];
1547             	}
1548             };
1549             
1550             /** Returns the number of day in the year. */
1551             Date.prototype.getDayOfYear = function() {
1552             	var now = new Date(this.getFullYear(), this.getMonth(), this.getDate(), 0, 0, 0);
1553             	var then = new Date(this.getFullYear(), 0, 1, 0, 0, 0);
1554             	var time = now - then;
1555 rizwank 1.1 	return Math.floor(time / Date.DAY);
1556             };
1557             
1558             /** Returns the number of the week in year, as defined in ISO 8601. */
1559             Date.prototype.getWeekNumber = function() {
1560             	var now = new Date(this.getFullYear(), this.getMonth(), this.getDate(), 0, 0, 0);
1561             	var then = new Date(this.getFullYear(), 0, 1, 0, 0, 0);
1562             	var time = now - then;
1563             	var day = then.getDay(); // 0 means Sunday
1564             	if (day == 0) day = 7;
1565             	(day > 4) && (day -= 4) || (day += 3);
1566             	return Math.round(((time / Date.DAY) + day) / 7);
1567             };
1568             
1569             /** Checks dates equality (ignores time) */
1570             Date.prototype.equalsTo = function(date) {
1571             	return ((this.getFullYear() == date.getFullYear()) &&
1572             		(this.getMonth() == date.getMonth()) &&
1573             		(this.getDate() == date.getDate()) &&
1574             		(this.getHours() == date.getHours()) &&
1575             		(this.getMinutes() == date.getMinutes()));
1576 rizwank 1.1 };
1577             
1578             /** Prints the date in a string according to the given format. */
1579             Date.prototype.print = function (str) {
1580             	var m = this.getMonth();
1581             	var d = this.getDate();
1582             	var y = this.getFullYear();
1583             	var wn = this.getWeekNumber();
1584             	var w = this.getDay();
1585             	var s = {};
1586             	var hr = this.getHours();
1587             	var pm = (hr >= 12);
1588             	var ir = (pm) ? (hr - 12) : hr;
1589             	var dy = this.getDayOfYear();
1590             	if (ir == 0)
1591             		ir = 12;
1592             	var min = this.getMinutes();
1593             	var sec = this.getSeconds();
1594             	s["%a"] = Calendar._SDN[w]; // abbreviated weekday name [FIXME: I18N]
1595             	s["%A"] = Calendar._DN[w]; // full weekday name
1596             	s["%b"] = Calendar._SMN[m]; // abbreviated month name [FIXME: I18N]
1597 rizwank 1.1 	s["%B"] = Calendar._MN[m]; // full month name
1598             	// FIXME: %c : preferred date and time representation for the current locale
1599             	s["%C"] = 1 + Math.floor(y / 100); // the century number
1600             	s["%d"] = (d < 10) ? ("0" + d) : d; // the day of the month (range 01 to 31)
1601             	s["%e"] = d; // the day of the month (range 1 to 31)
1602             	// FIXME: %D : american date style: %m/%d/%y
1603             	// FIXME: %E, %F, %G, %g, %h (man strftime)
1604             	s["%H"] = (hr < 10) ? ("0" + hr) : hr; // hour, range 00 to 23 (24h format)
1605             	s["%I"] = (ir < 10) ? ("0" + ir) : ir; // hour, range 01 to 12 (12h format)
1606             	s["%j"] = (dy < 100) ? ((dy < 10) ? ("00" + dy) : ("0" + dy)) : dy; // day of the year (range 001 to 366)
1607             	s["%k"] = hr;		// hour, range 0 to 23 (24h format)
1608             	s["%l"] = ir;		// hour, range 1 to 12 (12h format)
1609             	s["%m"] = (m < 9) ? ("0" + (1+m)) : (1+m); // month, range 01 to 12
1610             	s["%M"] = (min < 10) ? ("0" + min) : min; // minute, range 00 to 59
1611             	s["%n"] = "\n";		// a newline character
1612             	s["%p"] = pm ? "PM" : "AM";
1613             	s["%P"] = pm ? "pm" : "am";
1614             	// FIXME: %r : the time in am/pm notation %I:%M:%S %p
1615             	// FIXME: %R : the time in 24-hour notation %H:%M
1616             	s["%s"] = Math.floor(this.getTime() / 1000);
1617             	s["%S"] = (sec < 10) ? ("0" + sec) : sec; // seconds, range 00 to 59
1618 rizwank 1.1 	s["%t"] = "\t";		// a tab character
1619             	// FIXME: %T : the time in 24-hour notation (%H:%M:%S)
1620             	s["%U"] = s["%W"] = s["%V"] = (wn < 10) ? ("0" + wn) : wn;
1621             	s["%u"] = w + 1;	// the day of the week (range 1 to 7, 1 = MON)
1622             	s["%w"] = w;		// the day of the week (range 0 to 6, 0 = SUN)
1623             	// FIXME: %x : preferred date representation for the current locale without the time
1624             	// FIXME: %X : preferred time representation for the current locale without the date
1625             	s["%y"] = ('' + y).substr(2, 2); // year without the century (range 00 to 99)
1626             	s["%Y"] = y;		// year with the century
1627             	s["%%"] = "%";		// a literal '%' character
1628             	var re = Date._msh_formatRegexp;
1629             	if (typeof re == "undefined") {
1630             		var tmp = "";
1631             		for (var i in s)
1632             			tmp += tmp ? ("|" + i) : i;
1633             		Date._msh_formatRegexp = re = new RegExp("(" + tmp + ")", 'g');
1634             	}
1635             	return str.replace(re, function(match, par) { return s[par]; });
1636             };
1637             
1638             // END: DATE OBJECT PATCHES
1639 rizwank 1.1 
1640             // global object that remembers the calendar
1641             window.calendar = null;

Rizwan Kassim
Powered by
ViewCVS 0.9.2