1 // ===================================================================
2 // Author: Matt Kruse <matt@mattkruse.com>
3 // WWW: http://www.mattkruse.com/
5 // NOTICE: You may use this code for any purpose, commercial or
6 // private, without any further permission from the author. You may
7 // remove this notice from your final code if you wish, however it is
8 // appreciated by the author if at least my web site address is kept.
10 // You may *NOT* re-distribute this code in any way except through its
11 // use. That means, you can include it in your product, or your web
12 // site, or any other form where the code is actually being used. You
13 // may not put the plain javascript up on your site for download or
14 // include it in your javascript libraries for download.
15 // If you wish to share this code with others, please just point them
16 // to the URL instead.
17 // Please DO NOT link directly to my .js files from your site. Copy
18 // the files to your server and use them there. Thank you.
19 // ===================================================================
22 /* SOURCE FILE: date.js */
25 // ------------------------------------------------------------------
26 // May 17, 2003: Fixed bug in parseDate() for dates <1970
27 // March 11, 2003: Added parseDate() function
28 // March 11, 2003: Added "NNN" formatting option. Doesn't match up
29 // perfectly with SimpleDateFormat formats, but
30 // backwards-compatability was required.
32 // ------------------------------------------------------------------
33 // These functions use the same 'format' strings as the
34 // java.text.SimpleDateFormat class, with minor exceptions.
35 // The format string consists of the following abbreviations:
37 // Field | Full Form | Short Form
38 // -------------+--------------------+-----------------------
39 // Year | yyyy (4 digits) | yy (2 digits), y (2 or 4 digits)
40 // Month | MMM (name or abbr.)| MM (2 digits), M (1 or 2 digits)
42 // Day of Month | dd (2 digits) | d (1 or 2 digits)
43 // Day of Week | EE (name) | E (abbr)
44 // Hour (1-12) | hh (2 digits) | h (1 or 2 digits)
45 // Hour (0-23) | HH (2 digits) | H (1 or 2 digits)
46 // Hour (0-11) | KK (2 digits) | K (1 or 2 digits)
47 // Hour (1-24) | kk (2 digits) | k (1 or 2 digits)
48 // Minute | mm (2 digits) | m (1 or 2 digits)
49 // Second | ss (2 digits) | s (1 or 2 digits)
52 // NOTE THE DIFFERENCE BETWEEN MM and mm! Month=MM, not mm!
54 // "MMM d, y" matches: January 01, 2000
57 // "M/d/yy" matches: 01/20/00
59 // "MMM dd, yyyy hh:mm:ssa" matches: "January 01, 2000 12:30:45AM"
60 // ------------------------------------------------------------------
62 var MONTH_NAMES=new Array('January','February','March','April','May','June','July','August','September','October','November','December','Jan','Feb','Mar','Apr','May','Jun','Jul','Aug','Sep','Oct','Nov','Dec');
63 var DAY_NAMES=new Array('Sunday','Monday','Tuesday','Wednesday','Thursday','Friday','Saturday','Sun','Mon','Tue','Wed','Thu','Fri','Sat');
64 function LZ(x) {return(x<0||x>9?"":"0")+x}
66 // ------------------------------------------------------------------
67 // isDate ( date_string, format_string )
68 // Returns true if date string matches format of format string and
69 // is a valid date. Else returns false.
70 // It is recommended that you trim whitespace around the value before
71 // passing it to this function, as whitespace is NOT ignored!
72 // ------------------------------------------------------------------
73 function isDate(val,format) {
74 var date=getDateFromFormat(val,format);
75 if (date==0) { return false; }
79 // -------------------------------------------------------------------
80 // compareDates(date1,date1format,date2,date2format)
81 // Compare two date strings to see which is greater.
83 // 1 if date1 is greater than date2
84 // 0 if date2 is greater than date1 of if they are the same
85 // -1 if either of the dates is in an invalid format
86 // -------------------------------------------------------------------
87 function compareDates(date1,dateformat1,date2,dateformat2) {
88 var d1=getDateFromFormat(date1,dateformat1);
89 var d2=getDateFromFormat(date2,dateformat2);
99 // ------------------------------------------------------------------
100 // formatDate (date_object, format)
101 // Returns a date in the output format specified.
102 // The format string uses the same abbreviations as in getDateFromFormat()
103 // ------------------------------------------------------------------
104 function formatDate(date,format) {
110 var y=date.getYear()+"";
111 var M=date.getMonth()+1;
112 var d=date.getDate();
114 var H=date.getHours();
115 var m=date.getMinutes();
116 var s=date.getSeconds();
117 var yyyy,yy,MMM,MM,dd,hh,h,mm,ss,ampm,HH,H,KK,K,kk,k;
118 // Convert real date parts into formatted versions
119 var value=new Object();
120 if (y.length < 4) {y=""+(y-0+1900);}
123 value["yy"]=y.substring(2,4);
126 value["MMM"]=MONTH_NAMES[M-1];
127 value["NNN"]=MONTH_NAMES[M+11];
130 value["E"]=DAY_NAMES[E+7];
131 value["EE"]=DAY_NAMES[E];
134 if (H==0){value["h"]=12;}
135 else if (H>12){value["h"]=H-12;}
137 value["hh"]=LZ(value["h"]);
138 if (H>11){value["K"]=H-12;} else {value["K"]=H;}
140 value["KK"]=LZ(value["K"]);
141 value["kk"]=LZ(value["k"]);
142 if (H > 11) { value["a"]="PM"; }
143 else { value["a"]="AM"; }
148 while (i_format < format.length) {
149 c=format.charAt(i_format);
151 while ((format.charAt(i_format)==c) && (i_format < format.length)) {
152 token += format.charAt(i_format++);
154 if (value[token] != null) { result=result + value[token]; }
155 else { result=result + token; }
160 // ------------------------------------------------------------------
161 // Utility functions for parsing in getDateFromFormat()
162 // ------------------------------------------------------------------
163 function _isInteger(val) {
164 var digits="1234567890";
165 for (var i=0; i < val.length; i++) {
166 if (digits.indexOf(val.charAt(i))==-1) { return false; }
170 function _getInt(str,i,minlength,maxlength) {
171 for (var x=maxlength; x>=minlength; x--) {
172 var token=str.substring(i,i+x);
173 if (token.length < minlength) { return null; }
174 if (_isInteger(token)) { return token; }
179 // ------------------------------------------------------------------
180 // getDateFromFormat( date_string , format_string )
182 // This function takes a date string and a format string. It matches
183 // If the date string matches the format string, it returns the
184 // getTime() of the date. If it does not match, it returns 0.
185 // ------------------------------------------------------------------
186 function getDateFromFormat(val,format) {
197 var year=now.getYear();
198 var month=now.getMonth()+1;
200 var hh=now.getHours();
201 var mm=now.getMinutes();
202 var ss=now.getSeconds();
205 while (i_format < format.length) {
206 // Get next token from format string
207 c=format.charAt(i_format);
209 while ((format.charAt(i_format)==c) && (i_format < format.length)) {
210 token += format.charAt(i_format++);
212 // Extract contents of value based on format token
213 if (token=="yyyy" || token=="yy" || token=="y") {
214 if (token=="yyyy") { x=4;y=4; }
215 if (token=="yy") { x=2;y=2; }
216 if (token=="y") { x=2;y=4; }
217 year=_getInt(val,i_val,x,y);
218 if (year==null) { return 0; }
219 i_val += year.length;
220 if (year.length==2) {
221 if (year > 70) { year=1900+(year-0); }
222 else { year=2000+(year-0); }
225 else if (token=="MMM"||token=="NNN"){
227 for (var i=0; i<MONTH_NAMES.length; i++) {
228 var month_name=MONTH_NAMES[i];
229 if (val.substring(i_val,i_val+month_name.length).toLowerCase()==month_name.toLowerCase()) {
230 if (token=="MMM"||(token=="NNN"&&i>11)) {
232 if (month>12) { month -= 12; }
233 i_val += month_name.length;
238 if ((month < 1)||(month>12)){return 0;}
240 else if (token=="EE"||token=="E"){
241 for (var i=0; i<DAY_NAMES.length; i++) {
242 var day_name=DAY_NAMES[i];
243 if (val.substring(i_val,i_val+day_name.length).toLowerCase()==day_name.toLowerCase()) {
244 i_val += day_name.length;
249 else if (token=="MM"||token=="M") {
250 month=_getInt(val,i_val,token.length,2);
251 if(month==null||(month<1)||(month>12)){return 0;}
252 i_val+=month.length;}
253 else if (token=="dd"||token=="d") {
254 date=_getInt(val,i_val,token.length,2);
255 if(date==null||(date<1)||(date>31)){return 0;}
257 else if (token=="hh"||token=="h") {
258 hh=_getInt(val,i_val,token.length,2);
259 if(hh==null||(hh<1)||(hh>12)){return 0;}
261 else if (token=="HH"||token=="H") {
262 hh=_getInt(val,i_val,token.length,2);
263 if(hh==null||(hh<0)||(hh>23)){return 0;}
265 else if (token=="KK"||token=="K") {
266 hh=_getInt(val,i_val,token.length,2);
267 if(hh==null||(hh<0)||(hh>11)){return 0;}
269 else if (token=="kk"||token=="k") {
270 hh=_getInt(val,i_val,token.length,2);
271 if(hh==null||(hh<1)||(hh>24)){return 0;}
272 i_val+=hh.length;hh--;}
273 else if (token=="mm"||token=="m") {
274 mm=_getInt(val,i_val,token.length,2);
275 if(mm==null||(mm<0)||(mm>59)){return 0;}
277 else if (token=="ss"||token=="s") {
278 ss=_getInt(val,i_val,token.length,2);
279 if(ss==null||(ss<0)||(ss>59)){return 0;}
281 else if (token=="a") {
282 if (val.substring(i_val,i_val+2).toLowerCase()=="am") {ampm="AM";}
283 else if (val.substring(i_val,i_val+2).toLowerCase()=="pm") {ampm="PM";}
287 if (val.substring(i_val,i_val+token.length)!=token) {return 0;}
288 else {i_val+=token.length;}
291 // If there are any trailing characters left in the value, it doesn't match
292 if (i_val != val.length) { return 0; }
293 // Is date valid for month?
295 // Check for leap year
296 if ( ( (year%4==0)&&(year%100 != 0) ) || (year%400==0) ) { // leap year
297 if (date > 29){ return 0; }
299 else { if (date > 28) { return 0; } }
301 if ((month==4)||(month==6)||(month==9)||(month==11)) {
302 if (date > 30) { return 0; }
304 // Correct hours value
305 if (hh<12 && ampm=="PM") { hh=hh-0+12; }
306 else if (hh>11 && ampm=="AM") { hh-=12; }
307 var newdate=new Date(year,month-1,date,hh,mm,ss);
308 return newdate.getTime();
311 // ------------------------------------------------------------------
312 // parseDate( date_string [, prefer_euro_format] )
314 // This function takes a date string and tries to match it to a
315 // number of possible date formats to get the value. It will try to
316 // match against the following international formats, in this order:
317 // y-M-d MMM d, y MMM d,y y-MMM-d d-MMM-y MMM d
318 // M/d/y M-d-y M.d.y MMM-d M/d M-d
319 // d/M/y d-M-y d.M.y d-MMM d/M d-M
320 // A second argument may be passed to instruct the method to search
321 // for formats like d/M/y (european format) before M/d/y (American).
322 // Returns a Date object or null if no patterns match.
323 // ------------------------------------------------------------------
324 function parseDate(val) {
325 var preferEuro=(arguments.length==2)?arguments[1]:false;
326 generalFormats=new Array('y-M-d','MMM d, y','MMM d,y','y-MMM-d','d-MMM-y','MMM d');
327 monthFirst=new Array('M/d/y','M-d-y','M.d.y','MMM-d','M/d','M-d');
328 dateFirst =new Array('d/M/y','d-M-y','d.M.y','d-MMM','d/M','d-M');
329 var checkList=new Array('generalFormats',preferEuro?'dateFirst':'monthFirst',preferEuro?'monthFirst':'dateFirst');
331 for (var i=0; i<checkList.length; i++) {
332 var l=window[checkList[i]];
333 for (var j=0; j<l.length; j++) {
334 d=getDateFromFormat(val,l[j]);
335 if (d!=0) { return new Date(d); }
341 /* SOURCE FILE: PopupWindow.js */
346 Last modified: 02/16/04
348 DESCRIPTION: This object allows you to easily and quickly popup a window
349 in a certain place. The window can either be a DIV or a separate browser
352 COMPATABILITY: Works with Netscape 4.x, 6.x, IE 5.x on Windows. Some small
353 positioning errors - usually with Window positioning - occur on the
354 Macintosh platform. Due to bugs in Netscape 4.x, populating the popup
355 window with <STYLE> tags may cause errors.
358 // Create an object for a WINDOW popup
359 var win = new PopupWindow();
361 // Create an object for a DIV window using the DIV named 'mydiv'
362 var win = new PopupWindow('mydiv');
364 // Set the window to automatically hide itself when the user clicks
365 // anywhere else on the page except the popup
368 // Show the window relative to the anchor name passed in
369 win.showPopup(anchorname);
374 // Set the size of the popup window (only applies to WINDOW popups
375 win.setSize(width,height);
377 // Populate the contents of the popup window that will be shown. If you
378 // change the contents while it is displayed, you will need to refresh()
379 win.populate(string);
381 // set the URL of the window, rather than populating its contents
383 win.setUrl("http://www.site.com/");
385 // Refresh the contents of the popup
388 // Specify how many pixels to the right of the anchor the popup will appear
391 // Specify how many pixels below the anchor the popup will appear
395 1) Requires the functions in AnchorPosition.js
397 2) Your anchor tag MUST contain both NAME and ID attributes which are the
399 <A NAME="test" ID="test"> </A>
401 3) There must be at least a space between <A> </A> for IE5.5 to see the
402 anchor tag correctly. Do not do <A></A> with no space.
404 4) When a PopupWindow object is created, a handler for 'onmouseup' is
405 attached to any event handler you may have already defined. Do NOT define
406 an event handler for 'onmouseup' after you define a PopupWindow object or
407 the autoHide() will not work correctly.
413 var coordinates = new Object();
414 if (!e) var e = window.event;
415 if (e.pageX || e.pageY)
420 else if (e.clientX || e.clientY)
423 posx = e.clientX + document.body.scrollLeft
424 + document.documentElement.scrollLeft;
425 posy = e.clientY + document.body.scrollTop
426 + document.documentElement.scrollTop;
429 //alert("posx: " + posx + " posy: " + posy);
430 coordinates.x = posx;
431 coordinates.y = posy;
434 // Set the position of the popup window based on the anchor
435 function PopupWindow_getXYPosition(anchorname) {
437 if (this.type == "WINDOW") {
438 coordinates = getAnchorWindowPosition(anchorname);
439 coordinates = getPos(anchorname); // Replaced using getPost(event)
442 //alert("envent: " + anchorname);
443 //coordinates = getAnchorPosition(anchorname);
444 coordinates = getPos(anchorname); // Replaced using getPost(event)
447 this.x = coordinates.x;
448 this.y = coordinates.y;
449 //alert("PopupWindow_getXYPosition x: " + this.x + " y: " + this.y);
451 // Set width/height of DIV/popup window
452 function PopupWindow_setSize(width,height) {
454 this.height = height;
456 // Fill the window with contents
457 function PopupWindow_populate(contents) {
458 this.contents = contents;
459 this.populated = false;
461 // Set the URL to go to
462 function PopupWindow_setUrl(url) {
465 // Set the window popup properties
466 function PopupWindow_setWindowProperties(props) {
467 this.windowProperties = props;
469 // Refresh the displayed contents of the popup
470 function PopupWindow_refresh() {
471 if (this.divName != null) {
472 // refresh the DIV object
474 document.getElementById(this.divName).innerHTML = this.contents;
476 else if (this.use_css) {
477 document.all[this.divName].innerHTML = this.contents;
479 else if (this.use_layers) {
480 var d = document.layers[this.divName];
482 d.document.writeln(this.contents);
487 if (this.popupWindow != null && !this.popupWindow.closed) {
489 this.popupWindow.location.href=this.url;
492 this.popupWindow.document.open();
493 this.popupWindow.document.writeln(this.contents);
494 this.popupWindow.document.close();
496 this.popupWindow.focus();
503 function parenName(ref)
505 ok=0; // it's just to start the loop, we don't use it to get out.
508 ref = ref.parentNode;
509 if (ref.nodeType==1) //check that the node is a tag, not text (type=3)
511 if (String(ref.nodeName)=="DIV")
513 offsetLeft = ref.offsetLeft;
514 offsetTop = ref.offsetTop;
518 if (String(ref.nodeName)=="BODY")
526 // Position and show the popup, relative to an anchor object
527 function PopupWindow_showPopup(anchorname) {
528 this.getXYPosition(anchorname);
529 this.x += this.offsetX - 125;
530 this.y += this.offsetY;
531 if (!this.populated && (this.contents != "")) {
532 this.populated = true;
535 if (this.divName != null) {
536 // Show the DIV object
537 var oDiv = document.getElementById(this.divName);
540 document.getElementById(this.divName).style.left = this.x - offsetLeft + "px";
541 document.getElementById(this.divName).style.top = this.y - offsetTop + "px";
542 document.getElementById(this.divName).style.visibility = "visible";
544 else if (this.use_css) {
545 document.all[this.divName].style.left = this.x;
546 document.all[this.divName].style.top = this.y;
547 document.all[this.divName].style.visibility = "visible";
549 else if (this.use_layers) {
550 document.layers[this.divName].left = this.x;
551 document.layers[this.divName].top = this.y;
552 document.layers[this.divName].visibility = "visible";
556 if (this.popupWindow == null || this.popupWindow.closed) {
557 // If the popup window will go off-screen, move it so it doesn't
558 if (this.x<0) { this.x=0; }
559 if (this.y<0) { this.y=0; }
560 if (screen && screen.availHeight) {
561 if ((this.y + this.height) > screen.availHeight) {
562 this.y = screen.availHeight - this.height;
565 if (screen && screen.availWidth) {
566 if ((this.x + this.width) > screen.availWidth) {
567 this.x = screen.availWidth - this.width;
570 var avoidAboutBlank = window.opera || ( document.layers && !navigator.mimeTypes['*'] ) || navigator.vendor == 'KDE' || ( document.childNodes && !document.all && !navigator.taintEnabled );
571 this.popupWindow = window.open(avoidAboutBlank?"":"about:blank","window_"+anchorname,this.windowProperties+",width="+this.width+",height="+this.height+",screenX="+this.x+",left="+this.x+",screenY="+this.y+",top="+this.y+"");
576 //added for IE6 issue
577 ///////////////////////
578 showFrame(this.divName, this.frameName);
579 /*var oIfr = document.getElementById(this.frameName);
580 var oCal = document.getElementById(this.divName);
581 oIfr.style.display='block';
582 oIfr.style.top=oCal.style.top;
583 oIfr.style.left=oCal.style.left;*/
588 function PopupWindow_hidePopup() {
589 if (this.divName != null) {
592 document.getElementById(this.divName).style.visibility = "hidden";
594 else if (this.use_css) {
595 document.all[this.divName].style.visibility = "hidden";
597 else if (this.use_layers) {
598 document.layers[this.divName].visibility = "hidden";
602 if (this.popupWindow && !this.popupWindow.closed) {
603 this.popupWindow.close();
604 this.popupWindow = null;
609 //added for IE6 issue
611 hideFrame(this.divName, this.frameName);
612 /*var oIfr = document.getElementById(this.frameName);
613 oIfr.style.display='none'; */
615 // Pass an event and return whether or not it was the popup DIV that was clicked
616 function PopupWindow_isClicked(e) {
617 if (this.divName != null) {
618 if (this.use_layers) {
619 var clickX = e.pageX;
620 var clickY = e.pageY;
621 var t = document.layers[this.divName];
622 if ((clickX > t.left) && (clickX < t.left+t.clip.width) && (clickY > t.top) && (clickY < t.top+t.clip.height)) {
623 window.calendarAction='Y';
626 else { return false; }
628 else if (document.all) { // Need to hard-code this to trap IE for error-handling
629 var t = window.event.srcElement;
630 while (t.parentElement != null) {
631 if (t.id==this.divName) {
632 window.calendarAction='Y';
639 else if (this.use_gebi && e) {
640 var t = e.originalTarget;
642 while (t && t.parentNode != null) {
643 if (t.id==this.divName) {
644 window.calendarAction='Y';
656 // Check an onMouseDown event to see if we should hide
657 function PopupWindow_hideIfNotClicked(e) {
658 if (this.autoHideEnabled && !this.isClicked(e)) {
663 // Call this to make the DIV disable automatically when mouse is clicked outside it
664 function PopupWindow_autoHide() {
665 this.autoHideEnabled = true;
667 // This global function checks all PopupWindow objects onmouseup to see if they should be hidden
668 function PopupWindow_hidePopupWindows(e) {
669 for (var i=0; i<popupWindowObjects.length; i++) {
670 if (popupWindowObjects[i] != null) {
671 var p = popupWindowObjects[i];
672 p.hideIfNotClicked(e);
676 // Run this immediately to attach the event listener
677 function PopupWindow_attachListener() {
678 if (document.layers) {
679 document.captureEvents(Event.MOUSEUP);
681 window.popupWindowOldEventListener = document.onmouseup;
682 if (window.popupWindowOldEventListener != null) {
683 document.onmouseup = new Function("window.popupWindowOldEventListener(); PopupWindow_hidePopupWindows();");
686 document.onmouseup = PopupWindow_hidePopupWindows;
690 // Reset the calendar DIV realted to another DIV
691 function PopupWindow_resetPosition(relatedDiv) {
692 //var calendarDiv = document.getElementById("calendarDiv");
693 var calendarDiv = document.getElementById(this.divName);
694 var popupDiv = document.getElementById(relatedDiv);
695 var left = calendarDiv.offsetLeft - popupDiv.offsetLeft;
696 var top = calendarDiv.offsetTop - popupDiv.offsetTop;
697 //alert("left: " + left + " top: " + top);
699 calendarDiv.style.left = left + "px";
700 calendarDiv.style.top = top + "px";
702 var calendarDivFrame = document.getElementById(this.divName + "frame");
703 var popupDivFrame = document.getElementById(relatedDiv + "frame");
704 var leftFrame = calendarDivFrame.offsetLeft - popupDivFrame.offsetLeft;
705 var topFrame = calendarDivFrame.offsetTop - popupDivFrame.offsetTop;
706 //alert("left: " + left + " top: " + top);
708 calendarDivFrame.style.left = leftFrame + "px";
709 calendarDivFrame.style.top = leftFrame + "px";
712 // CONSTRUCTOR for the PopupWindow object
713 // Pass it a DIV name to use a DHTML popup, otherwise will default to window popup
714 function PopupWindow() {
715 if (!window.popupWindowIndex) { window.popupWindowIndex = 0; }
716 if (!window.popupWindowObjects) { window.popupWindowObjects = new Array(); }
717 if (!window.listenerAttached) {
718 window.listenerAttached = true;
719 PopupWindow_attachListener();
722 this.index = popupWindowIndex++;
723 popupWindowObjects[this.index] = this;
725 //added for IE6 issue
726 this.frameName = null
727 this.popupWindow = null;
730 this.populated = false;
731 this.visible = false;
732 this.autoHideEnabled = false;
736 this.windowProperties="toolbar=no,location=no,status=no,menubar=no,scrollbars=auto,resizable,alwaysRaised,dependent,titlebar=no";
737 if (arguments.length>0) {
739 this.divName = arguments[0];
740 //added for IE6 issue
742 if (arguments.length>1)
743 this.frameName = arguments[1];
748 this.use_gebi = false;
749 this.use_css = false;
750 this.use_layers = false;
751 if (document.getElementById) { this.use_gebi = true; }
752 else if (document.all) { this.use_css = true; }
753 else if (document.layers) { this.use_layers = true; }
754 else { this.type = "WINDOW"; }
758 this.getXYPosition = PopupWindow_getXYPosition;
759 this.populate = PopupWindow_populate;
760 this.setUrl = PopupWindow_setUrl;
761 this.setWindowProperties = PopupWindow_setWindowProperties;
762 this.refresh = PopupWindow_refresh;
763 this.showPopup = PopupWindow_showPopup;
764 this.hidePopup = PopupWindow_hidePopup;
765 this.setSize = PopupWindow_setSize;
766 this.isClicked = PopupWindow_isClicked;
767 this.autoHide = PopupWindow_autoHide;
768 this.hideIfNotClicked = PopupWindow_hideIfNotClicked;
770 // Added to reset the Calendar DIV when it related with another DIV
771 this.resetPosition = PopupWindow_resetPosition;
774 /* SOURCE FILE: CalendarPopup.js */
777 // ------------------------------------------------------------------
778 // Feb 7, 2005: Fixed a CSS styles to use px unit
779 // March 29, 2004: Added check in select() method for the form field
780 // being disabled. If it is, just return and don't do anything.
781 // March 24, 2004: Fixed bug - when month name and abbreviations were
782 // changed, date format still used original values.
783 // January 26, 2004: Added support for drop-down month and year
784 // navigation (Thanks to Chris Reid for the idea)
785 // September 22, 2003: Fixed a minor problem in YEAR calendar with
787 // August 19, 2003: Renamed the function to get styles, and made it
788 // work correctly without an object reference
789 // August 18, 2003: Changed showYearNavigation and
790 // showYearNavigationInput to optionally take an argument of
792 // July 31, 2003: Added text input option for year navigation.
793 // Added a per-calendar CSS prefix option to optionally use
794 // different styles for different calendars.
795 // July 29, 2003: Fixed bug causing the Today link to be clickable
796 // even though today falls in a disabled date range.
797 // Changed formatting to use pure CSS, allowing greater control
798 // over look-and-feel options.
799 // June 11, 2003: Fixed bug causing the Today link to be unselectable
800 // under certain cases when some days of week are disabled
801 // March 14, 2003: Added ability to disable individual dates or date
802 // ranges, display as light gray and strike-through
803 // March 14, 2003: Removed dependency on graypixel.gif and instead
804 /// use table border coloring
805 // March 12, 2003: Modified showCalendar() function to allow optional
806 // start-date parameter
807 // March 11, 2003: Modified select() function to allow optional
808 // start-date parameter
810 DESCRIPTION: This object implements a popup calendar to allow the user to
811 select a date, month, quarter, or year.
813 COMPATABILITY: Works with Netscape 4.x, 6.x, IE 5.x on Windows. Some small
814 positioning errors - usually with Window positioning - occur on the
816 The calendar can be modified to work for any location in the world by
817 changing which weekday is displayed as the first column, changing the month
818 names, and changing the column headers for each day.
821 // Create a new CalendarPopup object of type WINDOW
822 var cal = new CalendarPopup();
824 // Create a new CalendarPopup object of type DIV using the DIV named 'mydiv'
825 var cal = new CalendarPopup('mydiv');
827 // Easy method to link the popup calendar with an input box.
828 cal.select(inputObject, anchorname, dateFormat);
829 // Same method, but passing a default date other than the field's current value
830 cal.select(inputObject, anchorname, dateFormat, '01/02/2000');
831 // This is an example call to the popup calendar from a link to populate an
832 // input box. Note that to use this, date.js must also be included!!
833 <A HREF="#" onClick="cal.select(document.forms[0].date,'anchorname','MM/dd/yyyy'); return false;">Select</A>
835 // Set the type of date select to be used. By default it is 'date'.
836 cal.setDisplayType(type);
838 // When a date, month, quarter, or year is clicked, a function is called and
839 // passed the details. You must write this function, and tell the calendar
840 // popup what the function name is.
841 // Function to be called for 'date' select receives y, m, d
842 cal.setReturnFunction(functionname);
843 // Function to be called for 'month' select receives y, m
844 cal.setReturnMonthFunction(functionname);
845 // Function to be called for 'quarter' select receives y, q
846 cal.setReturnQuarterFunction(functionname);
847 // Function to be called for 'year' select receives y
848 cal.setReturnYearFunction(functionname);
850 // Show the calendar relative to a given anchor
851 cal.showCalendar(anchorname);
853 // Hide the calendar. The calendar is set to autoHide automatically
856 // Set the month names to be used. Default are English month names
857 cal.setMonthNames("January","February","March",...);
859 // Set the month abbreviations to be used. Default are English month abbreviations
860 cal.setMonthAbbreviations("Jan","Feb","Mar",...);
862 // Show navigation for changing by the year, not just one month at a time
863 cal.showYearNavigation();
865 // Show month and year dropdowns, for quicker selection of month of dates
866 cal.showNavigationDropdowns();
868 // Set the text to be used above each day column. The days start with
869 // sunday regardless of the value of WeekStartDay
870 cal.setDayHeaders("S","M","T",...);
872 // Set the day for the first column in the calendar grid. By default this
873 // is Sunday (0) but it may be changed to fit the conventions of other
875 cal.setWeekStartDay(1); // week is Monday - Sunday
877 // Set the weekdays which should be disabled in the 'date' select popup. You can
878 // then allow someone to only select week end dates, or Tuedays, for example
879 cal.setDisabledWeekDays(0,1); // To disable selecting the 1st or 2nd days of the week
881 // Selectively disable individual days or date ranges. Disabled days will not
882 // be clickable, and show as strike-through text on current browsers.
883 // Date format is any format recognized by parseDate() in date.js
884 // Pass a single date to disable:
885 cal.addDisabledDates("2003-01-01");
886 // Pass null as the first parameter to mean "anything up to and including" the
888 cal.addDisabledDates(null, "01/02/03");
889 // Pass null as the second parameter to mean "including the passed date and
890 // anything after it:
891 cal.addDisabledDates("Jan 01, 2003", null);
892 // Pass two dates to disable all dates inbetween and including the two
893 cal.addDisabledDates("January 01, 2003", "Dec 31, 2003");
895 // When the 'year' select is displayed, set the number of years back from the
896 // current year to start listing years. Default is 2.
897 // This is also used for year drop-down, to decide how many years +/- to display
898 cal.setYearSelectStartOffset(2);
900 // Text for the word "Today" appearing on the calendar
901 cal.setTodayText("Today");
903 // The calendar uses CSS classes for formatting. If you want your calendar to
904 // have unique styles, you can set the prefix that will be added to all the
905 // classes in the output.
906 // For example, normal output may have this:
907 // <SPAN CLASS="cpTodayTextDisabled">Today<SPAN>
908 // But if you set the prefix like this:
909 cal.setCssPrefix("Test");
910 // The output will then look like:
911 // <SPAN CLASS="TestcpTodayTextDisabled">Today<SPAN>
912 // And you can define that style somewhere in your page.
914 // When using Year navigation, you can make the year be an input box, so
915 // the user can manually change it and jump to any year
916 cal.showYearNavigationInput();
918 // Set the calendar offset to be different than the default. By default it
919 // will appear just below and to the right of the anchorname. So if you have
920 // a text box where the date will go and and anchor immediately after the
921 // text box, the calendar will display immediately under the text box.
926 1) Requires the functions in AnchorPosition.js and PopupWindow.js
928 2) Your anchor tag MUST contain both NAME and ID attributes which are the
930 <A NAME="test" ID="test"> </A>
932 3) There must be at least a space between <A> </A> for IE5.5 to see the
933 anchor tag correctly. Do not do <A></A> with no space.
935 4) When a CalendarPopup object is created, a handler for 'onmouseup' is
936 attached to any event handler you may have already defined. Do NOT define
937 an event handler for 'onmouseup' after you define a CalendarPopup object
938 or the autoHide() will not work correctly.
940 5) The calendar popup display uses style sheets to make it look nice.
944 // CONSTRUCTOR for the CalendarPopup Object
945 function CalendarPopup() {
947 //added for IE6 issue
948 if (arguments.length>1) {
949 c = new PopupWindow(arguments[0], arguments[1]);
951 else if (arguments.length>0) {
952 c = new PopupWindow(arguments[0]);
955 c = new PopupWindow();
961 // Calendar-specific properties
962 c.monthNames = new Array("January","February","March","April","May","June","July","August","September","October","November","December");
963 c.monthAbbreviations = new Array("Jan","Feb","Mar","Apr","May","Jun","Jul","Aug","Sep","Oct","Nov","Dec");
964 c.dayHeaders = new Array("S","M","T","W","T","F","S");
965 c.returnFunction = "CP_tmpReturnFunction";
966 c.returnMonthFunction = "CP_tmpReturnMonthFunction";
967 c.returnQuarterFunction = "CP_tmpReturnQuarterFunction";
968 c.returnYearFunction = "CP_tmpReturnYearFunction";
970 c.isShowYearNavigation = false;
971 c.displayType = "date";
972 c.disabledWeekDays = new Object();
973 c.disabledDatesExpression = "";
974 c.yearSelectStartOffset = 2;
975 c.currentDate = null;
978 c.isShowNavigationDropdowns=false;
979 c.isShowYearNavigationInput=false;
980 window.CP_calendarObject = null;
981 window.CP_targetInput = null;
982 window.CP_dateFormat = "MM/dd/yyyy";
984 c.copyMonthNamesToWindow = CP_copyMonthNamesToWindow;
985 c.setReturnFunction = CP_setReturnFunction;
986 c.setReturnMonthFunction = CP_setReturnMonthFunction;
987 c.setReturnQuarterFunction = CP_setReturnQuarterFunction;
988 c.setReturnYearFunction = CP_setReturnYearFunction;
989 c.setMonthNames = CP_setMonthNames;
990 c.setMonthAbbreviations = CP_setMonthAbbreviations;
991 c.setDayHeaders = CP_setDayHeaders;
992 c.setWeekStartDay = CP_setWeekStartDay;
993 c.setDisplayType = CP_setDisplayType;
994 c.setDisabledWeekDays = CP_setDisabledWeekDays;
995 c.addDisabledDates = CP_addDisabledDates;
996 c.setYearSelectStartOffset = CP_setYearSelectStartOffset;
997 c.setTodayText = CP_setTodayText;
998 c.showYearNavigation = CP_showYearNavigation;
999 c.showCalendar = CP_showCalendar;
1000 c.hideCalendar = CP_hideCalendar;
1001 c.getStyles = getCalendarStyles;
1002 c.refreshCalendar = CP_refreshCalendar;
1003 c.getCalendar = CP_getCalendar;
1004 c.select = CP_select;
1005 c.setCssPrefix = CP_setCssPrefix;
1006 c.showNavigationDropdowns = CP_showNavigationDropdowns;
1007 c.showYearNavigationInput = CP_showYearNavigationInput;
1008 c.copyMonthNamesToWindow();
1009 // Return the object
1012 function CP_copyMonthNamesToWindow() {
1013 // Copy these values over to the date.js
1014 if (typeof(window.MONTH_NAMES)!="undefined" && window.MONTH_NAMES!=null) {
1015 window.MONTH_NAMES = new Array();
1016 for (var i=0; i<this.monthNames.length; i++) {
1017 window.MONTH_NAMES[window.MONTH_NAMES.length] = this.monthNames[i];
1019 for (var i=0; i<this.monthAbbreviations.length; i++) {
1020 window.MONTH_NAMES[window.MONTH_NAMES.length] = this.monthAbbreviations[i];
1024 // Temporary default functions to be called when items clicked, so no error is thrown
1025 function CP_tmpReturnFunction(y,m,d) {
1026 if (window.CP_targetInput!=null) {
1027 var dt = new Date(y,m-1,d,0,0,0);
1028 if (window.CP_calendarObject!=null) { window.CP_calendarObject.copyMonthNamesToWindow(); }
1029 window.CP_targetInput.value = formatDate(dt,window.CP_dateFormat);
1031 if (window.CP_targetInput.onchange){
1032 window.CP_targetInput.onchange();
1036 alert('Use setReturnFunction() to define which function will get the clicked results!');
1039 function CP_tmpReturnMonthFunction(y,m) {
1040 alert('Use setReturnMonthFunction() to define which function will get the clicked results!\nYou clicked: year='+y+' , month='+m);
1042 function CP_tmpReturnQuarterFunction(y,q) {
1043 alert('Use setReturnQuarterFunction() to define which function will get the clicked results!\nYou clicked: year='+y+' , quarter='+q);
1045 function CP_tmpReturnYearFunction(y) {
1046 alert('Use setReturnYearFunction() to define which function will get the clicked results!\nYou clicked: year='+y);
1049 // Set the name of the functions to call to get the clicked item
1050 function CP_setReturnFunction(name) { this.returnFunction = name; }
1051 function CP_setReturnMonthFunction(name) { this.returnMonthFunction = name; }
1052 function CP_setReturnQuarterFunction(name) { this.returnQuarterFunction = name; }
1053 function CP_setReturnYearFunction(name) { this.returnYearFunction = name; }
1055 // Over-ride the built-in month names
1056 function CP_setMonthNames() {
1057 for (var i=0; i<arguments.length; i++) { this.monthNames[i] = arguments[i]; }
1058 this.copyMonthNamesToWindow();
1061 // Over-ride the built-in month abbreviations
1062 function CP_setMonthAbbreviations() {
1063 for (var i=0; i<arguments.length; i++) { this.monthAbbreviations[i] = arguments[i]; }
1064 this.copyMonthNamesToWindow();
1067 // Over-ride the built-in column headers for each day
1068 function CP_setDayHeaders() {
1069 for (var i=0; i<arguments.length; i++) { this.dayHeaders[i] = arguments[i]; }
1072 // Set the day of the week (0-7) that the calendar display starts on
1073 // This is for countries other than the US whose calendar displays start on Monday(1), for example
1074 function CP_setWeekStartDay(day) { this.weekStartDay = day; }
1076 // Show next/last year navigation links
1077 function CP_showYearNavigation() { this.isShowYearNavigation = (arguments.length>0)?arguments[0]:true; }
1079 // Which type of calendar to display
1080 function CP_setDisplayType(type) {
1081 if (type!="date"&&type!="week-end"&&type!="month"&&type!="quarter"&&type!="year") { alert("Invalid display type! Must be one of: date,week-end,month,quarter,year"); return false; }
1082 this.displayType=type;
1085 // How many years back to start by default for year display
1086 function CP_setYearSelectStartOffset(num) { this.yearSelectStartOffset=num; }
1088 // Set which weekdays should not be clickable
1089 function CP_setDisabledWeekDays() {
1090 this.disabledWeekDays = new Object();
1091 for (var i=0; i<arguments.length; i++) { this.disabledWeekDays[arguments[i]] = true; }
1094 // Disable individual dates or ranges
1095 // Builds an internal logical test which is run via eval() for efficiency
1096 function CP_addDisabledDates(start, end) {
1097 if (arguments.length==1) { end=start; }
1098 if (start==null && end==null) { return; }
1099 if (this.disabledDatesExpression!="") { this.disabledDatesExpression+= "||"; }
1100 if (start!=null) { start = parseDate(start); start=""+start.getFullYear()+LZ(start.getMonth()+1)+LZ(start.getDate());}
1101 if (end!=null) { end=parseDate(end); end=""+end.getFullYear()+LZ(end.getMonth()+1)+LZ(end.getDate());}
1102 if (start==null) { this.disabledDatesExpression+="(ds<="+end+")"; }
1103 else if (end ==null) { this.disabledDatesExpression+="(ds>="+start+")"; }
1104 else { this.disabledDatesExpression+="(ds>="+start+"&&ds<="+end+")"; }
1107 // Set the text to use for the "Today" link
1108 function CP_setTodayText(text) {
1109 this.todayText = text;
1112 // Set the prefix to be added to all CSS classes when writing output
1113 function CP_setCssPrefix(val) {
1114 this.cssPrefix = val;
1117 // Show the navigation as an dropdowns that can be manually changed
1118 function CP_showNavigationDropdowns() { this.isShowNavigationDropdowns = (arguments.length>0)?arguments[0]:true; }
1120 // Show the year navigation as an input box that can be manually changed
1121 function CP_showYearNavigationInput() { this.isShowYearNavigationInput = (arguments.length>0)?arguments[0]:true; }
1123 // Hide a calendar object
1124 function CP_hideCalendar() {
1125 if (arguments.length > 0) { window.popupWindowObjects[arguments[0]].hidePopup(); }
1126 else { this.hidePopup(); }
1130 // Refresh the contents of the calendar display
1131 function CP_refreshCalendar(index) {
1132 var calObject = window.popupWindowObjects[index];
1133 if (arguments.length>1) {
1134 calObject.populate(calObject.getCalendar(arguments[1],arguments[2],arguments[3],arguments[4],arguments[5]));
1137 calObject.populate(calObject.getCalendar());
1139 calObject.refresh();
1142 // Populate the calendar and display it
1143 function CP_showCalendar(anchorname) {
1145 if (arguments.length>1) {
1146 if (arguments[1]==null||arguments[1]=="") {
1147 //var dd = parseDate();
1148 this.currentDate=new Date();
1149 //this.currentDate = dd;
1153 this.currentDate=new Date(parseDate(arguments[1]));
1156 this.populate(this.getCalendar());
1157 this.showPopup(anchorname);
1160 // Simple method to interface popup calendar with a text-entry box
1161 function CP_select(inputobj, linkname, format) {
1162 var selectedDate=(arguments.length>3)?arguments[3]:null;
1163 if (!window.getDateFromFormat) {
1164 alert("calendar.select: To use this method you must also include 'date.js' for date formatting");
1167 if (this.displayType!="date"&&this.displayType!="week-end") {
1168 alert("calendar.select: This function can only be used with displayType 'date' or 'week-end'");
1171 if (inputobj.type!="text" && inputobj.type!="hidden" && inputobj.type!="textarea") {
1172 alert("calendar.select: Input object passed is not a valid form input object");
1173 window.CP_targetInput=null;
1176 if (inputobj.disabled) { return; } // Can't use calendar input on disabled form input!
1177 window.CP_targetInput = inputobj;
1178 window.CP_calendarObject = this;
1179 this.currentDate=null;
1181 if (selectedDate!=null) {
1182 time = getDateFromFormat(selectedDate,format)
1184 else if (inputobj.value!="") {
1185 time = getDateFromFormat(inputobj.value,format);
1187 if (selectedDate!=null || inputobj.value!="") {
1188 if (time==0) { this.currentDate=null; }
1189 else { this.currentDate=new Date(time); }
1191 window.CP_dateFormat = format;
1192 this.showCalendar(linkname);
1195 // Get style block needed to display the calendar correctly
1196 function getCalendarStyles() {
1199 if (this!=null && typeof(this.cssPrefix)!="undefined" && this.cssPrefix!=null && this.cssPrefix!="") { p=this.cssPrefix; }
1200 result += "<STYLE>\n";
1201 result += "."+p+"cpYearNavigation,."+p+"cpMonthNavigation { background-color:#C0C0C0; text-align:center; vertical-align:center; text-decoration:none; color:#000000; font-weight:bold; }\n";
1202 result += "."+p+"cpDayColumnHeader, ."+p+"cpYearNavigation,."+p+"cpMonthNavigation,."+p+"cpCurrentMonthDate,."+p+"cpCurrentMonthDateDisabled,."+p+"cpOtherMonthDate,."+p+"cpOtherMonthDateDisabled,."+p+"cpCurrentDate,."+p+"cpCurrentDateDisabled,."+p+"cpTodayText,."+p+"cpTodayTextDisabled,."+p+"cpText { font-family:arial; font-size:8pt; }\n";
1203 result += "TD."+p+"cpDayColumnHeader { text-align:right; border:solid thin #C0C0C0;border-width:0px 0px 1px 0px; }\n";
1204 result += "."+p+"cpCurrentMonthDate, ."+p+"cpOtherMonthDate, ."+p+"cpCurrentDate { text-align:right; text-decoration:none; }\n";
1205 result += "."+p+"cpCurrentMonthDateDisabled, ."+p+"cpOtherMonthDateDisabled, ."+p+"cpCurrentDateDisabled { color:#D0D0D0; text-align:right; text-decoration:line-through; }\n";
1206 result += "."+p+"cpCurrentMonthDate, .cpCurrentDate { color:#000000; }\n";
1207 result += "."+p+"cpOtherMonthDate { color:#808080; }\n";
1208 result += "TD."+p+"cpCurrentDate { color:white; background-color: #C0C0C0; border-width:1px; border:solid thin #800000; }\n";
1209 result += "TD."+p+"cpCurrentDateDisabled { border-width:1px; border:solid thin #FFAAAA; }\n";
1210 result += "TD."+p+"cpTodayText, TD."+p+"cpTodayTextDisabled { border:solid thin #C0C0C0; border-width:1px 0px 0px 0px;}\n";
1211 result += "A."+p+"cpTodayText, SPAN."+p+"cpTodayTextDisabled { height:20px; }\n";
1212 result += "A."+p+"cpTodayText { color:black; }\n";
1213 result += "."+p+"cpTodayTextDisabled { color:#D0D0D0; }\n";
1214 result += "."+p+"cpBorder { border:solid thin #808080; }\n";
1215 result += "</STYLE>\n";
1219 // Return a string containing all the calendar code to be displayed
1220 function CP_getCalendar() {
1221 var now = new Date();
1222 if (typeof oracleDateString == 'function'){
1223 now = parseDate(oracleDateString());
1224 }else if (typeof parent.oracleDateString == 'function'){
1225 now = parseDate(parent.oracleDateString());
1227 // Reference to window
1228 if (this.type == "WINDOW") { var windowref = "window.opener."; }
1229 else { var windowref = ""; }
1231 // If POPUP, write entire HTML document
1232 if (this.type == "WINDOW") {
1233 result += "<HTML><HEAD><TITLE>Calendar</TITLE>"+this.getStyles()+"</HEAD><BODY MARGINWIDTH=0 MARGINHEIGHT=0 TOPMARGIN=0 RIGHTMARGIN=0 LEFTMARGIN=0>\n";
1234 result += '<CENTER><TABLE WIDTH=100% BORDER=0 BORDERWIDTH=0 CELLSPACING=0 CELLPADDING=0>\n';
1237 result += '<TABLE CLASS="'+this.cssPrefix+'cpBorder" WIDTH=144 BORDER=1 BORDERWIDTH=1 CELLSPACING=0 CELLPADDING=1>\n';
1238 result += '<TR><TD ALIGN=CENTER>\n';
1239 result += '<CENTER>\n';
1241 // Code for DATE display (default)
1242 // -------------------------------
1243 if (this.displayType=="date" || this.displayType=="week-end") {
1244 if (this.currentDate==null) { this.currentDate = now; }
1245 if (arguments.length > 0) { var month = arguments[0]; }
1246 else { var month = this.currentDate.getMonth()+1; }
1247 if (arguments.length > 1 && arguments[1]>0 && arguments[1]-0==arguments[1]) { var year = arguments[1]; }
1248 else { var year = this.currentDate.getFullYear(); }
1249 var daysinmonth= new Array(0,31,28,31,30,31,30,31,31,30,31,30,31);
1250 if ( ( (year%4 == 0)&&(year%100 != 0) ) || (year%400 == 0) ) {
1251 daysinmonth[2] = 29;
1253 var current_month = new Date(year,month-1,1);
1254 var display_year = year;
1255 var display_month = month;
1256 var display_date = 1;
1257 var weekday= current_month.getDay();
1260 offset = (weekday >= this.weekStartDay) ? weekday-this.weekStartDay : 7-this.weekStartDay+weekday ;
1263 if (display_month < 1) { display_month = 12; display_year--; }
1264 display_date = daysinmonth[display_month]-offset+1;
1266 var next_month = month+1;
1267 var next_month_year = year;
1268 if (next_month > 12) { next_month=1; next_month_year++; }
1269 var last_month = month-1;
1270 var last_month_year = year;
1271 if (last_month < 1) { last_month=12; last_month_year--; }
1273 if (this.type!="WINDOW") {
1274 result += "<TABLE WIDTH=144 BORDER=0 BORDERWIDTH=0 CELLSPACING=0 CELLPADDING=0>";
1277 var refresh = windowref+'CP_refreshCalendar';
1278 var refreshLink = 'javascript:' + refresh;
1279 if (this.isShowNavigationDropdowns) {
1280 result += '<TD CLASS="'+this.cssPrefix+'cpMonthNavigation" WIDTH="78" COLSPAN="3"><select CLASS="'+this.cssPrefix+'cpMonthNavigation" name="cpMonth" onChange="'+refresh+'('+this.index+',this.options[this.selectedIndex].value-0,'+(year-0)+');">';
1281 for( var monthCounter=1; monthCounter<=12; monthCounter++ ) {
1282 var selected = (monthCounter==month) ? 'SELECTED' : '';
1283 result += '<option value="'+monthCounter+'" '+selected+'>'+this.monthNames[monthCounter-1]+'</option>';
1285 result += '</select></TD>';
1286 result += '<TD CLASS="'+this.cssPrefix+'cpMonthNavigation" WIDTH="10"> </TD>';
1288 result += '<TD CLASS="'+this.cssPrefix+'cpYearNavigation" WIDTH="56" COLSPAN="3"><select CLASS="'+this.cssPrefix+'cpYearNavigation" name="cpYear" onChange="'+refresh+'('+this.index+','+month+',this.options[this.selectedIndex].value-0);">';
1289 for( var yearCounter=year-this.yearSelectStartOffset; yearCounter<=year+this.yearSelectStartOffset; yearCounter++ ) {
1290 var selected = (yearCounter==year) ? 'SELECTED' : '';
1291 result += '<option value="'+yearCounter+'" '+selected+'>'+yearCounter+'</option>';
1293 result += '</select></TD>';
1296 if (this.isShowYearNavigation) {
1297 result += '<TD CLASS="'+this.cssPrefix+'cpMonthNavigation" WIDTH="10"><A CLASS="'+this.cssPrefix+'cpMonthNavigation" HREF="'+refreshLink+'('+this.index+','+last_month+','+last_month_year+');"><</A></TD>';
1298 result += '<TD CLASS="'+this.cssPrefix+'cpMonthNavigation" WIDTH="58"><SPAN CLASS="'+this.cssPrefix+'cpMonthNavigation">'+this.monthNames[month-1]+'</SPAN></TD>';
1299 result += '<TD CLASS="'+this.cssPrefix+'cpMonthNavigation" WIDTH="10"><A CLASS="'+this.cssPrefix+'cpMonthNavigation" HREF="'+refreshLink+'('+this.index+','+next_month+','+next_month_year+');">></A></TD>';
1300 result += '<TD CLASS="'+this.cssPrefix+'cpMonthNavigation" WIDTH="10"> </TD>';
1302 result += '<TD CLASS="'+this.cssPrefix+'cpYearNavigation" WIDTH="10"><A CLASS="'+this.cssPrefix+'cpYearNavigation" HREF="'+refreshLink+'('+this.index+','+month+','+(year-1)+');"><</A></TD>';
1303 if (this.isShowYearNavigationInput) {
1304 result += '<TD CLASS="'+this.cssPrefix+'cpYearNavigation" WIDTH="36"><INPUT NAME="cpYear" CLASS="'+this.cssPrefix+'cpYearNavigation" SIZE="4" MAXLENGTH="4" VALUE="'+year+'" onBlur="'+refresh+'('+this.index+','+month+',this.value-0);"></TD>';
1307 result += '<TD CLASS="'+this.cssPrefix+'cpYearNavigation" WIDTH="36"><SPAN CLASS="'+this.cssPrefix+'cpYearNavigation">'+year+'</SPAN></TD>';
1309 result += '<TD CLASS="'+this.cssPrefix+'cpYearNavigation" WIDTH="10"><A CLASS="'+this.cssPrefix+'cpYearNavigation" HREF="'+refreshLink+'('+this.index+','+month+','+(year+1)+');">></A></TD>';
1312 result += '<TD CLASS="'+this.cssPrefix+'cpMonthNavigation" WIDTH="22"><A CLASS="'+this.cssPrefix+'cpMonthNavigation" HREF="'+refreshLink+'('+this.index+','+last_month+','+last_month_year+');"><<</A></TD>\n';
1313 result += '<TD CLASS="'+this.cssPrefix+'cpMonthNavigation" WIDTH="100"><SPAN CLASS="'+this.cssPrefix+'cpMonthNavigation">'+this.monthNames[month-1]+' '+year+'</SPAN></TD>\n';
1314 result += '<TD CLASS="'+this.cssPrefix+'cpMonthNavigation" WIDTH="22"><A CLASS="'+this.cssPrefix+'cpMonthNavigation" HREF="'+refreshLink+'('+this.index+','+next_month+','+next_month_year+');">>></A></TD>\n';
1317 result += '</TR></TABLE>\n';
1318 result += '<TABLE WIDTH=120 BORDER=0 CELLSPACING=0 CELLPADDING=1 ALIGN=CENTER>\n';
1320 for (var j=0; j<7; j++) {
1322 result += '<TD CLASS="'+this.cssPrefix+'cpDayColumnHeader" WIDTH="14%"><SPAN CLASS="'+this.cssPrefix+'cpDayColumnHeader">'+this.dayHeaders[(this.weekStartDay+j)%7]+'</TD>\n';
1324 result += '</TR>\n';
1325 for (var row=1; row<=6; row++) {
1327 for (var col=1; col<=7; col++) {
1329 if (this.disabledDatesExpression!="") {
1330 var ds=""+display_year+LZ(display_month)+LZ(display_date);
1331 eval("disabled=("+this.disabledDatesExpression+")");
1334 if ((display_month == this.currentDate.getMonth()+1) && (display_date==this.currentDate.getDate()) && (display_year==this.currentDate.getFullYear())) {
1335 dateClass = "cpCurrentDate";
1337 else if (display_month == month) {
1338 dateClass = "cpCurrentMonthDate";
1341 dateClass = "cpOtherMonthDate";
1343 if (disabled || this.disabledWeekDays[col-1]) {
1344 result += ' <TD CLASS="'+this.cssPrefix+dateClass+'"><SPAN CLASS="'+this.cssPrefix+dateClass+'Disabled">'+display_date+'</SPAN></TD>\n';
1347 var selected_date = display_date;
1348 var selected_month = display_month;
1349 var selected_year = display_year;
1350 if (this.displayType=="week-end") {
1351 var d = new Date(selected_year,selected_month-1,selected_date,0,0,0,0);
1352 d.setDate(d.getDate() + (7-col));
1353 selected_year = d.getYear();
1354 if (selected_year < 1000) { selected_year += 1900; }
1355 selected_month = d.getMonth()+1;
1356 selected_date = d.getDate();
1358 result += ' <TD CLASS="'+this.cssPrefix+dateClass+'"><A HREF="javascript:'+windowref+this.returnFunction+'('+selected_year+','+selected_month+','+selected_date+');'+windowref+'CP_hideCalendar(\''+this.index+'\');" CLASS="'+this.cssPrefix+dateClass+'">'+display_date+'</A></TD>\n';
1361 if (display_date > daysinmonth[display_month]) {
1365 if (display_month > 12) {
1372 var current_weekday = now.getDay() - this.weekStartDay;
1373 if (current_weekday < 0) {
1374 current_weekday += 7;
1377 result += ' <TD COLSPAN=7 ALIGN=CENTER CLASS="'+this.cssPrefix+'cpTodayText">\n';
1378 if (this.disabledDatesExpression!="") {
1379 var ds=""+now.getFullYear()+LZ(now.getMonth()+1)+LZ(now.getDate());
1380 eval("disabled=("+this.disabledDatesExpression+")");
1382 if (disabled || this.disabledWeekDays[current_weekday+1]) {
1383 result += ' <SPAN CLASS="'+this.cssPrefix+'cpTodayTextDisabled">'+this.todayText+'</SPAN>\n';
1386 result += ' <A CLASS="'+this.cssPrefix+'cpTodayText" HREF="javascript:'+windowref+this.returnFunction+'(\''+now.getFullYear()+'\',\''+(now.getMonth()+1)+'\',\''+now.getDate()+'\');'+windowref+'CP_hideCalendar(\''+this.index+'\');">'+this.todayText+'</A>\n';
1388 result += ' <BR>\n';
1389 result += ' </TD></TR></TABLE></CENTER></TD></TR></TABLE>\n';
1392 // Code common for MONTH, QUARTER, YEAR
1393 // ------------------------------------
1394 if (this.displayType=="month" || this.displayType=="quarter" || this.displayType=="year") {
1395 if (arguments.length > 0) { var year = arguments[0]; }
1397 if (this.displayType=="year") { var year = now.getFullYear()-this.yearSelectStartOffset; }
1398 else { var year = now.getFullYear(); }
1400 if (this.displayType!="year" && this.isShowYearNavigation) {
1401 result += "<TABLE WIDTH=144 BORDER=0 BORDERWIDTH=0 CELLSPACING=0 CELLPADDING=0>";
1403 result += ' <TD CLASS="'+this.cssPrefix+'cpYearNavigation" WIDTH="22"><A CLASS="'+this.cssPrefix+'cpYearNavigation" HREF="javascript:'+windowref+'CP_refreshCalendar('+this.index+','+(year-1)+');"><<</A></TD>\n';
1404 result += ' <TD CLASS="'+this.cssPrefix+'cpYearNavigation" WIDTH="100">'+year+'</TD>\n';
1405 result += ' <TD CLASS="'+this.cssPrefix+'cpYearNavigation" WIDTH="22"><A CLASS="'+this.cssPrefix+'cpYearNavigation" HREF="javascript:'+windowref+'CP_refreshCalendar('+this.index+','+(year+1)+');">>></A></TD>\n';
1406 result += '</TR></TABLE>\n';
1410 // Code for MONTH display
1411 // ----------------------
1412 if (this.displayType=="month") {
1413 // If POPUP, write entire HTML document
1414 result += '<TABLE WIDTH=120 BORDER=0 CELLSPACING=1 CELLPADDING=0 ALIGN=CENTER>\n';
1415 for (var i=0; i<4; i++) {
1417 for (var j=0; j<3; j++) {
1418 var monthindex = ((i*3)+j);
1419 result += '<TD WIDTH=33% ALIGN=CENTER><A CLASS="'+this.cssPrefix+'cpText" HREF="javascript:'+windowref+this.returnMonthFunction+'('+year+','+(monthindex+1)+');'+windowref+'CP_hideCalendar(\''+this.index+'\');" CLASS="'+date_class+'">'+this.monthAbbreviations[monthindex]+'</A></TD>';
1423 result += '</TABLE></CENTER></TD></TR></TABLE>\n';
1426 // Code for QUARTER display
1427 // ------------------------
1428 if (this.displayType=="quarter") {
1429 result += '<BR><TABLE WIDTH=120 BORDER=1 CELLSPACING=0 CELLPADDING=0 ALIGN=CENTER>\n';
1430 for (var i=0; i<2; i++) {
1432 for (var j=0; j<2; j++) {
1433 var quarter = ((i*2)+j+1);
1434 result += '<TD WIDTH=50% ALIGN=CENTER><BR><A CLASS="'+this.cssPrefix+'cpText" HREF="javascript:'+windowref+this.returnQuarterFunction+'('+year+','+quarter+');'+windowref+'CP_hideCalendar(\''+this.index+'\');" CLASS="'+date_class+'">Q'+quarter+'</A><BR><BR></TD>';
1438 result += '</TABLE></CENTER></TD></TR></TABLE>\n';
1441 // Code for YEAR display
1442 // ---------------------
1443 if (this.displayType=="year") {
1444 var yearColumnSize = 4;
1445 result += "<TABLE WIDTH=144 BORDER=0 BORDERWIDTH=0 CELLSPACING=0 CELLPADDING=0>";
1447 result += ' <TD CLASS="'+this.cssPrefix+'cpYearNavigation" WIDTH="50%"><A CLASS="'+this.cssPrefix+'cpYearNavigation" HREF="javascript:'+windowref+'CP_refreshCalendar('+this.index+','+(year-(yearColumnSize*2))+');"><<</A></TD>\n';
1448 result += ' <TD CLASS="'+this.cssPrefix+'cpYearNavigation" WIDTH="50%"><A CLASS="'+this.cssPrefix+'cpYearNavigation" HREF="javascript:'+windowref+'CP_refreshCalendar('+this.index+','+(year+(yearColumnSize*2))+');">>></A></TD>\n';
1449 result += '</TR></TABLE>\n';
1450 result += '<TABLE WIDTH=120 BORDER=0 CELLSPACING=1 CELLPADDING=0 ALIGN=CENTER>\n';
1451 for (var i=0; i<yearColumnSize; i++) {
1452 for (var j=0; j<2; j++) {
1453 var currentyear = year+(j*yearColumnSize)+i;
1454 result += '<TD WIDTH=50% ALIGN=CENTER><A CLASS="'+this.cssPrefix+'cpText" HREF="javascript:'+windowref+this.returnYearFunction+'('+currentyear+');'+windowref+'CP_hideCalendar(\''+this.index+'\');" CLASS="'+date_class+'">'+currentyear+'</A></TD>';
1458 result += '</TABLE></CENTER></TD></TR></TABLE>\n';
1461 if (this.type == "WINDOW") {
1462 result += "</BODY></HTML>\n";
1467 //added for IE6 issue
1469 function showFrame(divName, frameName){
1471 // added to show Iframe behind calender
1472 var oIfr = document.getElementById(frameName);
1473 var oCal = document.getElementById(divName);
1475 oIfr.style.display='block';
1476 oIfr.style.top=oCal.style.top;
1477 oIfr.style.left=oCal.style.left;
1481 function hideFrame(divName, frameName){
1482 var oIfr = document.getElementById(frameName);
1484 oIfr.style.display='none';