/* Theme Pack 3.1.1+ DO NOT modify */
/* Contains Calendar and Datepicker */
/* DatePicker */
CS.v3.Components.DatePicker = function(el,options) {new CS.v3.Config.DatePicker(el,options); };
CS.v3.Config.DatePicker = Class.create(CS.v3.Base.prototype, {
	initialize: function(el,options){
		this.allPickers = $(el).select("select[class*='csPicker']","input[class*='csPicker']");
		//this.bind();
		if (options.bind == 'true') {this.bind(); }
	},
	bind: function(){
		var ar = this.allPickers;
		var i = ar.length;
		var el;
		var tag;
		while(i--){
			el = ar[i];
			CS.v3.DatePicker.addDecoration(el);
			Event.observe(el,'change', function(event){ CS.v3.DatePicker.changeDateEv(event); });
			Event.observe(el,'blur', function(event){ CS.v3.DatePicker.changeDateEv(event); });
			tag = CS.v3.I18N.getTagName(el);
			if(tag == 'INPUT'){
				Event.observe(el,'keyup', function(event){ CS.v3.DatePicker.changeDateEv(event); });
			}
		}
	}
});
CS.v3.DatePicker = {
	addDecoration: function(el){
		CS.v3.I18N.initialize(el);
		var fieldset = CS.v3.getParentElement(el,'FIELDSET');//el.up('FIELDSET');
		var b = fieldset.hasClassName('csDate-wrapper');
		if(!b){
			var locale = CS.v3.I18N.initialize(el);
			CS.v3.I18N.initialize(fieldset);
			fieldset.addClassName('csDate-wrapper');
			fieldset.wrap('DIV',{'class':'csDate-wrapper'});
			var node = CS.v3.up(el,'DIV.csDate-wrapper');
			var parms = ' lang=\"' + locale + '\" xml:lang=\"' + locale + '\"';
			// NOTE: considering merging code so that even the picker can show a calendar!
			node.insert({bottom:'<div class=\"csDate-holder\"'+ parms +'>&nbsp;</div><div class=\"csDate-display\"'+ parms +'>&nbsp;</div>'});
		}
		this.updateDate(el);
	},
	changeDateEv: function(event){
		var el = $(Event.element(event));
		this.updateDate(el);
	},
	updateDate: function(el){
		CS.v3.I18N.initialize(el);
		var node = CS.v3.up(el,'DIV.csDate-wrapper');
		var fieldset = CS.v3.down(node,'FIELDSET.csDate-wrapper');
		var childs = fieldset.childElements();// node.children;
		var dt = CS.v3.I18N.createDate();
		var isTZ = dt.getTimezoneOffset();
		var isYR;
		var isMO;
		var isDA;
		var isHR;
		var isMN;
		var isSE;
		var isMS;
		var isAP;
		if(childs){
			var i1 = childs.length;
			var item1;
			while(i1--){
				item1 = childs[i1];
				//isTZ = this.tester(isTZ,item1,'?','csOffset',-2400,2400,'');
				isYR = this.tester(isYR,item1,'Y','csFullyear',1900,9999,'');
				isMO = this.tester(isMO,item1,'M','csMonth',0,12,'');
				isDA = this.tester(isDA,item1,'D','csDay',1,31,'');
				isHR = this.tester(isHR,item1,'h','csHour',0,24,'');
				isMN = this.tester(isMN,item1,'m','csMinute',0,60,'');
				isSE = this.tester(isSE,item1,'s','csSecond',0,60,'');
				//isAP = this.tester(isAM,item1,'a','csAmpm','','','AM');
			}//end for
			// day of week only available when all DAY/MONTH and YEAR are known
			if(isDA>0 && isMO>0){// && isYR>0)
				var daysInMonth = CS.v3.I18N.getDaysInMonth(isMO+1,isYR);
				// update UI and fix the date to be the last one in the month if greater
				var i2=childs.length;
				var item2;
				while(i2--){
					item2 = childs[i2];
					isDA = this.tester(isDA,item2,'D','csDay',0,daysInMonth,daysInMonth);
				} // end for
			} //end if (isDA...)
		}
		var p = CS.v3.down(node,'DIV.csDate-display');
		if(p){
			CS.v3.I18N.initialize(p);
			var pattern = CS.v3.I18N.getCustomAttributePattern(p);
			if(CS.v3.I18N.isEmpty(pattern)){
				pattern = 'EEEE, MMMM DD YYYY';
			}
			//this.log'update-pattern=' + pattern + '|' + isYR + '|' + isMO + '|' + isDA);
			var msg = CS.v3.I18N.pattern_replace(p,pattern,isTZ,isYR,isMO+1,isDA,isHR,isMN,isSE,isMS,isAP);
			var x = CS.v3.I18N.trimString(msg);
			//if(x!='-1'){
				p.update(msg);
			//}
		}
	},
	tester: function(rc,el,abbr,cls,minVal,maxVal,repVal){
		CS.v3.I18N.initialize(el);
		var b = CS.v3.I18N.isEmpty(repVal);
		var str = CS.v3.I18N.getValue(el,true);
		if(CS.v3.I18N.isEmpty(str)){
			str = '-1';
		}
		var pattern = '';
		if(abbr=='Y'){
			pattern = abbr + abbr + abbr + abbr;
		} else {
			pattern = abbr + abbr;
		}
		if(str){
			var valStr = CS.v3.I18N.parseCommon(el,str,pattern,abbr,'');
			var val = parseInt(valStr);
			if(val>=0){
				if(abbr=='M'){
					val = val - 1;
				}
				if(el.hasClassName(cls)){
					var tr = CS.v3.getParentElement(el,'TR');//el.up('TR');
					if((val>=minVal) && (val<=maxVal)){
						rc=val;
						CS.v3.I18N.removeError(tr);
					} else {
						if(b){
							CS.v3.I18N.addError(tr);
						} else {
							rc = repVal;
							CS.v3.I18N.setValue(el,repVal);
						}
					}
				}
			}
		}
		return rc;
	},
	log: function (s) {
		CS.v3.Logger.log("DatePicker:" + s);
	}
};
/* CALENDAR */
CS.v3.Components.Calendar = function(el,options) { new CS.v3.Config.Calendar(el,options);};
CS.v3.Config.Calendar = Class.create(CS.v3.Base.prototype, {
	initialize: function(el,options){
		this.allCalendars = CS.v3.Calendar.allCalendars(el);
		//this.bind();
		if (options.bind == 'true') {this.bind(); }
	},
	bind: function(){
		var ar = this.allCalendars;
		var i = ar.length;
		var el;
		while(i--){
			el = ar[i];
			CS.v3.Calendar.addDecoration(el);
			Event.observe(el,'change', function(event){ CS.v3.Calendar.changeCalendarEv(event); });
			Event.observe(el,'click', function(event){ CS.v3.Calendar.focusCalendarEv(event); });
			//Event.observe(el,'focus', function(event){ CS.v3.Calendar.focusCalendarEv(event); });
			//Event.observe(el,'blur', function(event){ CS.v3.Calendar.blurCalendarEv(event); });
		}
	}
});
CS.v3.Calendar = {
	allCalendars: function(el){
		return $(el).select("input[class*='csCalendar']");
	},
	addDecoration: function(input){
		var b=input.hasClassName('csCalendar-icon');
		if(!b){
			//input.wrap('DIV',{'class':'csCalendar-wrapper'} );
			//input.wrap('DIV',{'class':'csCalendarInput'});
			//input.wrap('DIV',{'class':'csCalendarInputWrap'});
			var node = this.findCalendarWrapper(input);
			CS.v3.I18N.initialize(node);
			CS.v3.I18N.initialize(input);
			input.addClassName('csCalendar-icon');
			Element.identify(input);//CS.v3.I18N.assertId(input,'calendar');
			var ipattern = this.getInputPattern(input);
			CS.v3.I18N.updateAttribute(input,'title',ipattern);
			//node.insert({bottom:'<div class=\"csCalendar-holder\"></div>'});
			node.insert({bottom:'<div class=\"csPanel csPanelCalendar\"></div>'});
			/* removed display 
			node.insert({bottom:'<div class=\"csCalendar-holder\"></div><div class=\"csCalendar-display\"></div>'});
			end removed display */
		}
		this.updateCalendar(input);
	},
	updateCalendar: function(input){
		//this.log('updateCalendar:init');
		/* removed display 
		var spanwrap = this.findCalendarWrapper(input);
		var p = CS.v3.down(spanwrap,'DIV.csCalendar-display');
		if(p){
			var displayPattern = this.getDisplayPattern(input);
			var pattern = CS.v3.I18N.getCustomAttributePattern(p,displayPattern);
			var str = CS.v3.I18N.getValue(input);
			var msg = '';
			var b = CS.v3.I18N.isEmpty(str);
			if(!b){
				CS.v3.I18N.initialize(p);
				var ipattern = this.getInputPattern(input);
				var calVal = this.getCurrentDate(input,ipattern);
				msg = CS.v3.I18N.pattern_obj(input,pattern,calVal);
			}
			var bm = CS.v3.I18N.isEmpty(msg);
			if(bm) {
				var ipattern = this.getInputPattern(input);
				msg = ipattern;
			}
			this.updateFix(p,msg)
		}
		end removed display */
		//this.log('updateCalendar:exit');
	},
	changeCalendarEv: function(event){
		var el = $(Event.element(event));
		if(el!=null){
			var tag = CS.v3.I18N.getTagName(el);
			if(tag == 'INPUT'){
				this.updateCalendar(el);
				this.hideCalendar(el);
			}
		}
	},
	focusCalendarEv: function(event){
		var el = $(Event.element(event));
		if(el!=null){
			var tag = CS.v3.I18N.getTagName(el);
			if(tag == 'INPUT'){
				this.showCalendar(el,'');
			}
		}
	},
	blurCalendarEv: function(event){
		var el = $(Event.element(event));
		if(el!=null){
			var tag = CS.v3.I18N.getTagName(el);
			if(tag == 'INPUT'){
				this.hideCalendar(el);
			}
		}
	},
	clickCalendarEv: function(event){
		var el = $(Event.element(event));
		if(el!=null){
			var tag = CS.v3.I18N.getTagName(el);
			if(tag == 'A'){
				var li = CS.v3.getParentElement(el,'LI');//el.up('LI');
				if(li){
					var isClose = li.hasClassName('csIconClose');
					if(isClose){
						this.hideCalendar(el);
						event.stop();
					}
				}
				var div = CS.v3.getParentElement(el,'DIV');//el.up('DIV');
				if(div){
					var isNext = div.hasClassName('csCalendar-next');
					var isPrev = div.hasClassName('csCalendar-previous');
					var valStr = div.getAttribute('title');
					var input = this.findCalendarInput(div);
					if(input){
						if(isNext){
							this.showCalendar(input,valStr);
							event.stop();
						} else {
							if(isPrev){
								this.showCalendar(input,valStr);
								event.stop();
							} else {
								this.clickCalendar(el,input);
								event.stop();
							}
						}
					}
				}
			}
		}
	},
	clickCalendar: function(el,input){
		//var val = CS.v3.I18N.getValue(el); //BUTTON
		var valStr = this.getCustomDataAttributeValue(el,''); // A(nchor)
		CS.v3.I18N.setValue(input,valStr);
		var processDays = this.getCustomAttributeProcessDays(input);
		if(processDays<1){
			this.hideCalendar(input);
		} else {
			this.updateCalendar(input);
			this.showCalendar(input,'');
			input.focus();
		}
		CS.v3.fireOnchange(input);
	},
	hideCalendar: function(el){
		var input = this.findCalendarInput(el);
		if(input){
			var spanwrap = this.findCalendarWrapper(input);
			CS.v3.styleZIndex.inactive(input,spanwrap);
			spanwrap.removeClassName('csCalendar-show');
			var spanafter = this.findCalendarDiv(spanwrap);
			this.updateFix(spanafter,''); // remove?
		}
	},
	getInputMonths2Show: function(el){
		var rc = 2;// NOTE: was '1'
		var b1=el.hasClassName('csOnemonth');
		if(b1){
			rc = 1;
		} else {
			var b2=el.hasClassName('csTwomonths');
			if(b2){
				rc = 2;
			}
		}
		return rc;
	},
	getInputWeeks2Show: function(el){
		var rc = false;
		var b=el.hasClassName('csWeeks');
		if(b){
			rc = true;
		}
		return rc;
	},
	getCurrentDate: function(el,pattern){
		//this.log('getCurrentDate:init');
		//var pattern = this.getInputPattern(el);
		//CS.v3.I18N.initialize(el);
		var dt_now = CS.v3.I18N.createDate();
		var rc = CS.v3.I18N.parseDateField(el,pattern,dt_now);
		//this.log('getCurrentDate:exit:rc=' + rc);
		return rc;
	},
	getAllHolidays: function(el){
		//this.log('getAllHolidays:init');
		var rc = null;
		var keys = this.getCustomDataAttributeCountry(el);
 		var b1 = CS.v3.I18N.isEmpty(keys);
 		if(!b1){
			var b2 = (el.hasClassName('csHolidays') || el.hasClassName('isNoHolidays'));
			if(b2){
				rc = this.findHolidays(el,keys);
			}
		}
		//this.log('getAllHolidays:exit');
		return rc;
	},
	showCalendar: function(el,valStr){
		//this.log('showCalendar:init');
		//try{
			this.hideOtherCalendars(el);
			var spanup = this.findCalendarWrapper(el);
			if(spanup){
				var spanafter = this.findCalendarDiv(spanup);
				CS.v3.I18N.initialize(el);
				var locale = CS.v3.I18N.getLocale(el);
				CS.v3.I18N.setLocale(spanafter,locale);
				var todayVal = CS.v3.I18N.createDate();
				var pattern = this.getInputPattern(el);
				var patternPaging = this.getPagingPattern(el); //'YYYYMMDD'
				//this.log('showCalendar:pattern=' + pattern);
				var months2show = this.getInputMonths2Show(el);
				var isShowWeek = this.getInputWeeks2Show(el);
				var currentVal;
				var bval = CS.v3.I18N.isEmpty(valStr);
				//this.log('showCalendar:valStr=' + valStr + '|bval=' + bval);
				if(bval){
					currentVal = this.getCurrentDate(el,pattern);
				} else {
					currentVal = CS.v3.I18N.parseDateFieldVal(el,valStr,patternPaging,todayVal);
				}
				//this.log('showCalendar:currentVal=' + currentVal);
				if((!currentVal) || currentVal=='Invalid Date'){ // NaN?
					this.log('showCalendar:bad date!');
					var tr = CS.v3.getParentElement(el,'TR');//el.up('TR');
					CS.v3.I18N.addError(tr);
				} else {
					//CS.v3.I18N.removeError(el);
					spanup.addClassName('csCalendar-show');
					CS.v3.styleZIndex.active(el,spanup);
					if (CS.v3.Base.prototype.coverIE) {
							var ieCover = el.readAttribute('data-ie6Cover');
							if (ieCover == 'true') {
							CS.v3.Base.prototype.coverIE(spanup);
						}
					}
					Event.observe(spanup,'click', function(event){ CS.v3.Calendar.clickCalendarEv(event); });
					var closeLabel = this.getCustomAttributeCloseLabel(el);
					//var valSummaryLabel = this.getCustomAttributeSummaryLabel(el);
					var startOnDOW = this.getCustomAttributeStartOnDOW(el);
					var processDays = this.getCustomAttributeProcessDays(el);
					var patternMonth = this.getHeaderPattern(el);//'MMMM YYYY'; // '(LL)'
					var patternTitle = this.getDisplayPattern(el);//'EEEE, MMMM DD YYYY';
					var patternDay = 'DD';
					var year = currentVal.getFullYear();
					var month = currentVal.getMonth()+1;
					var day = currentVal.getDate();
					var allHolidays = this.getAllHolidays(el);
					var calVal1 = CS.v3.I18N.setDateObj(year,month,1);// TODO is month correct here?
					var calValNext = this.getNextMonth(calVal1);
					var calValPrev = this.getPrevMonth(calVal1);
					var calHolidays1 = this.filterHolidays(el,allHolidays,calVal1);
					var calN = CS.v3.I18N.pattern_obj(el,patternPaging,calValNext);
					var calP = CS.v3.I18N.pattern_obj(el,patternPaging,calValPrev);
					var msgPrev = '<div class=\"csCalendar-previous\" title=\"' + calP + '\"><a href=\"#\">&nbsp;</a></div>\n';
					var msgNext = '<div class=\"csCalendar-next\" title=\"' + calN + '\"><a href=\"#\">&nbsp;</a></div>\n';
					var NBSP = '&nbsp;';
					var msg1Left = msgPrev;
					var msg1Right = NBSP;
					var msg2Left = NBSP;
					var msg2Right = NBSP;
					if(months2show==1){
						msg1Right = msgNext;
					}
					if(months2show==2){
						msg2Right = msgNext;
					}
					var caldays = CS.v3.I18N.findArray(el,patternDay);
					var cal1 = this.getCalendar(el,pattern,patternTitle,patternMonth,caldays,calVal1,currentVal,todayVal,calHolidays1,isShowWeek,startOnDOW,processDays,msg1Left,msg1Right);
					var sb = new StringBuffer();
					sb.append("<div class=\"csPanelTopLeft\"><div class=\"csPanelTopRight\"><div class=\"csPanelContent\"><div class=\"csPanelScroll\"><div class=\"csRow csCols-2 csCalendarControls\" dir=\"ltr\"><div class=\"csCol-1\">");
					if(processDays>0){
						var valSendLabel = this.getCustomAttributeSendLabel(el);
						var valArriveLabel = this.getCustomAttributeArriveLabel(el);
						sb.append("<div class=\"csNav-x\"><ul class=\"csNavList\"><li class=\"csNavItem-0 csNavFirst csNavIcon csCalendar-sendLabel\"><div class=\"csNavWrap\"><a href=\"#\">");
						sb.append(valSendLabel);
						sb.append("</a></div></li><li class=\"csNavItem-0 csNavLast csNavIcon csCalendar-arriveLabel\"><div class=\"csNavWrap\"><a href=\"#\">");
						sb.append(valArriveLabel);
						sb.append("</a></div></li></ul></div>");
					}
					sb.append("</div><div class=\"csCol-2\"><div class=\"csNav-x\"><ul class=\"csNavList\"><li class=\"csNavItem-0 csNavFirst csNavIcon csIconClose\"><div class=\"csNavWrap\"><a href=\"#\">");
					sb.append(closeLabel);
					sb.append("</a></div></li></ul></div></div></div><div class=\"csRow csCols-2\"><div class=\"csCol-1\">");
					sb.append(cal1);
					sb.append("</div>");// col-1
					if(months2show==2){
						var calVal2 = this.getNextMonth(calVal1);
						var calHolidays2 = this.filterHolidays(el,allHolidays,calVal2);
						var cal2 = this.getCalendar(el,pattern,patternTitle,patternMonth,caldays,calVal2,currentVal,todayVal,calHolidays2,isShowWeek,startOnDOW,processDays,msg2Left,msg2Right);
						sb.append("<div class=\"csCol-2\">");
						sb.append(cal2)
						sb.append("</div>");
					}
					sb.append("</div></div></div></div></div><div class=\"csPanelBottomLeft\"><div class=\"csPanelBottomRight\"></div></div>");
					var msg = sb.toString();
					this.updateFix(spanafter,msg);
				}
			}
		//}
		//catch(e){
		//	this.log('showCalendar:e=' + e);
		//}
		//this.log('showCalendar:exit');
	},
	getCalendar: function(el,pattern,patternTitle,patternMonth,caldays,calVal,currentVal,todayVal,calHolidays,isShowWeek,startOnDOW,processDays,msgLeft,msgRight){
		//var tz = calVal.getTimezoneOffset();
		var year = calVal.getFullYear();
		var month = calVal.getMonth() + 1;
		var dow = calVal.getDay();
		var cal = parseInt(1-dow);
		var NBSP = "&nbsp;";
		// TODO implement ... startOnDOW
		CS.v3.I18N.initialize(el);
		var month_year = CS.v3.I18N.pattern_obj(el,patternMonth,calVal);
		var isHideWeekend = el.hasClassName('isNoWeekends');
		var isHideHoliday = el.hasClassName('isNoHolidays');
		var isHidePast = el.hasClassName('isNoPast');
		var isHideFuture = el.hasClassName('isNoFuture');
		var isHideToday = el.hasClassName('isNoToday');
		var isHideSend = el.hasClassName('isNoSend');
		var isHideArrive = el.hasClassName('isNoArrive');
		var sendVal = currentVal;
		var arriveVal = this._getArriveDate(el,sendVal,processDays,calHolidays);
		var cols = 7;
		var colWidth='14%';
		if(isShowWeek){
			cols = 8;
			colWidth='12.5%';
		}
		var ddd = CS.v3.I18N.findArray(el,'DDD');
		var startdow = 0;//startOnDOW;
		if(cols==8){ 
			startdow = startonDOW-1;
		}
		var colspan = cols-2;
		var msg;
		var isPast;
		var isFuture;
		var isSend;
		var isArrive;
		var isToday;
		var isShow;
		var isCurrent;
		var da;
		var x;
		var bm;
		var weekrow;
		var dt;
		var dd;
		var wk;
		var msg;
		var val;
		var arCssClass;
		var cssClass;
		var arTitle;
		var titles;
		var title;
		var label;
		var calMonth;
		var holidayStr;
		var isWeekend;
		var isHoliday;
		var calVal;
		var idx;
		var i;
		var sb = new StringBuffer();
		sb.append("<table class=\"csTableCalendar\" cellspacing=\"0\" dir=\"ltr\"><colgroup>");
		i = cols;
		while(i--){
			sb.append('<col style=\"width:');
			sb.append(colWidth);
			sb.append(';\" />');
		}
		sb.append("</colgroup><thead><tr class=\"csMonth\"><th>");
		sb.append(msgLeft);
		sb.append("</th><th scope=\"col\" colspan=\"");
		sb.append(colspan);
		sb.append("\">");
		sb.append(month_year);
		sb.append("</th><th>");
		sb.append(msgRight);
		sb.append("</th></tr><tr class=\"csDay\">");
		i = cols;
		while(i--){
			arCssClass = new Array();
			msg = null;
			da = 6-i;
			//arCssClass.push('d'+ d);
			//arCssClass.push('i'+ i);
			if(da==0){ arCssClass.push('csWeekend-sun'); }
			if(da==6){ arCssClass.push('csWeekend-sat'); }
			if(i==0){ arCssClass.push('csLast'); }
			if(i==cols-1){ arCssClass.push('csFirst'); }
			if(i==8){
				//msg=NBSP;
				arCssClass.push('csWeek');
			} else { 
				msg = ddd[da];
			}
			sb.append("<th scope=\"col\"");
			x = arCssClass.length;
			if(x>0){
				sb.append(" class=\"");
				while(x--){
					cssClass = arCssClass[x];
					sb.append(cssClass);
					sb.append(' ');
				}
				sb.append("\"");
			}
			sb.append(">");
			bm = CS.v3.I18N.isEmpty(msg);
			if(bm){
				sb.append(NBSP);
			} else {
				sb.append(msg);
			}
			sb.append("</th>");
		}
		sb.append("</tr></thead><tbody>");
		var start = 0;
		if(cols==8){
			start = -1;
		}
		for(idx=0; idx<36; idx=idx+7){
			sb.append("<tr>");
			i = cols;
			while(i--){
				//da = cal + idx + i;
				da = cal + idx + (6-i);
				arCssClass = new Array();
				arTitle = new Array();
				calVal = CS.v3.I18N.setDateObj(year,month,da);
				if(i==cols-1){ arCssClass.push('csFirst'); }
				if(i==0){ arCssClass.push('csLast'); }
				if(i==cols){
					arCssClass.push('csWeek');
					wk = CS.v3.I18N.getWeek(el,calVal);
					sb.append('<td');
					x = arCssClass.length;
					if(x>0){
						sb.append(" class=\"");
						while(x--){
							cssClass = arCssClass[x];
							sb.append(cssClass);
							sb.append(' ');
						}
					}
					sb.append('\">');
					sb.append(wk);
				} else {
					calMonth = calVal.getMonth()+1; // to see if we've rolled months!
					//isCurrent = false;
					//isPast = false;
					//isFuture = false;
					//isSend = false;
					//isArrive = false;
					//isToday = false;
					isShow = false;
					if(month == calMonth){
						isShow = true;
						if(processDays>0){
							isSend = CS.v3.I18N.equalDates(calVal,sendVal);
							if(isSend){
								arCssClass.push('csDate-send');
								label = this.getCustomAttributeSendLabel(el);
								arTitle.push(label);
								if(isHideSend){ isShow = false; }
							}
							isArrive = CS.v3.I18N.equalDates(calVal,arriveVal);
							if(isArrive){
								arCssClass.push('csDate-arrive');
								label = this.getCustomAttributeArriveLabel(el);
								arTitle.push(label);
								if(isHideArrive){ isShow = false; }
							}
						}
						isCurrent = CS.v3.I18N.equalDates(calVal,currentVal);
						if(isCurrent){
							arCssClass.push('csDate-current');
							label = this.getCustomAttributeCurrentLabel(el);
							arTitle.push(label);
						}
						isToday = CS.v3.I18N.equalDates(calVal,todayVal);
						if(isToday){
							arCssClass.push('csDate-today');
							label = this.getCustomAttributeTodayLabel(el);
							arTitle.push(label);
							if(isHideToday){ isShow = false; }
						} else {
							var calTime = calVal.getTime();
							var todTime = todayVal.getTime();
							isPast = calTime<todTime;
							if(isPast){
								arCssClass.push('csDate-past');
								if(isHidePast){ isShow = false; }
							} else {
								isFuture = calTime>todTime;
								if(isFuture){
									arCssClass.push('csDate-future');
									if(isHideFuture){ isShow = false; }
								}
							}
						}
						isWeekend = this._isWeekend(calVal);
						if(isWeekend){
							arCssClass.push('csDate-weekend');
							if(isHideWeekend){ isShow = false; }
						}
						
						holidayStr = this.getHoliday(el,calHolidays,calVal);
						isHoliday = !CS.v3.I18N.isEmpty(holidayStr);
						if(isHoliday){
							arCssClass.push('csDate-holiday');
							arTitle.push(holidayStr);
							if(isHideHoliday){ isShow = false; }
						}
					}
					if(isShow){
						//title = CS.v3.I18N.pattern_obj(el,patternTitle,calVal);
						//arTitle.push(title);
					} else {
						arCssClass.push('csDate-noDate');
					}
				}
				sb.append("<td");
				var x = arCssClass.length;
				if(x>0){
					sb.append(" class=\"");
					while(x--){
						cssClass = arCssClass[x];
						sb.append(cssClass);
						sb.append(' ');
					}
					sb.append("\"");
				}
				titles = arTitle.length;
				if(titles>0){
					sb.append(" title=\"");
					while(titles--){
						title = arTitle[titles];
						sb.append(title);
						sb.append(' ');
					}
					sb.append("\"");
				}
				sb.append(">");
				//CS.v3.I18N.initialize(el);
				if(isShow){
					dd = calVal.getDate() -1;
					msg = caldays[dd];//CS.v3.I18N.pattern_cal(el,patternDay,calVal);
					val = CS.v3.I18N.pattern_cal(el,pattern,calVal);
					sb.append("<a href=\"#\" data-csValue=\"");
					sb.append(val);
					sb.append("\">"); // HTML5
					sb.append(msg);
					sb.append("</a>");
				} else {
					sb.append(NBSP);
				}
				sb.append("</td>");
			}
			sb.append("</tr>");
		}
		sb.append("</tbody></table>");
		var rc = sb.toString();
		return rc;
	},
	findHolidays: function(el,keys){
		//this.log('findHolidays:init');
		var rc = null;
		var ar = this.deriveCountries(keys);
		//var ar = this.deriveCountriesFromLocale(keys);
		if(ar){
			//var sb = new StringBuffer();
			var i = ar.length;
			var country;
			var b;
			var str;
			var key;
			var ar2;
			while(rc==null && i--){
				country = ar[i];
				b = CS.v3.I18N.isEmpty(country);
				if(!b){
					key = this._makeHolidayKey(country);
					ar2 = CS.v3.I18N.findProperty(el,key);
					rc = CS.v3.I18N.mergeArrays(rc,ar2);
					//sb.append(str);
				}
			}
			//rc = sb.toString();
		}
		//this.log('findHolidays:exit');
		return rc;
	},
	_makeHolidayKey: function(country){
		var rc = 'CalendarHolidays';
		var b = CS.v3.I18N.isEmpty(country);
		if(!b){
			rc += '-';
			rc += country;
		}
		return rc;
	},
	deriveCountries: function(keys){
		var rc = null;
		var bc = CS.v3.I18N.isEmpty(keys);
		if(!bc){
			var COMMA = ',';
			var SPACE = ' ';
			var clean = CS.v3.I18N.replaceString(keys,COMMA,SPACE);
			var ar = clean.split(SPACE);
			var i = ar.length;
			if(i>0){
				rc = new Array();
				var country;
				var b;
				while(i--){
					country = ar[i];
					b = CS.v3.I18N.isEmpty(country);
					if(!b){
						rc.push(country);
					}
				}
			}
		}
		return rc;
	},
	deriveCountriesFromLocale: function(locale){
		var rc = '';
		var bl = CS.v3.I18N.isEmpty(locale);
		var country = '';
		if(!bl){
			var DASH = '-';
			var SCORE = '_';
			var clean = CS.v3.I18N.replaceString(locale,DASH,SCORE);
			var ar = clean.split(SCORE);
			var language = ar[0];
			country = ar[1];
		}
		var def = CS.v3.I18NDefaultLocale;//'default';
		var bc = CS.v3.I18N.isEmpty(country);
		if(!bc){
			rc = new Array(def,country);
		} else {
			rc = new Array(def);
		}
		return rc;
	},
	getHoliday: function(el, ar, dt_cal){
		var rc = '';
		if(ar!=null){
			var EQUALS = '=';
			//CS.v3.I18N.initialize(el);
			var pagingPattern = this.getPagingPattern(el);
			var obj;
			var item;
			var dateStr;
			var title;
			var dt_hol;
			var i = ar.length;
			while(i--){
				obj = ar[i];
				item = obj.split(EQUALS);
				dateStr = item[0];
				title = item[1];
				dt_hol = CS.v3.I18N.parseDateFieldVal(el,dateStr,pagingPattern,dt_cal);
				var b = CS.v3.I18N.equalDates(dt_hol,dt_cal);
				if(b){
					rc += title;
				}
			}
		}
		return rc;
	},
	_getArriveDate: function(el,dt,processDays,calHolidays){
		var rc = null;
		if(processDays>0){
			rc = this._getIncrDays(dt,processDays);
			var holidayStr = this.getHoliday(el,calHolidays,rc);
			var isHoliday = !CS.v3.I18N.isEmpty(holidayStr);
			var isWeekend = this._isWeekend(rc);
			while(isHoliday || isWeekend){
				rc = this._getIncrDays(rc,1);
				holidayStr = this.getHoliday(el,calHolidays,rc);
				isHoliday = !CS.v3.I18N.isEmpty(holidayStr);
				isWeekend = this._isWeekend(rc);
			}
		}
		return rc;
	},
	_isWeekend: function(dt){
		var rc = false;
		if(dt){
			var dow = dt.getDay(); 
			rc = (dow == 0 || dow == 6);
		}
		return rc;
	},
	_getIncrDays: function(dt,val){
		var dayOld = dt.getDate();
		var dayNew = parseInt(dayOld) + parseInt(val);
		var rc = new Date(dt.getFullYear(),dt.getMonth(),dayNew);
		return rc;
	},
	getNextMonth: function(dt){
		var rc = new Date(dt.getFullYear(),dt.getMonth()+1,dt.getDate());
		return rc;
	},
	getPrevMonth: function(dt){
		var rc = new Date(dt.getFullYear(),dt.getMonth()-1,dt.getDate());
		return rc;
	},
	getPagingPattern: function(el){
		return 'YYYYMMDD';
	},
	getHolidayPattern: function(el){
		return 'YYYYMM';
	},
	getInputPattern: function(el){
		var def = CS.v3.I18N.findProperty(el,'Calendar-inputPattern');
		var rc = CS.v3.I18N.getCustomAttributePattern(el,def);
		return rc;
	},
	getCustomDataAttributeCountry: function(el,def){
		var rc = CS.v3.I18N.getDataAttribute(el,'data-csCountry',def);// HTML5
		return rc;
	},
	getCustomDataAttributeValue: function(el,def){
		var rc = CS.v3.I18N.getDataAttribute(el,'data-csValue',def);// HTML5
		return rc;
	},
	getDisplayPattern: function(el){
		var def = CS.v3.I18N.findProperty(el,'Calendar-displayPattern');
		var rc = CS.v3.I18N.getDataAttribute(el,'data-csDisplayPattern',def);// HTML5
		return rc;
	},
	getHeaderPattern: function(el){
		var def = CS.v3.I18N.findProperty(el,'Calendar-headerPattern');
		var rc = CS.v3.I18N.getDataAttribute(el,'data-csHeaderPattern',def);// HTML5
		return rc;
	},
	getCustomAttributeProcessDays: function(el){
		var def = CS.v3.I18N.findProperty(el,'Calendar-processDays'); //0
		var rc = CS.v3.I18N.getDataAttribute(el,'data-csProcessdays',def);// HTML5
		return rc;
	},
	getCustomAttributeStartOnDOW: function(el){
		var def = CS.v3.I18N.findProperty(el,'Calendar-startDow'); // '0' = sunday in JS!
		var rc = CS.v3.I18N.getDataAttribute(el,'data-csStartDow',def);// HTML5
		return rc;
	},
	getCustomAttributeCloseLabel: function(el){
		var def = CS.v3.I18N.findProperty(el,'Calendar-closeLabel');
		var rc = CS.v3.I18N.getDataAttribute(el,'data-csCloseLabel',def);// HTML5
		return rc;
	},
	getCustomAttributeSummaryLabel: function(el,def){
		var def = CS.v3.I18N.findProperty(el,'Calendar-summaryLabel');
		var rc = CS.v3.I18N.getDataAttribute(el,'data-csSummaryLabel',def);// HTML5
		return rc;
	},
	getCustomAttributeSendLabel: function(el){
		var def = CS.v3.I18N.findProperty(el,'Calendar-sendLabel');
		var rc = CS.v3.I18N.getDataAttribute(el,'data-csSendLabel',def);// HTML5
		return rc;
	},
	getCustomAttributeArriveLabel: function(el){
		var def = CS.v3.I18N.findProperty(el,'Calendar-arriveLabel');
		var rc = CS.v3.I18N.getDataAttribute(el,'data-csArriveLabel',def);// HTML5
		return rc;
	},
	getCustomAttributeTodayLabel: function(el){
		var def = CS.v3.I18N.findProperty(el,'Calendar-todayLabel');
		var rc = CS.v3.I18N.getDataAttribute(el,'data-csTodayLabel',def);// HTML5
		return rc;
	},
	getCustomAttributeCurrentLabel: function(el){
		var def = CS.v3.I18N.findProperty(el,'Calendar-currentLabel');
		var rc = CS.v3.I18N.getDataAttribute(el,'data-csCurrentLabel',def);// HTML5
		return rc;
	},
	filterHolidays: function(el,ar,calVal){
		//this.log('filterHolidays:init:calVal=' + calVal);
		var rc = new Array();
		if(calVal!=null){
			var patternHolidayFilter = this.getHolidayPattern(el);
			var startYYYYMM = CS.v3.I18N.pattern_obj(el,patternHolidayFilter,calVal);
			//if(ar){
			var b = Object.isArray(ar);
			if(b){
				var obj;
				var i = ar.length;
				var year = calVal.getFullYear();
				var dateStr;
				var dateStartsWith;
				while(i--){
					obj = ar[i];
					dateStr = obj.replace('####',year);
					dateStartsWith = CS.v3.I18N.truncateString(dateStr,6);
					if(dateStartsWith == startYYYYMM){
						rc.push(dateStr);
					}
				}
			}
			//}
		}
		//this.log('filterHolidays:exit');
		return rc;
	},
	hideOtherCalendars: function(el){
		var body = document.body;// could limit to the form if we chose
		var ar = this.allCalendars(body);
		var i = ar.length;
		if(i>1){
			var myid = el.readAttribute('id');
			var obj;
			var objid;
			while(i--){
				obj = ar[i];
				objid = obj.readAttribute('id');
				if(objid!=myid){
					this.hideCalendar(obj);
				}
			}
		}
	},
	updateFix: function(el,str){
		//el.update(str);
		el.innerHTML = str
	},
	findCalendarWrapper: function(el){
		var rc;
		if(el){
			rc = CS.v3.up(el,'DIV.csCalendar-wrapper');
		}
		return rc;
	},
	findCalendarInput: function(el){
		var rc;
		var spanwrap = this.findCalendarWrapper(el);
		if(spanwrap){
			var divinput = CS.v3.down(spanwrap,'DIV.csCalendarInput');
			if(divinput){
				rc = CS.v3.down(divinput,'INPUT');
			}
		}
		return rc;
	},
	findCalendarDiv: function(el){
		var rc;
		if(el){
			rc = CS.v3.down(el,'DIV.csPanelCalendar');
		}
		return rc;
	},
	log: function (s){
		CS.v3.Logger.log("Calendar:" + s);
	}
};
CS.v3.I18N.addProperty('Calendar-inputPattern','','MM/DD/YYYY');
CS.v3.I18N.addProperty('Calendar-displayPattern','','EEEE, MMMM DD YYYY');
CS.v3.I18N.addProperty('Calendar-headerPattern','','MMMM YYYY');
CS.v3.I18N.addProperty('Calendar-closeLabel','','Close Calendar');
//CS.v3.I18N.addProperty('Calendar-summaryLabel','','Summary');
CS.v3.I18N.addProperty('Calendar-arriveLabel','','Arrive Date');
CS.v3.I18N.addProperty('Calendar-closeLabel','','Close');
CS.v3.I18N.addProperty('Calendar-currentLabel','','(current)');
CS.v3.I18N.addProperty('Calendar-sendLabel','','Send Date');
CS.v3.I18N.addProperty('Calendar-todayLabel','','(today)');
CS.v3.I18N.addProperty('Calendar-processDays','','0');
CS.v3.I18N.addProperty('Calendar-startDow','','0');
CS.v3.I18N.addProperty('CalendarHolidays','',null);
CS.v3.I18N.addProperty('CalendarHolidays-US','',new Array("####0101=New Year's Day",
									   "20090119=Martin Luther King Jr. Day",
									   "20090216=Presidents Day",
									   "20090525=Memorial Day",
									   "20090703=Independence Day (Observed)",
									   "####0704=Independence Day",
									   "20090907=Labor Day",
									   "20091012=Columbus Day",
									   "####1111=Veteran's Day",
									   "20091126=Thanksgiving Day",
									   "####1225=Christmas Day"));
CS.v3.I18N.addProperty('CalendarHolidays-CA','',new Array("####0101=New Year's Day",
									   "20090701=Canada Day",
									   "####1225=Christmas Day"));
CS.v3.I18N.addProperty('CalendarHolidays-CN','',new Array("20090126=Chinese New Year 2009",
									   "20100214=Chinese New Year 2010"));
CS.v3.I18N.addProperty('CalendarHolidays-FR','',new Array("####0101=Jour de l‚Äôan",
										"20090413=Lundi de P√¢ques",
										"####0501=F√™te du Travail",
										"####0508=F√™te de la Victoire 1945",
										"20090521=jeudi de l'Ascension",
										"20090601=Lundi de Pentec√¥te",
										"####0714=F√™te nationale",
										"####0815=Assomption",
										"####1101=Toussaint",
										"####1111=Armistice",
			  							"####1225=No√´l"));
