PageSourceSearch

https://www.vghks.gov.tw/Scripts/JSCal2-1.9/src/js/jquery.dynDateTimeMinGo.js

js vghks.gov.tw collected 2026-10-02 04:50:20 UTC 61,275 bytes, 2,049 lines download raw bytes

1/*
2	dynDateTime 0.2
3	
4	A jQuery date time picker.
5	
6	Author: Toolman
7	Version: 0.2
8	Website: http://code.google.com/p/dyndatetime/
9
10*/
11
12
13(function($) {
14	var myr=0;
15	$.fn.dynDateTime = function(options) {
16	    
17		  // plugin defaults
18		  $.fn.dynDateTime.defaults = {
19			displayArea:  null,
20			button:       null,
21			eventName:    "click",
22			ifFormat:     "%Y/%m/%d",
23			daFormat:     "%Y/%m/%d",
24			singleClick:  true,
25			dateStatusFunc: null,
26			dateText:     null,
27			firstDay:     null,
28			align:        "Br",
29			range:        [1900, 2999],
30			weekNumbers:  true,
31			flat:         null,
32			flatCallback: null,
33			onSelect:     null,
34			onClose:      null,
35			onUpdate:     null,
36			date:         null,
37			showsTime:    false,
38			timeFormat:   "24",
39			electric:     true,
40			step:         1,
41			position:     null,
42			cache:        false,
43			showOthers:   false,
44			multiple:     null,
45			debug:        false,
46			isCht:		  false
47		  };		
48		
49		var opts = $.extend({}, $.fn.dynDateTime.defaults, options);
50	
51		return this.each(function() {
52		
53			//opts are shared per jQuery call; create per inputField closures of non-shared values for each instance
54			var this_inputField = this;
55			var this_displayArea = null;
56			var this_button = null;
57			var this_flat = null;
58			if(opts.displayArea) {
59				try {
60					this_displayArea = eval("jQuery(this)" + opts.displayArea + ".get(0);");
61				} catch (err) {
62					opts.displayArea = null;
63				}
64			}
65			if(opts.button) {
66				try {
67					this_button = eval("jQuery(this)" + opts.button + ".get(0);");
68				} catch (err) {
69					opts.button = null;
70				}
71			}
72			if(opts.flat) {
73				try {
74					this_flat = eval("jQuery(this)" + opts.flat + ".get(0);");
75				} catch (err) {
76					opts.flat = null;
77				}
78			}
79
80			
81		
82			if (!(this_flat || opts.multiple || this_inputField || this_displayArea || this_button)) {
83				log("opts");
84				//nothing to do
85				return;
86			}
87			
88			//default onSelect
89			function onSelect(cal) {
90				var p = cal.opts;
91				var update = (cal.dateClicked || p.electric);
92				if (update && this_inputField) {
93					this_inputField.value = cal.date.print(p.ifFormat);
94					if (typeof this_inputField.onchange == "function")
95						this_inputField.onchange();
96				}
97				if (update && this_displayArea)
98					this_displayArea.innerHTML = cal.date.print(p.daFormat);
99				if (update && typeof p.onUpdate == "function")
100					p.onUpdate(cal);
101				if (update && p.flat) {
102					if (typeof p.flatCallback == "function")
103						p.flatCallback(cal);
104				}
105				if (update && p.singleClick && cal.dateClicked)
106					cal.callCloseHandler();
107			};
108		
109			//flat setup
110			if (this_flat != null) {
111
112				var cal = new Calendar(opts.firstDay, opts.date, opts.onSelect || onSelect);
113				cal.showsOtherMonths = opts.showOthers;
114				cal.showsTime = opts.showsTime;
115				cal.time24 = (opts.timeFormat == "24");
116				cal.opts = opts;
117				cal.weekNumbers = opts.weekNumbers;
118				cal.setRange(opts.range[0], opts.range[1]);
119				cal.setDateStatusHandler(opts.dateStatusFunc);
120				cal.getDateText = opts.dateText;
121				if (opts.ifFormat) {
122					cal.setDateFormat(opts.ifFormat);
123				}
124				if (this_inputField && typeof this_inputField.value == "string") {
125					//cal.parseDate(this_inputField.value);
126					log("rar");
127				}
128				cal.create(this_flat);
129				cal.show();
130				return;
131			}
132		
133			//find the element to mount show/hide event 
134			var triggerEl = this_button || this_displayArea || this_inputField  ;
135
136			//bolt on event
137			triggerEl["on" + opts.eventName] = function() {
138				log("clicked");
139				var dateEl = this_inputField || this_displayArea;
140				var dateFmt = this_inputField ? opts.ifFormat : opts.daFormat;
141				var mustCreate = false;
142				var cal = window.calendar;
143				if (dateEl)
144					opts.date = Date.parseDate(dateEl.value || dateEl.innerHTML, dateFmt);
145				if (!(cal && opts.cache)) {
146					window.calendar = cal = new Calendar(opts.firstDay,
147									     opts.date,
148									     opts.onSelect || onSelect,
149									     opts.onClose || function(cal) { cal.hide(); });
150					cal.showsTime = opts.showsTime;
151					cal.time24 = (opts.timeFormat == "24");
152					cal.weekNumbers = opts.weekNumbers;
153					mustCreate = true;
154				} else {
155					if (opts.date)
156						cal.setDate(opts.date);
157					cal.hide();
158				}
159				if (opts.multiple) {
160					cal.multiple = {};
161					for (var i = opts.multiple.length; --i >= 0;) {
162						var d = opts.multiple[i];
163						var ds = d.print("%Y%m%d");
164						cal.multiple[ds] = d;
165					}
166				}
167				cal.showsOtherMonths = opts.showOthers;
168				cal.yearStep = opts.step;
169				cal.setRange(opts.range[0], opts.range[1]);
170				cal.opts = opts;
171				cal.setDateStatusHandler(opts.dateStatusFunc);
172				cal.getDateText = opts.dateText;
173				cal.setDateFormat(dateFmt);
174				if (mustCreate)
175					cal.create();
176				cal.refresh();
177				if (!opts.position)
178					cal.showAtElement(this_button || this_displayArea || this_inputField, opts.align);
179				else
180					cal.showAt(opts.position[0], opts.position[1]);
181				return false;
182			};
183		});
184		
185		// private function for debugging
186		function log(msg) {
187			if(opts.debug) {
188				window.loadFirebugConsole(); // file:// based access seems to disable this for me!
189				if (window.console && window.console.log ) window.console.log("dynDateTime: " + msg);
190			}
191		};
192	};
193})(jQuery);
194
195// Begin old dynarch code
196
197/*  Copyright Mihai Bazon, 2002-2005  |  www.bazon.net/mishoo
198 * -----------------------------------------------------------
199 *
200 * The DHTML Calendar, version 1.0 "It is happening again"
201 *
202 * Details and latest version at:
203 * www.dynarch.com/projects/calendar
204 *
205 * This script is developed by Dynarch.com.  Visit us at www.dynarch.com.
206 *
207 * This script is distributed under the GNU Lesser General Public License.
208 * Read the entire license text here: http://www.gnu.org/licenses/lgpl.html
209 */
210
211// $Id: calendar.js,v 1.51 2005/03/07 16:44:31 mishoo Exp $
212
213/** The Calendar object constructor. */
214Calendar = function (firstDayOfWeek, dateStr, onSelected, onClose) {
215	// member variables
216	this.activeDiv = null;
217	this.currentDateEl = null;
218	this.getDateStatus = null;
219	this.getDateToolTip = null;
220	this.getDateText = null;
221	this.timeout = null;
222	this.onSelected = onSelected || null;
223	this.onClose = onClose || null;
224	this.dragging = false;
225	this.hidden = false;
226	this.minYear = 1912;
227	this.maxYear = 3000;
228	this.dateFormat = Calendar._TT["DEF_DATE_FORMAT"];
229	this.ttDateFormat = Calendar._TT["TT_DATE_FORMAT"];
230	this.isPopup = true;
231	this.weekNumbers = true;
232	this.firstDayOfWeek = typeof firstDayOfWeek == "number" ? firstDayOfWeek : Calendar._FD; // 0 for Sunday, 1 for Monday, etc.
233	this.showsOtherMonths = false;
234	this.dateStr = dateStr;
235
236	var yearArray = this.dateStr.toString().split(" ");
237	var year = yearArray[yearArray.length - 1];
238	if (parseInt(year, 10) < 1911) {
239	    this.dateStr = "";
240	    var i = 0;
241	    for (i = 0; i < yearArray.length - 1; i++) {
242	        this.dateStr = this.dateStr + yearArray[i] + " ";
243	    }
244	    this.dateStr = this.dateStr + (parseInt(year, 10) + 1911).toString();
245	    alert(this.dateStr);
246	}
247
248	this.ar_days = null;
249	this.showsTime = false;
250	this.time24 = true;
251	this.yearStep = 2;
252	this.hiliteToday = true;
253	this.multiple = null;
254	// HTML elements
255	this.table = null;
256	this.element = null;
257	this.tbody = null;
258	this.firstdayname = null;
259	// Combo boxes
260	this.monthsCombo = null;
261	this.yearsCombo = null;
262	this.hilitedMonth = null;
263	this.activeMonth = null;
264	this.hilitedYear = null;
265	this.activeYear = null;
266	// Information
267	this.dateClicked = false;
268
269	// one-time initializations
270	if (typeof Calendar._SDN == "undefined") {
271		// table of short day names
272		if (typeof Calendar._SDN_len == "undefined")
273			Calendar._SDN_len = 3;
274		var ar = new Array();
275		for (var i = 8; i > 0;) {
276			ar[--i] = Calendar._DN[i].substr(0, Calendar._SDN_len);
277		}
278		Calendar._SDN = ar;
279		// table of short month names
280		if (typeof Calendar._SMN_len == "undefined")
281			Calendar._SMN_len = 3;
282		ar = new Array();
283		for (var i = 12; i > 0;) {
284			ar[--i] = Calendar._MN[i].substr(0, Calendar._SMN_len);
285		}
286		Calendar._SMN = ar;
287	}
288};
289
290// ** constants
291
292/// "static", needed for event handlers.
293Calendar._C = null;
294
295/// detect a special case of "web browser"
296Calendar.is_ie = ( /msie/i.test(navigator.userAgent) &&
297		   !/opera/i.test(navigator.userAgent) );
298
299Calendar.is_ie5 = ( Calendar.is_ie && /msie 5\.0/i.test(navigator.userAgent) );
300
301/// detect Opera browser
302Calendar.is_opera = /opera/i.test(navigator.userAgent);
303
304/// detect KHTML-based browsers
305Calendar.is_khtml = /Konqueror|Safari|KHTML/i.test(navigator.userAgent);
306
307// BEGIN: UTILITY FUNCTIONS; beware that these might be moved into a separate
308//        library, at some point.
309
310Calendar.getAbsolutePos = function(el) {
311	var SL = 0, ST = 0;
312	var is_div = /^div$/i.test(el.tagName);
313	if (is_div && el.scrollLeft)
314		
315		SL = el.scrollLeft;
316	if (is_div && el.scrollTop)
317		ST = el.scrollTop;
318	var r = { x: el.offsetLeft - SL, y: el.offsetTop - ST };
319	if (el.offsetParent) {
320		var tmp = this.getAbsolutePos(el.offsetParent);
321		r.x += tmp.x;
322		r.y += tmp.y;
323	}
324	return r;
325};
326
327Calendar.isRelated = function (el, evt) {
328	var related = evt.relatedTarget;
329	if (!related) {
330		var type = evt.type;
331		if (type == "mouseover") {
332			related = evt.fromElement;
333		} else if (type == "mouseout") {
334			related = evt.toElement;
335		}
336	}
337	while (related) {
338		if (related == el) {
339			return true;
340		}
341		related = related.parentNode;
342	}
343	return false;
344};
345
346Calendar.removeClass = function(el, className) {
347	if (!(el && el.className)) {
348		return;
349	}
350	var cls = el.className.split(" ");
351	var ar = new Array();
352	for (var i = cls.length; i > 0;) {
353		if (cls[--i] != className) {
354			ar[ar.length] = cls[i];
355		}
356	}
357	el.className = ar.join(" ");
358};
359
360Calendar.addClass = function(el, className) {
361	Calendar.removeClass(el, className);
362	el.className += " " + className;
363};
364
365// FIXME: the following 2 functions totally suck, are useless and should be replaced immediately.
366Calendar.getElement = function(ev) {
367	var f = Calendar.is_ie ? window.event.srcElement : ev.currentTarget;
368	while (f.nodeType != 1 || /^div$/i.test(f.tagName))
369		f = f.parentNode;
370	return f;
371};
372
373Calendar.getTargetElement = function(ev) {
374	var f = Calendar.is_ie ? window.event.srcElement : ev.target;
375	while (f.nodeType != 1)
376		f = f.parentNode;
377	return f;
378};
379
380Calendar.stopEvent = function(ev) {
381	ev || (ev = window.event);
382	if (Calendar.is_ie) {
383		ev.cancelBubble = true;
384		ev.returnValue = false;
385	} else {
386		ev.preventDefault();
387		ev.stopPropagation();
388	}
389	return false;
390};
391
392Calendar.addEvent = function(el, evname, func) {
393	if (el.attachEvent) { // IE
394		el.attachEvent("on" + evname, func);
395	} else if (el.addEventListener) { // Gecko / W3C
396		el.addEventListener(evname, func, true);
397	} else {
398		el["on" + evname] = func;
399	}
400};
401
402Calendar.removeEvent = function(el, evname, func) {
403	if (el.detachEvent) { // IE
404		el.detachEvent("on" + evname, func);
405	} else if (el.removeEventListener) { // Gecko / W3C
406		el.removeEventListener(evname, func, true);
407	} else {
408		el["on" + evname] = null;
409	}
410};
411
412Calendar.createElement = function(type, parent) {
413	var el = null;
414	if (document.createElementNS) {
415		// use the XHTML namespace; IE won't normally get here unless
416		// _they_ "fix" the DOM2 implementation.
417		el = document.createElementNS("http://www.w3.org/1999/xhtml", type);
418	} else {
419		el = document.createElement(type);
420	}
421	if (typeof parent != "undefined") {
422		parent.appendChild(el);
423	}
424	return el;
425};
426
427// END: UTILITY FUNCTIONS
428
429// BEGIN: CALENDAR STATIC FUNCTIONS
430
431/** Internal -- adds a set of events to make some element behave like a button. */
432Calendar._add_evs = function(el) {
433	with (Calendar) {
434		addEvent(el, "mouseover", dayMouseOver);
435		addEvent(el, "mousedown", dayMouseDown);
436		addEvent(el, "mouseout", dayMouseOut);
437		if (is_ie) {
438			addEvent(el, "dblclick", dayMouseDblClick);
439			el.setAttribute("unselectable", true);
440		}
441	}
442};
443
444Calendar.findMonth = function(el) {
445	if (typeof el.month != "undefined") {
446		return el;
447	} else if (typeof el.parentNode.month != "undefined") {
448		return el.parentNode;
449	}
450	return null;
451};
452
453Calendar.findYear = function(el) {
454	if (typeof el.year != "undefined") {
455		return el;
456	} else if (typeof el.parentNode.year != "undefined") {
457		return el.parentNode;
458	}
459	return null;
460};
461
462Calendar.showMonthsCombo = function () {
463	var cal = Calendar._C;
464	if (!cal) {
465		return false;
466	}
467	var cal = cal;
468	var cd = cal.activeDiv;
469	var mc = cal.monthsCombo;
470	if (cal.hilitedMonth) {
471		Calendar.removeClass(cal.hilitedMonth, "hilite");
472	}
473	if (cal.activeMonth) {
474		Calendar.removeClass(cal.activeMonth, "active");
475	}
476	var mon = cal.monthsCombo.getElementsByTagName("div")[cal.date.getMonth()];
477	Calendar.addClass(mon, "active");
478	cal.activeMonth = mon;
479	var s = mc.style;
480	s.display = "block";
481	if (cd.navtype < 0)
482		s.left = cd.offsetLeft + "px";
483	else {
484		var mcw = mc.offsetWidth;
485		if (typeof mcw == "undefined")
486			// Konqueror brain-dead techniques
487			mcw = 50;
488		s.left = (cd.offsetLeft + cd.offsetWidth - mcw) + "px";
489	}
490	s.top = (cd.offsetTop + cd.offsetHeight) + "px";
491};
492
493Calendar.showYearsCombo = function (fwd) {
494	var cal = Calendar._C;
495	if (!cal) {
496		return false;
497	}
498	var cal = cal;
499	var cd = cal.activeDiv;
500	var yc = cal.yearsCombo;
501	if (cal.hilitedYear) {
502		Calendar.removeClass(cal.hilitedYear, "hilite");
503	}
504	if (cal.activeYear) {
505		Calendar.removeClass(cal.activeYear, "active");
506	}
507	cal.activeYear = null;
508	var Y = cal.date.getFullYear() + (fwd ? 1 : -1);
509	var yr = yc.firstChild;
510	var show = false;
511	for (var i = 12; i > 0; --i) {
512		if (Y >= cal.minYear && Y <= cal.maxYear) {
513			yr.innerHTML = Y-1911;	//topcat
514			yr.year = Y;	
515			yr.style.display = "block";
516			show = true;
517		} else {
518			yr.style.display = "none";
519		}
520		yr = yr.nextSibling;
521		Y += fwd ? cal.yearStep : -cal.yearStep;
522	}
523	if (show) {
524		var s = yc.style;
525		s.display = "block";
526		if (cd.navtype < 0)
527			s.left = cd.offsetLeft + "px";
528		else {
529			var ycw = yc.offsetWidth;
530			if (typeof ycw == "undefined")
531				// Konqueror brain-dead techniques
532				ycw = 50;
533			s.left = (cd.offsetLeft + cd.offsetWidth - ycw) + "px";
534		}
535		s.top = (cd.offsetTop + cd.offsetHeight) + "px";
536	}
537};
538
539// event handlers
540
541Calendar.tableMouseUp = function(ev) {
542	var cal = Calendar._C;
543	if (!cal) {
544		return false;
545	}
546	if (cal.timeout) {
547		clearTimeout(cal.timeout);
548	}
549	var el = cal.activeDiv;
550	if (!el) {
551		return false;
552	}
553	var target = Calendar.getTargetElement(ev);
554	ev || (ev = window.event);
555	Calendar.removeClass(el, "active");
556	if (target == el || target.parentNode == el) {
557		Calendar.cellClick(el, ev);
558	}
559	var mon = Calendar.findMonth(target);
560	var date = null;
561	if (mon) {
562		date = new Date(cal.date);
563		if (mon.month != date.getMonth()) {
564			date.setMonth(mon.month);
565			cal.setDate(date);
566			cal.dateClicked = false;
567			cal.callHandler();
568		}
569	} else {
570		var year = Calendar.findYear(target);
571		if (year) {
572			date = new Date(cal.date);
573			if (year.year != date.getFullYear()) {
574				date.setFullYear(year.year);
575				cal.setDate(date);
576				cal.dateClicked = false;
577				cal.callHandler();
578			}
579		}
580	}
581	with (Calendar) {
582		removeEvent(document, "mouseup", tableMouseUp);
583		removeEvent(document, "mouseover", tableMouseOver);
584		removeEvent(document, "mousemove", tableMouseOver);
585		cal._hideCombos();
586		_C = null;
587		return stopEvent(ev);
588	}
589};
590
591Calendar.tableMouseOver = function (ev) {
592	var cal = Calendar._C;
593	if (!cal) {
594		return;
595	}
596	var el = cal.activeDiv;
597	var target = Calendar.getTargetElement(ev);
598	if (target == el || target.parentNode == el) {
599		Calendar.addClass(el, "hilite active");
600		Calendar.addClass(el.parentNode, "rowhilite");
601	} else {
602		if (typeof el.navtype == "undefined" || (el.navtype != 50 && (el.navtype == 0 || Math.abs(el.navtype) > 2)))
603			Calendar.removeClass(el, "active");
604		Calendar.removeClass(el, "hilite");
605		Calendar.removeClass(el.parentNode, "rowhilite");
606	}
607	ev || (ev = window.event);
608	if (el.navtype == 50 && target != el) {
609		var pos = Calendar.getAbsolutePos(el);
610		var w = el.offsetWidth;
611		var x = ev.clientX;
612		var dx;
613		var decrease = true;
614		if (x >
614 pos.x + w) {
615			dx = x - pos.x - w;
616			decrease = false;
617		} else
618			dx = pos.x - x;
619
620		if (dx < 0) dx = 0;
621		var range = el._range;
622		var current = el._current;
623		var count = Math.floor(dx / 10) % range.length;
624		for (var i = range.length; --i >= 0;)
625			if (range[i] == current)
626				break;
627		while (count-- > 0)
628			if (decrease) {
629				if (--i < 0)
630					i = range.length - 1;
631			} else if ( ++i >= range.length )
632				i = 0;
633		var newval = range[i];
634		el.innerHTML = newval;
635
636		cal.onUpdateTime();
637	}
638	var mon = Calendar.findMonth(target);
639	if (mon) {
640		if (mon.month != cal.date.getMonth()) {
641			if (cal.hilitedMonth) {
642				Calendar.removeClass(cal.hilitedMonth, "hilite");
643			}
644			Calendar.addClass(mon, "hilite");
645			cal.hilitedMonth = mon;
646		} else if (cal.hilitedMonth) {
647			Calendar.removeClass(cal.hilitedMonth, "hilite");
648		}
649	} else {
650		if (cal.hilitedMonth) {
651			Calendar.removeClass(cal.hilitedMonth, "hilite");
652		}
653		var year = Calendar.findYear(target);
654		if (year) {
655			if (year.year != cal.date.getFullYear()) {
656				if (cal.hilitedYear) {
657					Calendar.removeClass(cal.hilitedYear, "hilite");
658				}
659				Calendar.addClass(year, "hilite");
660				cal.hilitedYear = year;
661			} else if (cal.hilitedYear) {
662				Calendar.removeClass(cal.hilitedYear, "hilite");
663			}
664		} else if (cal.hilitedYear) {
665			Calendar.removeClass(cal.hilitedYear, "hilite");
666		}
667	}
668	return Calendar.stopEvent(ev);
669};
670
671Calendar.tableMouseDown = function (ev) {
672	if (Calendar.getTargetElement(ev) == Calendar.getElement(ev)) {
673		return Calendar.stopEvent(ev);
674	}
675};
676
677Calendar.calDragIt = function (ev) {
678	var cal = Calendar._C;
679	if (!(cal && cal.dragging)) {
680		return false;
681	}
682	var posX;
683	var posY;
684	if (Calendar.is_ie) {
685		posY = window.event.clientY + document.body.scrollTop;
686		posX = window.event.clientX + document.body.scrollLeft;
687	} else {
688		posX = ev.pageX;
689		posY = ev.pageY;
690	}
691	cal.hideShowCovered();
692	var st = cal.element.style;
693	st.left = (posX - cal.xOffs) + "px";
694	st.top = (posY - cal.yOffs) + "px";
695	return Calendar.stopEvent(ev);
696};
697
698Calendar.calDragEnd = function (ev) {
699	var cal = Calendar._C;
700	if (!cal) {
701		return false;
702	}
703	cal.dragging = false;
704	with (Calendar) {
705		removeEvent(document, "mousemove", calDragIt);
706		removeEvent(document, "mouseup", calDragEnd);
707		tableMouseUp(ev);
708	}
709	cal.hideShowCovered();
710};
711
712Calendar.dayMouseDown = function(ev) {
713	var el = Calendar.getElement(ev);
714	if (el.disabled) {
715		return false;
716	}
717	var cal = el.calendar;
718	cal.activeDiv = el;
719	Calendar._C = cal;
720	if (el.navtype != 300) with (Calendar) {
721		if (el.navtype == 50) {
722			el._current = el.innerHTML;
723			addEvent(document, "mousemove", tableMouseOver);
724		} else
725			addEvent(document, Calendar.is_ie5 ? "mousemove" : "mouseover", tableMouseOver);
726		addClass(el, "hilite active");
727		addEvent(document, "mouseup", tableMouseUp);
728	} else if (cal.isPopup) {
729		cal._dragStart(ev);
730	}
731	if (el.navtype == -1 || el.navtype == 1) {
732		if (cal.timeout) clearTimeout(cal.timeout);
733		cal.timeout = setTimeout("Calendar.showMonthsCombo()", 250);
734	} else if (el.navtype == -2 || el.navtype == 2) {
735		if (cal.timeout) clearTimeout(cal.timeout);
736		cal.timeout = setTimeout((el.navtype > 0) ? "Calendar.showYearsCombo(true)" : "Calendar.showYearsCombo(false)", 250);
737	} else {
738		cal.timeout = null;
739	}
740	return Calendar.stopEvent(ev);
741};
742
743Calendar.dayMouseDblClick = function(ev) {
744	Calendar.cellClick(Calendar.getElement(ev), ev || window.event);
745	if (Calendar.is_ie) {
746		document.selection.empty();
747	}
748};
749
750Calendar.dayMouseOver = function(ev) {
751	var el = Calendar.getElement(ev);
752	if (Calendar.isRelated(el, ev) || Calendar._C || el.disabled) {
753		return false;
754	}
755	if (el.ttip) {
756		if (el.ttip.substr(0, 1) == "_") {
757			el.ttip = el.caldate.print(el.calendar.ttDateFormat) + el.ttip.substr(1);
758		}
759		el.calendar.tooltips.innerHTML = el.ttip;
760	}
761	if (el.navtype != 300) {
762		Calendar.addClass(el, "hilite");
763		if (el.caldate) {
764			Calendar.addClass(el.parentNode, "rowhilite");
765		}
766	}
767	return Calendar.stopEvent(ev);
768};
769
770Calendar.dayMouseOut = function(ev) {
771	with (Calendar) {
772		var el = getElement(ev);
773		if (isRelated(el, ev) || _C || el.disabled)
774			return false;
775		removeClass(el, "hilite");
776		if (el.caldate)
777			removeClass(el.parentNode, "rowhilite");
778		if (el.calendar)
779			el.calendar.tooltips.innerHTML = _TT["SEL_DATE"];
780		return stopEvent(ev);
781	}
782};
783
784/**
785 *  A generic "click" handler :) handles all types of buttons defined in this
786 *  calendar.
787 */
788Calendar.cellClick = function(el, ev) {
789	var cal = el.calendar;
790	var closing = false;
791	var newdate = false;
792	var date = null;
793	if (typeof el.navtype == "undefined") {
794		if (cal.currentDateEl) {
795			Calendar.removeClass(cal.currentDateEl, "selected");
796			Calendar.addClass(el, "selected");
797			closing = (cal.currentDateEl == el);
798			if (!closing) {
799				cal.currentDateEl = el;
800			}
801		}
802		cal.date.setDateOnly(el.caldate);
803		date = cal.date;
804		var other_month = !(cal.dateClicked = !el.otherMonth);
805		if (!other_month && !cal.currentDateEl)
806			cal._toggleMultipleDate(new Date(date));
807		else
808			newdate = !el.disabled;
809		// a date was clicked
810		if (other_month)
811			cal._init(cal.firstDayOfWeek, date);
812	} else {
813		if (el.navtype == 200) {
814			Calendar.removeClass(el, "hilite");
815			cal.callCloseHandler();
816			return;
817		}
818		date = new Date(cal.date);
819		if (el.navtype == 0)
820			date.setDateOnly(new Date()); // TODAY
821		// unless "today" was clicked, we assume no date was clicked so
822		// the selected handler will know not to close the calenar when
823		// in single-click mode.
824		// cal.dateClicked = (el.navtype == 0);
825		cal.dateClicked = false;
826		var year = date.getFullYear();
827		    if (parseInt(year, 10) < 1911) {
828		        year += 1911;
829		    }
830		var mon = date.getMonth();
831		function setMonth(m) {
832			var day = date.getDate();
833			var max = date.getMonthDays(m);
834			if (day > max) {
835				date.setDate(max);
836			}
837			date.setMonth(m);
838		};
839		switch (el.navtype) {
840		    case 400:
841			Calendar.removeClass(el, "hilite");
842			var text = Calendar._TT["ABOUT"];
843			if (typeof text != "undefined") {
844				text += cal.showsTime ? Calendar._TT["ABOUT_TIME"] : "";
845			} else {
846				// FIXME: this should be removed as soon as lang files get updated!
847				text = "Help and about box text is not translated into this language.\n" +
848					"If you know this language and you feel generous please update\n" +
849					"the corresponding file in \"lang\" subdir to match calendar-en.js\n" +
850					"and send it back to <[email protected]> to get it into the distribution  ;-)\n\n" +
851					"Thank you!\n" +
852					"http://dynarch.com/mishoo/calendar.epl\n";
853			}
854			alert(text);
855			return;
856		    case -2:
857			if (year > cal.minYear) {
858				date.setFullYear(year - 1);
859			}
860			break;
861		    case -1:
862			if (mon > 0) {
863				setMonth(mon - 1);
864			} else if (year-- > cal.minYear) {
865				date.setFullYear(year);
866				setMonth(11);
867			}
868			break;
869		    case 1:
870			if (mon < 11) {
871				setMonth(mon + 1);
872			} else if (year < cal.maxYear) {
873				date.setFullYear(year + 1);
874				setMonth(0);
875			}
876			break;
877		    case 2:
878			if (year < cal.maxYear) {
879				date.setFullYear(year + 1);
880			}
881			break;
882		    case 100:
883			cal.setFirstDayOfWeek(el.fdow);
884			return;
885		    case 50:
886			var range = el._range;
887			var current = el.innerHTML;
888			for (var i = range.length; --i >= 0;)
889				if (range[i] == current)
890					break;
891			if (ev && ev.shiftKey) {
892				if (--i < 0)
893					i = range.length - 1;
894			} else if ( ++i >= range.length )
895				i = 0;
896			var newval = range[i];
897			el.innerHTML = newval;
898			cal.onUpdateTime();
899			return;
900		    case 0:
901			// TODAY will bring us here
902			if ((typeof cal.getDateStatus == "function") &&
903			    cal.getDateStatus(date, date.getFullYear(), date.getMonth(), date.getDate())) {
904				return false;
905			}
906			break;
907		}
908		if (!date.equalsTo(cal.date)) {
909			cal.setDate(date);
910			newdate = true;
911		} else if (el.navtype == 0)
912			newdate = closing = true;
913	}
914	if (newdate) {
915		ev && cal.callHandler();
916	}
917	if (closing) {
918		Calendar.removeClass(el, "hilite");
919		ev && cal.callCloseHandler();
920	}
921};
922
923// END: CALENDAR STATIC FUNCTIONS
924
925// BEGIN: CALENDAR OBJECT FUNCTIONS
926/**
927 *  This function creates the calendar inside the given parent.  If _par is
928 *  null than it creates a popup calendar inside the BODY element.  If _par is
929 *  an element, be it BODY, then it creates a non-popup calendar (still
930 *  hidden).  Some properties need to be set before calling this function.
931 */
932Calendar.prototype.create = function (_par) {
933    var parent = null;
934    if (!_par) {
935        // default parent is the document body, in which case we create
936        // a popup calendar.
937        parent = document.getElementsByTagName("body")[0];
938        this.isPopup = true;
939    } else {
940        parent = _par;
941        this.isPopup = false;
942    }
943
944    var yearArray = this.dateStr.toString().split(" ");
945    var year = yearArray[yearArray.length - 1];
946    if (parseInt(year, 10) < 1911) {
947        this.dateStr = "";
948        var i = 0;
949        for (i = 0; i < yearArray.length - 1; i++) {
950            this.dateStr = this.dateStr + yearArray[i] + " ";
951        }
952        this.dateStr = this.dateStr + (parseInt(year, 10) + 1911).toString();
953        //alert(this.dateStr);
954    }
955
956    this.date = this.dateStr ? new Date(this.dateStr) : new Date();
957
958    var table = Calendar.createElement("table");
959    this.table = table;
960    table.cellSpacing = 0;
961    table.cellPadding = 0;
962    table.calendar = this;
963    Calendar.addEvent(table, "mousedown", Calendar.tableMouseDown);
964
965    var div = Calendar.createElement("div");
966    this.element = div;
967    div.className = "calendar";
968    if (this.isPopup) {
969        div.style.position = "absolute";
970        div.style.display = "none";
971    }
972    div.appendChild(table);
973
974    var thead = Calendar.createElement("thead", table);
975    var cell = null;
976    var row = null;
977
978    var cal = this;
979    var hh = function (text, cs, navtype) {
980        cell = Calendar.createElement("td", row);
981        cell.colSpan = cs;
982        cell.className = "button";
983        if (navtype != 0 && Math.abs(navtype) <= 2)
984            cell.className += " nav";
985        Calendar._add_evs(cell);
986        cell.calendar = cal;
987        cell.navtype = navtype;
988        cell.innerHTML = "<div unselectable='on'>
988" + text + "</div>";
989        return cell;
990    };
991
992    row = Calendar.createElement("tr", thead);
993    var title_length = 6;
994    (this.isPopup) && --title_length;
995    (this.weekNumbers) && ++title_length;
996
997    hh("?", 1, 400).ttip = Calendar._TT["INFO"];
998    this.title = hh("", title_length, 300);
999    this.title.className = "title";
1000    if (this.isPopup) {
1001        this.title.ttip = Calendar._TT["DRAG_TO_MOVE"];
1002        this.title.style.cursor = "move";
1003        hh("&#x00d7;", 1, 200).ttip = Calendar._TT["CLOSE"];
1004    }
1005
1006    row = Calendar.createElement("tr", thead);
1007    row.className = "headrow";
1008
1009    this._nav_py = hh("&#x00ab;", 1, -2);
1010    this._nav_py.ttip = Calendar._TT["PREV_YEAR"];
1011
1012    this._nav_pm = hh("&#x2039;", 1, -1);
1013    this._nav_pm.ttip = Calendar._TT["PREV_MONTH"];
1014
1015    this._nav_now = hh(Calendar._TT["TODAY"], this.weekNumbers ? 4 : 3, 0);
1016    this._nav_now.ttip = Calendar._TT["GO_TODAY"];
1017
1018    this._nav_nm = hh("&#x203a;", 1, 1);
1019    this._nav_nm.ttip = Calendar._TT["NEXT_MONTH"];
1020
1021    this._nav_ny = hh("&#x00bb;", 1, 2);
1022    this._nav_ny.ttip = Calendar._TT["NEXT_YEAR"];
1023
1024    // day names
1025    row = Calendar.createElement("tr", thead);
1026    row.className = "daynames";
1027    if (this.weekNumbers) {
1028        cell = Calendar.createElement("td", row);
1029        cell.className = "name wn";
1030        cell.innerHTML = Calendar._TT["WK"];
1031    }
1032    for (var i = 7; i > 0; --i) {
1033        cell = Calendar.createElement("td", row);
1034        if (!i) {
1035            cell.navtype = 100;
1036            cell.calendar = this;
1037            Calendar._add_evs(cell);
1038        }
1039    }
1040    this.firstdayname = (this.weekNumbers) ? row.firstChild.nextSibling : row.firstChild;
1041    this._displayWeekdays();
1042
1043    var tbody = Calendar.createElement("tbody", table);
1044    this.tbody = tbody;
1045
1046    for (i = 6; i > 0; --i) {
1047        row = Calendar.createElement("tr", tbody);
1048        if (this.weekNumbers) {
1049            cell = Calendar.createElement("td", row);
1050        }
1051        for (var j = 7; j > 0; --j) {
1052            cell = Calendar.createElement("td", row);
1053            cell.calendar = this;
1054            Calendar._add_evs(cell);
1055        }
1056    }
1057
1058    if (this.showsTime) {
1059        row = Calendar.createElement("tr", tbody);
1060        row.className = "time";
1061
1062        cell = Calendar.createElement("td", row);
1063        cell.className = "time";
1064        cell.colSpan = 2;
1065        cell.innerHTML = Calendar._TT["TIME"] || "&nbsp;";
1066
1067        cell = Calendar.createElement("td", row);
1068        cell.className = "time";
1069        cell.colSpan = this.weekNumbers ? 4 : 3;
1070
1071        (function () {
1072            function makeTimePart(className, init, range_start, range_end) {
1073                var part = Calendar.createElement("span", cell);
1074                part.className = className;
1075                part.innerHTML = init;
1076                part.calendar = cal;
1077                part.ttip = Calendar._TT["TIME_PART"];
1078                part.navtype = 50;
1079                part._range = [];
1080                if (typeof range_start != "number")
1081                    part._range = range_start;
1082                else {
1083                    for (var i = range_start; i <= range_end; ++i) {
1084                        var txt;
1085                        if (i < 10 && range_end >= 10) txt = '0' + i;
1086                        else txt = '' + i;
1087                        part._range[part._range.length] = txt;
1088                    }
1089                }
1090                Calendar._add_evs(part);
1091                return part;
1092            };
1093            var hrs = cal.date.getHours();
1094            var mins = cal.date.getMinutes();
1095            var t12 = !cal.time24;
1096            var pm = (hrs > 12);
1097            if (t12 && pm) hrs -= 12;
1098            var H = makeTimePart("hour", hrs, t12 ? 1 : 0, t12 ? 12 : 23);
1099            var span = Calendar.createElement("span", cell);
1100            span.innerHTML = ":";
1101            span.className = "colon";
1102            var M = makeTimePart("minute", mins, 0, 59);
1103            var AP = null;
1104            cell = Calendar.createElement("td", row);
1105            cell.className = "time";
1106            cell.colSpan = 2;
1107            if (t12)
1108                AP = makeTimePart("ampm", pm ? "pm" : "am", ["am", "pm"]);
1109            else
1110                cell.innerHTML = "&nbsp;";
1111
1112            cal.onSetTime = function () {
1113                var pm, hrs = this.date.getHours(),
1114					mins = this.date.getMinutes();
1115                if (t12) {
1116                    pm = (hrs >= 12);
1117                    if (pm) hrs -= 12;
1118                    if (hrs == 0) hrs = 12;
1119                    AP.innerHTML = pm ? "pm" : "am";
1120                }
1121                H.innerHTML = (hrs < 10) ? ("0" + hrs) : hrs;
1122                M.innerHTML = (mins < 10) ? ("0" + mins) : mins;
1123            };
1124
1125            cal.onUpdateTime = function () {
1126                var date = this.date;
1127                var h = parseInt(H.innerHTML, 10);
1128                if (t12) {
1129                    if (/pm/i.test(AP.innerHTML) && h < 12)
1130                        h += 12;
1131                    else if (/am/i.test(AP.innerHTML) && h == 12)
1132                        h = 0;
1133                }
1134                var d = date.getDate();
1135                var m = date.getMonth();
1136                var y = date.getFullYear();
1137                date.setHours(h);
1138                date.setMinutes(parseInt(M.innerHTML, 10));
1139                date.setFullYear(y);
1140                date.setMonth(m);
1141                date.setDate(d);
1142                this.dateClicked = false;
1143                this.callHandler();
1144            };
1145        })();
1146    } else {
1147        this.onSetTime = this.onUpdateTime = function () { };
1148    }
1149
1150    var tfoot = Calendar.createElement("tfoot", table);
1151
1152    row = Calendar.createElement("tr", tfoot);
1153    row.className = "footrow";
1154
1155    cell = hh(Calendar._TT["SEL_DATE"], this.weekNumbers ? 8 : 7, 300);
1156    cell.className = "ttip";
1157    if (this.isPopup) {
1158        cell.ttip = Calendar._TT["DRAG_TO_MOVE"];
1159        cell.style.cursor = "move";
1160    }
1161    this.tooltips = cell;
1162
1163    div = Calendar.createElement("div", this.element);
1164    this.monthsCombo = div;
1165    div.className = "combo";
1166    for (i = 0; i < Calendar._MN.length; ++i) {
1167        var mn = Calendar.createElement("div");
1168        mn.className = Calendar.is_ie ? "label-IEfix" : "label";
1169        mn.month = i;
1170        mn.innerHTML = Calendar._SMN[i];
1171        div.appendChild(mn);
1172    }
1173
1174    div = Calendar.createElement("div", this.element);
1175    this.yearsCombo = div;
1176    div.className = "combo";
1177    for (i = 12; i > 0; --i) {
1178        var yr = Calendar.createElement("div");
1179        yr.className = Calendar.is_ie ? "label-IEfix" : "label";
1180        div.appendChild(yr);
1181    }
1182
1183    this._init(this.firstDayOfWeek, this.date);
1184    parent.appendChild(this.element);
1185};
1186
1187/** keyboard navigation, only for popup calendars */
1188Calendar._keyEvent = function(ev) {
1189	var cal = window._dynarch_popupCalendar;
1190	if (!cal || cal.multiple)
1191		return false;
1192	(Calendar.is_ie) && (ev = window.event);
1193	var act = (Calendar.is_ie || ev.type == "keypress"),
1194		K = ev.keyCode;
1195	if (ev.ctrlKey) {
1196		switch (K) {
1197		    case 37: // KEY left
1198			act && Calendar.cellClick(cal._nav_pm);
1199			break;
1200		    case 38: // KEY up
1201			act && Calendar.cellClick(cal._nav_py);
1202			break;
1203		    case 39: // KEY right
1204			act && Calendar.cellClick(cal._nav_nm);
1205			break;
1206		    case 40: // KEY down
1207			act && Calendar.cellClick(cal._nav_ny);
1208			break;
1209		    default:
1210			return false;
1211		}
1212	} else switch (K) {
1213	    case 32: // KEY space (now)
1214		Calendar.cellClick(cal._nav_now);
1215		break;
1216	    case 27: // KEY esc
1217		act && cal.callCloseHandler();
1218		break;
1219	    case 37: // KEY left
1220	    case 38: // KEY up
1221	    case 39: // KEY right
1222	    case 40: // KEY down
1223		if (act) {
1224			var prev, x, y, ne, el, step;
1225			prev = K == 37 || K == 38;
1226			step = (K == 37 || K == 39) ? 1 : 7;
1227			function setVars() {
1228				el = cal.currentDateEl;
1229				var p = el.pos;
1230				x = p & 15;
1231				y = p >> 4;
1232				ne = cal.ar_days[y][x];
1233			};setVars();
1234			function prevMonth() {
1235				var date = new Date(cal.date);
1236				date.setDate(date.getDate() - step);
1237				cal.setDate(date);
1238			};
1239			function nextMonth() {
1240				var date = new Date(cal.date);
1241				date.setDate(date.getDate() + step);
1242				cal.setDate(date);
1243			};
1244			while (1) {
1245				switch (K) {
1246				    case 37: // KEY left
1247					if (--x >= 0)
1248						ne = cal.ar_days[y][x];
1249					else {
1250						x = 6;
1251						K = 38;
1252						continue;
1253					}
1254					break;
1255				    case 38: // KEY up
1256					if (--y >= 0)
1257						ne = cal.ar_days[y][x];
1258					else {
1259						prevMonth();
1260						setVars();
1261					}
1262					break;
1263				    case 39: // KEY right
1264					if (++x < 7)
1265						ne = cal.ar_days[y][x];
1266					else {
1267						x = 0;
1268						K = 40;
1269						continue;
1270					}
1271					break;
1272				    case 40: // KEY down
1273					if (++y < cal.ar_days.length)
1274						ne = cal.ar_days[y][x];
1275					else {
1276						nextMonth();
1277						setVars();
1278					}
1279					break;
1280				}
1281				break;
1282			}
1283			if (ne) {
1284				if (!ne.disabled)
1285					Calendar.cellClick(ne);
1286				else if (prev)
1287					prevMonth();
1288				else
1289					nextMonth();
1290			}
1291		}
1292		break;
1293	    case 13: // KEY enter
1294		if (act)
1295			Calendar.cellClick(cal.currentDateEl, ev);
1296		break;
1297	    default:
1298		return false;
1299	}
1300	return Calendar.stopEvent(ev);
1301};
1302
1303/**
1304 *  (RE)Initializes the calendar to the given date and firstDayOfWeek
1305 */
1306Calendar.prototype._init = function (firstDayOfWeek, date) {
1307    var today = new Date(),
1308		TY = today.getFullYear(),
1309		TM = today.getMonth(),
1310		TD = today.getDate();
1311    this.table.style.visibility = "hidden";
1312    var year = date.getFullYear();
1313    if (parseInt(year, 10) < 1911) {
1314        year += 1911;
1315    }
1316    if (year < this.minYear) {
1317        year = this.minYear;
1318        date.setFullYear(year);
1319    } else if (year > this.maxYear) {
1320        year = this.maxYear;
1321        date.setFullYear(year);
1322    }
1323    this.firstDayOfWeek = firstDayOfWeek;
1324    this.date = new Date(date);
1325    var month = date.getMonth();
1326    var mday = date.getDate();
1327    var no_days = date.getMonthDays();
1328
1329    // calendar voodoo for computing the first day that would actually be
1330    // displayed in the calendar, even if it's from the previous month.
1331    // WARNING: this is magic. ;-)
1332    date.setDate(1);
1333    var day1 = (date.getDay() - this.firstDayOfWeek) % 7;
1334    if (day1 < 0)
1335        day1 += 7;
1336    date.setDate(-day1);
1337    date.setDate(date.getDate() + 1);
1338
1339    var row = this.tbody.firstChild;
1340    var MN = Calendar._SMN[month];
1341    var ar_days = this.ar_days = new Array();
1342    var weekend = Calendar._TT["WEEKEND"];
1343    var dates = this.multiple ? (this.datesCells = {}) : null;
1344    for (var i = 0; i < 6; ++i, row = row.nextSibling) {
1345        var cell = row.firstChild;
1346        if (this.weekNumbers) {
1347            cell.className = "day wn";
1348            cell.innerHTML = date.getWeekNumber();
1349            cell = cell.nextSibling;
1350        }
1351        row.className = "daysrow";
1352        var hasdays = false, iday, dpos = ar_days[i] = [];
1353        for (var j = 0; j < 7; ++j, cell = cell.nextSibling, date.setDate(iday + 1)) {
1354            iday = date.getDate();
1355            var wday = date.getDay();
1356            cell.className = "day";
1357            cell.pos = i << 4 | j;
1358            dpos[j] = cell;
1359            var current_month = (date.getMonth() == month);
1360            if (!current_month) {
1361                if (this.showsOtherMonths) {
1362                    cell.className += " othermonth";
1363                    cell.otherMonth = true;
1364                } else {
1365                    cell.className = "emptycell";
1366                    cell.innerHTML = "&nbsp;";
1367                    cell.disabled = true;
1368                    continue;
1369                }
1370            } else {
1371                cell.otherMonth = false;
1372                hasdays = true;
1373            }
1374            cell.disabled = false;
1375            cell.innerHTML = this.getDateText ? this.getDateText(date, iday) : iday;
1376            if (dates)
1377                dates[date.print("%Y%m%d")] = cell;
1378            if (this.getDateStatus) {
1379                var status = this.getDateStatus(date, year, month, iday);
1380                if (this.getDateToolTip) {
1381                    var toolTip = this.getDateToolTip(date, year, month, iday);
1382                    if (toolTip)
1383                        cell.title = toolTip;
1384                }
1385                if (status === true) {
1386                    cell.className += " disabled";
1387                    cell.disabled = true;
1388                } else {
1389                    if (/disabled/i.test(status))
1390                        cell.disabled = true;
1391                    cell.className += " " + status;
1392                }
1393            }
1394            if (!cell.disabled) {
1395                cell.caldate = new Date(date);
1396                cell.ttip = "_";
1397                if (!this.multiple && current_month
1398				    && iday == mday && this.hiliteToday) {
1399                    cell.className += " selected";
1400                    this.currentDateEl = cell;
1401                }
1402                if (date.getFullYear() == TY &&
1403				    date.getMonth() == TM &&
1404				    iday == TD) {
1405                    cell.className += " today";
1406                    cell.ttip += Calendar._TT["PART_TODAY"];
1407                }
1408                if (weekend.indexOf(wday.toString()) != -1)
1409                    cell.className += cell.otherMonth ? " oweekend" : " weekend";
1410            }
1411        }
1412        if (!(hasdays || this.showsOtherMonths))
1413            row.className = "emptyrow";
1414    }
1415    //topcat
1416    //this.title.innerHTML = Calendar._MN[month] + ", " + year;	
1417    //alert("Show:" + year);
1418    if (parseInt(year, 10) > 1911)
1419        this.title.innerHTML = "民國" + (parseInt(year, 10) - 1911).toString() + "年 ," + Calendar._MN[month]; //topcat
1420    else
1421        this.title.innerHTML = "民國" + (parseInt(year, 10)).toString() + "年 ," + Calendar._MN[month]; //topcat
1422    this.onSetTime();
1423    this.table.style.visibility = "visible";
1424    this._initMultipleDates();
1425    // PROFILE
1426    // this.tooltips.innerHTML = "Generated in " + ((new Date()) - today) + " ms";
1427};
1428
1429Calendar.prototype._initMultipleDates = function() {
1430	if (this.multiple) {
1431		for (var i in this.multiple) {
1432			var cell = this.datesCells[i];
1433			var d = this.multiple[i];
1434			if (!d)
1435				continue;
1436			if (cell)
1437				cell.className += " selected";
1438		}
1439	}
1440};
1441
1442Calendar.prototype._toggleMultipleDate = function(date) {
1443	if (this.multiple) {
1444		var ds = date.print("%Y%m%d");
1445		var cell = this.datesCells[ds];
1446		if (cell) {
1447			var d = this.multiple[ds];
1448			if (!d) {
1449				Calendar.addClass(cell, "selected");
1450				this.multiple[ds] = date;
1451			} else {
1452				Calendar.removeClass(cell, "selected");
1453				delete this.multiple[ds];
1454			}
1455		}
1456	}
1457};
1458
1459Calendar.prototype.setDateToolTipHandler = function (unaryFunction) {
1460	this.getDateToolTip = unaryFunction;
1461};
1462
1463/**
1464 *  Calls _init function above for going to a certain date (but only if the
1465 *  date is different than the currently selected one).
1466 */
1467Calendar.prototype.setDate = function (date) {
1468	if (!date.equalsTo(this.date)) {
1469		this._init(this.firstDayOfWeek, date);
1470	}
1471};
1472
1473/**
1474 *  Refreshes the calendar.  Useful if the "disabledHandler" function is
1475 *  dynamic, meaning that the list of disabled date can change at runtime.
1476 *  Just * call this function if you think that the list of disabled dates
1477 *  should * change.
1478 */
1479Calendar.prototype.refresh = function () {
1480	this._init(this.firstDayOfWeek, this.date);
1481};
1482
1483/** Modifies the "firstDayOfWeek" parameter (pass 0 for Synday, 1 for Monday, etc.). */
1484Calendar.prototype.setFirstDayOfWeek = function (firstDayOfWeek) {
1485	this._init(firstDayOfWeek, this.date);
1486	this._displayWeekdays();
1487};
1488
1489/**
1490 *  Allows customization of what dates are enabled.  The "unaryFunction"
1491 *  parameter must be a function object that receives the date (as a JS Date
1492 *  object) and returns a boolean value.  If the returned value is true then
1493 *  the passed date will be marked as disabled.
1494 */
1495Calendar.prototype.setDateStatusHandler = Calendar.prototype.setDisabledHandler = function (unaryFunction) {
1496	this.getDateStatus = unaryFunction;
1497};
1498
1499/** Customization of allowed year range for the calendar. */
1500Calendar.prototype.setRange = function (a, z) {
1501	this.minYear = a;
1502	this.maxYear = z;
1503};
1504
1505/** Calls the first user handler (selectedHandler). */
1506Calendar.prototype.callHandler = function () {
1507	if (this.onSelected) {
1508		this.onSelected(this, this.date.print(this.dateFormat));
1509	}
1510};
1511
1512/** Calls the second user handler (closeHandler). */
1513Calendar.prototype.callCloseHandler = function () {
1514	if (this.onClose) {
1515		this.onClose(this);
1516	}
1517	this.hideShowCovered();
1518};
1519
1520/** Removes the calendar object from the DOM tree and destroys it. */
1521Calendar.prototype.destroy = function () {
1522	var el = this.element.parentNode;
1523	el.removeChild(this.element);
1524	Calendar._C = null;
1525	window._dynarch_popupCalendar = null;
1526};
1527
1528/**
1529 *  Moves the calendar element to a different section in the DOM tree (changes
1530 *  its parent).
1531 */
1532Calendar.prototype.reparent = function (new_parent) {
1533	var el = this.element;
1534	el.parentNode.removeChild(el);
1535	new_parent.appendChild(el);
1536};
1537
1538// This gets called when the user presses a mouse button anywhere in the
1539// document, if the calendar is shown.  If the click was outside the open
1540// calendar this function closes it.
1541Calendar._checkCalendar = function(ev) {
1542	var calendar = window._dynarch_popupCalendar;
1543	if (!calendar) {
1544		return false;
1545	}
1546	var el = Calendar.is_ie ? Calendar.getElement(ev) : Calendar.getTargetElement(ev);
1547	for (; el != null && el != calendar.element; el = el.parentNode);
1548	if (el == null) {
1549		// calls closeHandler which should hide the calendar.
1550		window._dynarch_popupCalendar.callCloseHandler();
1551		return Calendar.stopEvent(ev);
1552	}
1553};
1554
1555/** Shows the calendar. */
1556Calendar.prototype.show = function () {
1557	var rows = this.table.getElementsByTagName("tr");
1558	for (var i = rows.length; i > 0;) {
1559		var row = rows[--i];
1560		Calendar.removeClass(row, "rowhilite");
1561		var cells = row.getElementsByTagName("td");
1562		for (var j = cells.length; j > 0;) {
1563			var cell = cells[--j];
1564			Calendar.removeClass(cell, "hilite");
1565			Calendar.removeClass(cell, "active");
1566		}
1567	}
1568	this.element.style.display = "block";
1569	this.hidden = false;
1570	if (this.isPopup) {
1571		window._dynarch_popupCalendar = this;
1572		Calendar.addEvent(document, "keydown", Calendar._keyEvent);
1573		Calendar.addEvent(document, "keypress", Calendar._keyEvent);
1574		Calendar.addEvent(document, "mousedown", Calendar._checkCalendar);
1575	}
1576	this.hideShowCovered();
1577};
1578
1579/**
1580 *  Hides the calendar.  Also removes any "hilite" from the class of any TD
1581 *  element.
1582 */
1583Calendar.prototype.hide = function () {
1584	if (this.isPopup) {
1585		Calendar.removeEvent(document, "keydown", Calendar._keyEvent);
1586		Calendar.removeEvent(document, "keypress", Calendar._keyEvent);
1587		Calendar.removeEvent(document, "mousedown", Calendar._checkCalendar);
1588	}
1589	this.element.style.display = "none";
1590	this.hidden = true;
1591	this.hideShowCovered();
1592};
1593
1594/**
1595 *  Shows the calendar at a given absolute position (beware that, depending on
1596 *  the calendar element style -- position property -- this might be relative
1597 *  to the parent's containing rectangle).
1598 */
1599Calendar.prototype.showAt = function (x, y) {
1600	var s = this.element.style;
1601	s.left = x + "px";
1602	s.top = y + "px";
1603	this.show();
1604};
1605
1606/** Shows the calendar near a given element. */
1607Calendar.prototype.showAtElement = function (el, opts) {
1608	var self = this;
1609	var p = Calendar.getAbsolutePos(el);
1610	if (!opts || typeof opts != "string") {
1611		this.showAt(p.x, p.y + el.offsetHeight);
1612		return true;
1613	}
1614	function fixPosition(box) {
1615		if (box.x < 0)
1616			box.x = 0;
1617		if (box.y < 0)
1618			box.y = 0;
1619		var cp = document.createElement("div");
1620		var s = cp.style;
1621		s.position = "absolute";
1622		s.right = s.bottom = s.width = s.height = "0px";
1623		document.body.appendChild(cp);
1624		var br = Calendar.getAbsolutePos(cp);
1625		document.body.removeChild(cp);
1626		if (Calendar.is_ie) {
1627			br.y += document.body.scrollTop;
1628			br.x += document.body.scrollLeft;
1629		} else {
1630			br.y += window.scrollY;
1631			br.x += window.scrollX;
1632		}
1633		var tmp = box.x + box.width - br.x;
1634		if (tmp > 0) box.x -= tmp;
1635		tmp = box.y + box.height - br.y;
1636		if (tmp > 0) box.y -= tmp;
1637	};
1638	this.element.style.display = "block";
1639	Calendar.continuation_for_the_fucking_khtml_browser = function() {
1640		var w = self.element.offsetWidth;
1641		var h = self.element.offsetHeight;
1642		self.element.style.display = "none";
1643		var valign = opts.substr(0, 1);
1644		var halign = "l";
1645		if (opts.length > 1) {
1646			halign = opts.substr(1, 1);
1647		}
1648		// vertical alignment
1649		switch (valign) {
1650		    case "T": p.y -= h; break;
1651		    case "B": p.y += el.offsetHeight; break;
1652		    case "C": p.y += (el.offsetHeight - h) / 2; break;
1653		    case "t": p.y += el.offsetHeight - h; break;
1654		    case "b": break; // already there
1655		}
1656		// horizontal alignment
1657		switch (halign) {
1658		    case "L": p.x -= w; break;
1659		    case "R": p.x += el.offsetWidth; break;
1660		    case "C": p.x += (el.offsetWidth - w) / 2; break;
1661		    case "l": p.x += el.offsetWidth - w; break;
1662		    case "r": break; // already there
1663		}
1664		p.width = w;
1665		p.height = h + 40;
1666		self.monthsCombo.style.display = "none";
1667		fixPosition(p);
1668		self.showAt(p.x, p.y);
1669	};
1670	if (Calendar.is_khtml)
1671		setTimeout("Calendar.continuation_for_the_fucking_khtml_browser()", 10);
1672	else
1673		Calendar.continuation_for_the_fucking_khtml_browser();
1674};
1675
1676/** Customizes the date format. */
1677Calendar.prototype.setDateFormat = function (str) {
1678	this.dateFormat = str;
1679};
1680
1681/** Customizes the tooltip date format. */
1682Calendar.prototype.setTtDateFormat = function (str) {
1683	this.ttDateFormat = str;
1684};
1685
1686/**
1687 *  Tries to identify the date represented in a string.  If successful it also
1688 *  calls this.setDate which moves the calendar to the given date.
1689 */
1690Calendar.prototype.parseDate = function(str, fmt) {
1691	if (!fmt)
1692		fmt = this.dateFormat;
1693	this.setDate(Date.parseDate(str, fmt));
1694};
1695
1696Calendar.prototype.hideShowCovered = function () {
1697	if (!Calendar.is_ie && !Calendar.is_opera)
1698		return;
1699	function getVisib(obj){
1700		var value = obj.style.visibility;
1701		if (!value) {
1702			if (document.defaultView && typeof (document.defaultView.getComputedStyle) == "function") { // Gecko, W3C
1703				if (!Calendar.is_khtml)
1704					value = document.defaultView.
1705						getComputedStyle(obj, "").getPropertyValue("visibility");
1706				else
1707					value = '';
1708			} else if (obj.currentStyle) { // IE
1709				value = obj.currentStyle.visibility;
1710			} else
1711				value = '';
1712		}
1713		return value;
1714	};
1715
1716	var tags = new Array("applet", "iframe", "select");
1717	var el = this.element;
1718
1719	var p = Calendar.getAbsolutePos(el);
1720	var EX1 = p.x;
1721	var EX2 = el.offsetWidth + EX1;
1722	var EY1 = p.y;
1723	var EY2 = el.offsetHeight + EY1;
1724
1725	for (var k = tags.length; k > 0; ) {
1726		var ar = document.getElementsByTagName(tags[--k]);
1727		var cc = null;
1728
1729		for (var i = ar.length; i > 0;) {
1730			cc = ar[--i];
1731
1732			p = Calendar.getAbsolutePos(cc);
1733			var CX1 = p.x;
1734			var CX2 = cc.offsetWidth + CX1;
1735			var CY1 = p.y;
1736			var CY2 = cc.offsetHeight + CY1;
1737
1738			if (this.hidden || (CX1 > EX2) || (CX2 < EX1) || (CY1 > EY2) || (CY2 < EY1)) {
1739				if (!cc.__msh_save_visibility) {
1740					cc.__msh_save_visibility = getVisib(cc);
1741				}
1742				cc.style.visibility = cc.__msh_save_visibility;
1743			} else {
1744				if (!cc.__msh_save_visibility) {
1745					cc.__msh_save_visibility = getVisib(cc);
1746				}
1747				cc.style.visibility = "hidden";
1748			}
1749		}
1750	}
1751};
1752
1753/** Internal function; it displays the bar with the names of the weekday. */
1754Calendar.prototype._displayWeekdays = function () {
1755	var fdow = this.firstDayOfWeek;
1756	var cell = this.firstdayname;
1757	var weekend = Calendar._TT["WEEKEND"];
1758	for (var i = 0; i < 7; ++i) {
1759		cell.className = "day name";
1760		var realday = (i + fdow) % 7;
1761		if (i) {
1762			cell.ttip = Calendar._TT["DAY_FIRST"].replace("%s", Calendar._DN[realday]);
1763			cell.navtype = 100;
1764			cell.calendar = this;
1765			cell.fdow = realday;
1766			Calendar._add_evs(cell);
1767		}
1768		if (weekend.indexOf(realday.toString()) != -1) {
1769			Calendar.addClass(cell, "weekend");
1770		}
1771		cell.innerHTML = Calendar._SDN[(i + fdow) % 7];
1772		cell = cell.nextSibling;
1773	}
1774};
1775
1776/** Internal function.  Hides all combo boxes that might be displayed. */
1777Calendar.prototype._hideCombos = function () {
1778	this.monthsCombo.style.display = "none";
1779	this.yearsCombo.style.display = "none";
1780};
1781
1782/** Internal function.  Starts dragging the element. */
1783Calendar.prototype._dragStart = function (ev) {
1784	if (this.dragging) {
1785		return;
1786	}
1787	this.dragging = true;
1788	var posX;
1789	var posY;
1790	if (Calendar.is_ie) {
1791		posY = window.event.clientY + document.body.scrollTop;
1792		posX = window.event.clientX + document.body.scrollLeft;
1793	} else {
1794		posY = ev.clientY + window.scrollY;
1795		posX = ev.clientX + window.scrollX;
1796	}
1797	var st = this.element.style;
1798	this.xOffs = posX - parseInt(st.left);
1799	this.yOffs = posY - parseInt(st.top);
1800	with (Calendar) {
1801		addEvent(document, "mousemove", calDragIt);
1802		addEvent(document, "mouseup", calDragEnd);
1803	}
1804};
1805
1806// BEGIN: DATE OBJECT PATCHES
1807
1808/** Adds the number of days array to the Date object. */
1809Date._MD = new Array(31,28,31,30,31,30,31,31,30,31,30,31);
1810
1811/** Constants used for time computations */
1812Date.SECOND = 1000 /* milliseconds */;
1813Date.MINUTE = 60 * Date.SECOND;
1814Date.HOUR   = 60 * Date.MINUTE;
1815Date.DAY    = 24 * Date.HOUR;
1816Date.WEEK   =  7 * Date.DAY;
1817
1818Date.parseDate = function (str, fmt) {
1819    var today = new Date();
1820    var y = 0;
1821    var m = -1;
1822    var d = 0;
1823    var a = str.split(/\W+/);
1824    var b = fmt.match(/%./g);
1825    var i = 0, j = 0;
1826    var hr = 0;
1827    var min = 0;
1828    for (i = 0; i < a.length; ++i) {
1829        if (!a[i])
1830            continue;
1831        switch (b[i]) {
1832            case "%d":
1833            case "%e":
1834                d = parseInt(a[i], 10);
1835                break;
1836
1837            case "%m":
1838                m = parseInt(a[i], 10) - 1;
1839                break;
1840
1841            case "%Y":
1842
1843            case "%y":
1844                y = parseInt(a[i], 10);
1845                (y < 100) && (y += (y > 29) ? 1900 : 2000);
1846                break;
1847
1848            case "%b":
1849            case "%B":
1850                for (j = 0; j < 12; ++j) {
1851                    if (Calendar._MN[j].substr(0, a[i].length).toLowerCase() == a[i].toLowerCase()) { m = j; break; }
1852                }
1853                break;
1854
1855            case "%H":
1856            case "%I":
1857            case "%k":
1858            case "%l":
1859                hr = parseInt(a[i], 10);
1860                break;
1861
1862            case "%P":
1863            case "%p":
1864                if (/pm/i.test(a[i]) && hr < 12)
1865                    hr += 12;
1866                else if (/am/i.test(a[i]) && hr >= 12)
1867                    hr -= 12;
1868                break;
1869
1870            case "%M":
1871                min = parseInt(a[i], 10);
1872                break;
1873        }
1874    }
1875    if (isNaN(y)) y = today.getFullYear();
1876    if (isNaN(m)) m = today.getMonth();
1877    if (isNaN(d)) d = today.getDate();
1878    if (isNaN(hr)) hr = today.getHours();
1879    if (isNaN(min)) min = today.getMinutes();
1880    if (y != 0 && m != -1 && d != 0)
1881        return new Date(y, m, d, hr, min, 0);
1882    y = 0; m = -1; d = 0;
1883    for (i = 0; i < a.length; ++i) {
1884        if (a[i].search(/[a-zA-Z]+/) != -1) {
1885            var t = -1;
1886            for (j = 0; j < 12; ++j) {
1887                if (Calendar._MN[j].substr(0, a[i].length).toLowerCase() == a[i].toLowerCase()) { t = j; break; }
1888            }
1889            if (t != -1) {
1890                if (m != -1) {
1891                    d = m + 1;
1892                }
1893                m = t;
1894            }
1895        } else if (parseInt(a[i], 10) <= 12 && m == -1) {
1896            m = a[i] - 1;
1897        } else if (parseInt(a[i], 10) > 31 && y == 0) {
1898            y = parseInt(a[i], 10);
1899            if (y < 1911)
1900                y += 1911;
1901            //alert("test:" + y);            
1902            //(y < 100) && (y += (y > 29) ? 1900 : 2000);
1903        } else if (d == 0) {
1904            d = a[i];
1905        }
1906    }
1907    if (y == 0)
1908        y = today.getFullYear();
1909    if (m != -1 && d != 0)
1910        return new Date(y, m, d, hr, min, 0);
1911    return today;
1912};
1913
1914/** Returns the number of days in the current month */
1915Date.prototype.getMonthDays = function(month) {
1916	var year = this.getFullYear();
1917	if (typeof month == "undefined") {
1918		month = this.getMonth();
1919	}
1920	if (((0 == (year%4)) && ( (0 != (year%100)) || (0 == (year%400)))) && month == 1) {
1921		return 29;
1922	} else {
1923		return Date._MD[month];
1924	}
1925};
1926
1927/** Returns the number of day in the year. */
1928Date.prototype.getDayOfYear = function() {
1929	var now = new Date(this.getFullYear(), this.getMonth(), this.getDate(), 0, 0, 0);
1930	var then = new Date(this.getFullYear(), 0, 0, 0, 0, 0);
1931	var time = now - then;
1932	return Math.floor(time / Date.DAY);
1933};
1934
1935/** Returns the number of the week in year, as defined in ISO 8601. */
1936Date.prototype.getWeekNumber = function() {
1937	var d = new Date(this.getFullYear(), this.getMonth(), this.getDate(), 0, 0, 0);
1938	var DoW = d.getDay();
1939	d.setDate(d.getDate() - (DoW + 6) % 7 + 3); // Nearest Thu
1940	var ms = d.valueOf(); // GMT
1941	d.setMonth(0);
1942	d.setDate(4); // Thu in Week 1
1943	return Math.round((ms - d.valueOf()) / (7 * 864e5)) + 1;
1944};
1945
1946/** Checks date and time equality */
1947Date.prototype.equalsTo = function(date) {
1948	return ((this.getFullYear() == date.getFullYear()) &&
1949		(this.getMonth() == date.getMonth()) &&
1950		(this.getDate() == date.getDate()) &&
1951		(this.getHours() == date.getHours()) &&
1952		(this.getMinutes() == date.getMinutes()));
1953};
1954
1955/** Set only the year, month, date parts (keep existing time) */
1956Date.prototype.setDateOnly = function(date) {
1957	var tmp = new Date(date);
1958	this.setDate(1);
1959	this.setFullYear(tmp.getFullYear());
1960	this.setMonth(tmp.getMonth());
1961	this.setDate(tmp.getDate());
1962};
1963
1964/** Prints the date in a string according to the given format. */
1965Date.prototype.print = function (str) {
1966    var m = this.getMonth();
1967    var d = this.getDate();
1968    var y = this.getFullYear();
1969    var wn = this.getWeekNumber();
1970    var w = this.getDay();
1971    var s = {};
1972    var hr = this.getHours();
1973    var pm = (hr >= 12);
1974    var ir = (pm) ? (hr - 12) : hr;
1975    var dy = this.getDayOfYear();
1976    if (ir == 0)
1977        ir = 12;
1978    var min = this.getMinutes();
1979    var sec = this.getSeconds();
1980    s["%a"] = Calendar._SDN[w]; // abbreviated weekday name [FIXME: I18N]
1981    s["%A"] = Calendar._DN[w]; // full weekday name
1982    s["%b"] = Calendar._SMN[m]; // abbreviated month name [FIXME: I18N]
1983    s["%B"] = Calendar._MN[m]; // full month name
1984    // FIXME: %c : preferred date and time representation for the current locale
1985    s["%C"] = 1 + Math.floor(y / 100); // the century number
1986    s["%d"] = (d < 10) ? ("0" + d) : d; // the day of the month (range 01 to 31)
1987    s["%e"] = d; // the day of the month (range 1 to 31)
1988    // FIXME: %D : american date style: %m/%d/%y
1989    // FIXME: %E, %F, %G, %g, %h (man strftime)
1990    s["%H"] = (hr < 10) ? ("0" + hr) : hr; // hour, range 00 to 23 (24h format)
1991    s["%I"] = (ir < 10) ? ("0" + ir) : ir; // hour, range 01 to 12 (12h format)
1992    s["%j"] = (dy < 100) ? ((dy < 10) ? ("00" + dy) : ("0" + dy)) : dy; // day of the year (range 001 to 366)
1993    s["%k"] = hr; 	// hour, range 0 to 23 (24h format)
1994    s["%l"] = ir; 	// hour, range 1 to 12 (12h format)
1995    s["%m"] = (m < 9) ? ("0" + (1 + m)) : (1 + m); // month, range 01 to 12
1996    s["%M"] = (min < 10) ? ("0" + min) : min; // minute, range 00 to 59
1997    s["%n"] = "\n"; 	// a newline character
1998    s["%p"] = pm ? "PM" : "AM";
1999    s["%P"] = pm ? "pm" : "am";
2000    // FIXME: %r : the time in am/pm notation %I:%M:%S %p
2001    // FIXME: %R : the time in 24-hour notation %H:%M
2002    s["%s"] = Math.floor(this.getTime() / 1000);
2003    s["%S"] = (sec < 10) ? ("0" + sec) : sec; // seconds, range 00 to 59
2004    s["%t"] = "\t"; 	// a tab character
2005    // FIXME: %T : the time in 24-hour notation (%H:%M:%S)
2006    s["%U"] = s["%W"] = s["%V"] = (wn < 10) ? ("0" + wn) : wn;
2007    s["%u"] = w + 1; // the day of the week (range 1 to 7, 1 = MON)
2008    s["%w"] = w; 	// the day of the week (range 0 to 6, 0 = SUN)
2009    // FIXME: %x : preferred date representation for the current locale without the time
2010    // FIXME: %X : preferred time representation for the current locale without the date
2011    s["%y"] = ('' + y).substr(2, 2); // year without the century (range 00 to 99)
2012    s["%Y"] = y; 	// year with the century
2013    //topcat
2014    s["%Z"] = (y-1911).toString(); //.substr(0,3);		// year with the century	
2015
2016    s["%%"] = "%"; 	// a literal '%' character
2017
2018
2019    var re = /%./g;
2020    if (!Calendar.is_ie5 && !Calendar.is_khtml)
2021        return str.replace(re, function (par) { return s[par] || par; });
2022
2023    var a = str.match(re);
2024    for (var i = 0; i < a.length; i++) {
2025        var tmp = s[a[i]];
2026        if (tmp) {
2027            re = new RegExp(a[i], 'g');
2028            str = str.replace(re, tmp);
2029        }
2030    }
2031
2032    return str;
2033};
2034
2035Date.prototype.__msh_oldSetFullYear = Date.prototype.setFullYear;
2036Date.prototype.setFullYear = function(y) {
2037	var d = new Date(this);
2038	d.__msh_oldSetFullYear(y);
2039	if (d.getMonth() != this.getMonth())
2040		this.setDate(28);
2041	this.__msh_oldSetFullYear(y);
2042};
2043
2044// END: DATE OBJECT PATCHES
2045
2046
2047// global object that remembers the calendar
2048window._dynarch_popupCalendar = null;
2049

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.