PageSourceSearch

https://sso.nacional.uy/static/calendar.js?186682

js nacional.uy collected 2026-09-24 20:14:37 UTC 47,653 bytes, 1,655 lines download raw bytes

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

Line numbers count LF bytes from the start of the resource, as the search results do. Vendor segments are library code the classifier recognised; they are stored but not indexed. Bytes are shown as Latin1 characters, one per byte.