if (typeof CSDC == "undefined") {
	CSDC = function() {
		// private
		sendRequestSuccessHandler = function(o)
		{
			if (CSDC.util)
				CSDC.util.hideWait();
			if (o.argument.disableBtns)
				CSDC.disable(false, o.argument.disableBtns);
			var JSONData = YAHOO.lang.JSON.parse(o.responseText);
			if (JSONData.Error)
			{
				if (o.argument.errorInDlg)
					displayError(JSONData.Error);
				else if(o.argument.failureFcn && o.argument.customError)
					o.argument.failureFcn.apply(this, [JSONData.Error]);
				else
					displayErrorInPage(JSONData.Error);
			}
			else if( JSONData.login )
			{
				showLoginDialog(JSONData);
			}
			else
				o.argument.successFcn.apply(this, [JSONData] );
		}	
		
		sendRequestFailureHandler = function(o)
		{
			CSDC.util.hideWait();
			if (o.argument && o.argument.disableBtns)
				CSDC.disable(false, o.argument.disableBtns);
			o.argument.failureFcn.apply(this, [o.statusText] );
		}
		
		sendFileSuccessHandler = function(o)
		{
			// response to a file upload request somehow gets wrapped inside a <pre> tag inside the yui code somewhere - we need to extract it before we can use it!
			var responseText = o.responseText;
			CSDC.util.hideWait();
			if(CSDC.progressdlg) CSDC.progressdlg.close();
			//look for errors
			if(responseText.indexOf('nginx')!=-1){
				var errorText, errorCode;
				if (responseText.indexOf('413') != -1) {
					errorText='The file you tried to upload is too big.';
					errorCode='413';
				}else{
					errorText='There was a problem when uploading your file';
					errorCode='1';
				}
				
				if(o.argument.failureFcn && o.argument.customError)
					o.argument.failureFcn.apply(this, [errorText,errorCode]);
				else
					displayError(errorText);
			}else{
				var realResponseText = responseText.replace( /<(.|\n)*?>/gi, '' );
				o.responseText = realResponseText;
				sendRequestSuccessHandler( o );
			}
		}	
		
		// public functions
		return {
		lnkOpenClub : function(id){
			return "../jsp/club.jsp?cid=" + id;
		},
		lnkOpenLibrary : function(id){
			var query = (id!=null)? '?cid='+id : '';
			return '../jsp/collectionlist.jsp'+query;
		},
		lnkOpenCollection : function (id) {
			var link="../jsp/collection.jsp?id=" + id;
			return link;
		},
		lnkOpenPhoto : function (id) {
			var link="../jsp/photo.jsp?id=" + id;
			return link;
		},
		lnkOpenVideo : function (id) {
			return "../jsp/video.jsp?id=" + id;
		},
		lnkOpenDocument : function(id) {
			var link="../jsp/document.jsp?id=" + id;
			return link;
		},
		lnkOpenUser : function(id) {
			return "../jsp/user.jsp?uid=" + id;
		},
		lnkOpenEvent : function(id,calId) {
			var extraArgs = (calId )? "&calid=" + calId : "";
			return "../jsp/event.jsp?eid=" + id + extraArgs;
		},
		lnkOpenEditEvent : function(id,calId) {
			var extraArgs = (calId )? "&calid=" + calId : "";
			return "../jsp/eventabout.jsp?eid=" + id + extraArgs;
		},
		lnkOpenPostList : function(id){
			var query = (id!=null)? '?cid='+id : '';
			return '../jsp/discussions.jsp'+query;
		},
		lnkOpenFriendPostList : function(id){
			var query = (id!=null)? '?uid='+id : '';
			return '../jsp/userdiscussions.jsp'+query;
		},
		lnkOpenPost : function(id,qcontext){
			var query='id='+id;
			if(qcontext && qcontext.EntityType==EntityType_Club) query+='&cid='+qcontext.Id;
			return '../jsp/topic.jsp?'+query;
		},
		lnkOpenMembers : function(id){
			var query = (id!=null)? '?cid='+id : '';
			return '../jsp/members.jsp'+query;
		},
		lnkOpenSignups : function(id){
			var query = (id!=null)? '?cid='+id : '';
			return '../jsp/signuplist.jsp'+query;
		},
		lnkOpenSayings : function( cid ) {
			var query;
			if( cid )
				query = '../jsp/groupsayings.jsp?cid=' + cid;
			else
				query = '../jsp/sayings.jsp';
			return query;
		},
		lnkOpenCalendar : function(id){
			var query = (id!=null)? '?cid='+id : '';
			return '../jsp/calendar.jsp'+query;
		},
		lnkOpenAssignments : function(id){
			var query = (id!=null)? '?cid='+id : '';
			return '../jsp/assignments_week.jsp'+query;
		},

		 /**
		 * shortcut function for document.createElement() that accepts name=value pair arguments to specify attributes
		 * 
		 * 
		 * Example: CSDC.createElt('a', 'myId', 'myClass', 'My Link', 'href=#','style=float:left');
		 * will generate: <a href="#" class="myClass" id="myId" style="float:left">My Link<a>
		 * 
		 * only the first param is mandatory, all others params are optionals.
		 */
	 		createElt : function(ele, id, className, innerText, params) {
				var its = CSDC.createElt.arguments.length;
				elt = document.createElement(ele);
				if (id)
					elt.id = id;
				if (className)
					elt.className = className;
				
				for(i=4;i<its;i++) {
					if (CSDC.createElt.arguments[i]) {
						var att = CSDC.createElt.arguments[i].split("=");
						if (YAHOO.env.ua.ie > 0 && att[0]==="style") {elt.style.setAttribute('cssText',att[1]);}
						else elt.setAttribute(att[0],att[1]);
					}
				}
			
				if (innerText)
					elt.appendChild(document.createTextNode(innerText));
				return elt;
			},
			/**
			 *	makeDom: Slight variation of the createElt function.
			 *  Y.R.
			 *	Will generate an HTMLElement, but will also append to it other elements sent in the arrChildren array.
			 *	Example: 
			 *	myElement = CSDC.makeDom("div",{ id:this.id, className:"myClass",style:"color:red"	} ,
			 *										[	aFirstChildnode,
			 *											aSecondChildNode	]	);
			 */
			makeDom : function (szEle/*:String*/, oParam/*:Object*/, arrChildren/*:domElement[]*/)/*:domElement*/{
				var elt = document.createElement(szEle);
				for (var key in oParam) {
					if (key === "innerText")
						elt.appendChild(document.createTextNode(oParam[key]));
					else if (key === "innerHTML")
						elt.innerHTML=oParam[key];
					else if (key === "className")
						elt.className = oParam[key];
					else if (YAHOO.env.ua.ie > 0 && key === "style")
						elt.style.setAttribute('cssText', oParam[key]);
					else 
						elt.setAttribute(key, oParam[key]);
				}
				if(typeof arrChildren==="string"){
					elt.appendChild(document.createTextNode(arrChildren));
				}else{
					if(arrChildren){
						var j=arrChildren.length;
						for(var i=0;i<j;i++){
							elt.appendChild(arrChildren[i]);
						}
					}
				}
				return elt;
			},
			/**********************************************
			 * CSDC.getElt(id) : document.getElementById(id)
			 **********************************************/
			getElt : function(id) {
				return YAHOO.util.Dom.get( id );
			},
			setText: function(id, text) {
				var elt = CSDC.getElt(id);
				elt.innerHTML = "";
				if(typeof text==="string"){
					var txts = text.split("\n");
					for (var ii in txts) {
						if (ii > 0)
							elt.appendChild(document.createElement('br'));
						elt.appendChild(document.createTextNode(txts[ii]));
					}
				}
				else
						elt.appendChild(document.createTextNode(text));
			},
			
			setChild: function(id, eltChild) {
				var elt = CSDC.getElt(id);
				elt.innerHTML = "";
				elt.appendChild(eltChild);
			},
			removeElt: function(elt){
				if(elt.parentNode!==null){
					elt.parentNode.removeChild(elt);
				}
			},
			maxLength: function(obj, MaxLen)
			{
				if (obj.getAttribute && obj.value.length>MaxLen){
					obj.value=obj.value.substring(0,MaxLen)
					return false;
				}else{
					return true;
				}
			},
			disable: function (b, ids)
			{
				for (var ii=0;ii<ids.length;ii++) {
					var id = ids[ii];
					if (id && id[0] == '.')
						YAHOO.util.Dom.getElementsByClassName(id.substring(1), "*" , null, function(elt) { elt.disabled = b; });
					else
						CSDC.getElt(ids[ii]).disabled = b;
				}
			},
			// parameters for oConfig: { scope:obj, failureFcn:fcn, errorInDlg:boolean)
			submit: function(postdata, successFcn, disableBtns,oConfig)
			{
				if(!oConfig) oConfig={};
				oConfig.disableBtns=disableBtns || ['idButtonSubmit', 'idButtonCancel'];
				CSDC.send (postdata, successFcn, oConfig);
			},
			send: function( postdata, successFcn, oConfig )
			{
				CSDC.util.showWait();
				oConfig = oConfig || { };
				if (oConfig.disableBtns)
					CSDC.disable(true, oConfig.disableBtns);
				
				if( !oConfig.failureFcn )
					oConfig.failureFcn = displayError;
				if(!oConfig.customError)
					oConfig.customError=false;
//				postdata += '&async=' + document.location.pathname + escape(document.location.search);
				postdata += '&async=' + escape(document.location.href);
				return YAHOO.util.Connect.asyncRequest('POST', "../Servlet/Command", { success:sendRequestSuccessHandler, failure:sendRequestFailureHandler, argument: { "successFcn": successFcn, "failureFcn": oConfig.failureFcn, "errorInDlg":oConfig.errorInDlg, "disableBtns":oConfig.disableBtns,customError:oConfig.customError }, scope: oConfig.scope }, postdata );
			},
			sendFile: function( elForm, successFcn, oConfig )
			{
				CSDC.util.showWait();
				oConfig = oConfig || { };
				if( oConfig.disableBtns )
					CSDC.disable( true, oConfig.disableBtns );
				
				if( !oConfig.failureFcn )
					oConfig.failureFcn = displayError;
				if(!oConfig.customError)
					oConfig.customError=false;
//TODO	need to set this in case need to login			postdata += '&async=' + escape(document.location.href);
				// the second argument is true to indicate file upload. 
				YAHOO.util.Connect.setForm( elForm, true ); 
				return YAHOO.util.Connect.asyncRequest('POST', elForm.action, { upload:sendFileSuccessHandler, failure:sendRequestFailureHandler, argument: { "successFcn": successFcn, "failureFcn": oConfig.failureFcn, "errorInDlg":oConfig.errorInDlg, "disableBtns":oConfig.disableBtns,customError:oConfig.customError }, scope: oConfig.scope } );
			},
				/**
 				* gtMsg : finds localized message. Usage : gtMsg("MY_LABEL"); returns $MSG_MY_LABEL$ if not found.
 				* Y.R.
 				* @param {String} :(Mandatory) label name
 				* @returns : label string
 				* @type {String}
 				*/
			gtMsg : function(szLabel /*:String*/) /*:String*/{
				var szFullLabel="MSG_"+szLabel;
				return window[szFullLabel]||'$'+szFullLabel+'$';
			},
				/**
 				* gtMsgWInfo : finds localized message and add extra info. 
 				* Y.R.
 				* Usage : 	var MSG_MYLABEL="You have %nbmsg% message%plural%";
 				* 			var myInfo = { nbmsg:200, plural:"s" };
 				* 			alert(CSDC.gtMsgWInfo({szLabel:"MYLABEL",oInfo:myInfo}));
 				* @param {Object} :(Mandatory) Object composed  of :
 				*						- {String} szLabel : label name
 				*						- {Object} oInfo : hashmap of name / value pairs.
 				* @returns : label string
 				* @type {String}
 				*/
			gtMsgWInfo : function(oParams /*:Object*/) /*:String*/{
				var myLabel=CSDC.gtMsg(oParams.szLabel);
				for(var szInfoName in oParams.oInfo){
					myLabel=myLabel.replace('%'+szInfoName+'%', oParams.oInfo[szInfoName]);
				}
				return myLabel;
			},
			setValue : function(id, value) {
				CSDC.getElt( id ).value = value ? value : "";
			},
			/**
			 * forEach is a shortcut for "for" loops applied on arrays.
			 * Y.R.
			 * It will go throught all elements of the array and pass them as parameter of the callback function, along with the element index.
			 * The function can also be binded to a specific object (default is "window").
			 * 
			 * If the callback function returns a "truth-y" value, forEach will stop and return the current element.
			 * This is useful when trying to return the first element of an array responding to specific conditions.
			 * 
			 * ex :
			 * 
			 * var oLastEvent=null;
			 * for(var i=0,len=arrayEvents.length; i<len ; i++){
			 *  if(myCalendar.isLastEvent(arrayEvents[i]){
			 *  	oLastEvent=arrayEvents[i];
			 *  	break;
			 *  }
			 * }
			 * 
			 * would become :
			 * 
			 * var oLastEvent=CSDC.forEach(arrayEvents, function(ev){
			 * 	return this.isLastEvent(ev);
			 * },myCalendar);
			 * 
			 * 
			 * @param {Array} _arr
			 * @param {Function} _function
			 * @param {Object} bindTo
			 * @return {Object}
			 */
			forEach:function(_arr, _function, bindTo){
				for(var i=0;i<_arr.length;i++){
					var _break=_function.call(bindTo||window, _arr[i], i);
					if(_break){
						return _arr[i];
					}
				}
			},
			namespace:function(qname){
				if(CSDC[qname]==undefined){
					CSDC[qname]={};
				}
			},
			getObject:function(qpath){
				var tmpObj=window;
				var value=null;
				var found=true;
				var path=qpath.split('.');
				for(var i=0;i<path.length && found; i++){
					tmpObj=tmpObj[path[i]];
					if(tmpObj===undefined){
						found=false;
					}
				}
				if(found){
					value=tmpObj;
				}
				return value;
			}
		};
	} ();
	CSDC.helpTip=function(){
		var tipText='';
		var pageTitle=CSDC.getElt('idPageTitle');
		this.tip=null;
		
		this.setTip=function(qtxt){
			tipText=qtxt;
			if(this.tip){
				this.tip.innerHTML='';
				this.tip.appendChild(document.createTextNode(tipText));
			}
		}
		var showTip=function(e){
			if(!this.tip){
				this.tip=CSDC.makeDom('div',{className:'cPageDescription cPageTip'},tipText);
				tipWrap.appendChild(this.tip);
			}
			YAHOO.util.Dom.setStyle(this.tip,'display','block');
		}
		var hideTip=function(e){
			YAHOO.util.Dom.setStyle(this.tip,'display','none');
		}
		
		//init dom stuff
		if (pageTitle) {
			var tipLink = CSDC.makeDom('a', {href: '#'}, [
				CSDC.makeDom('img', {'src': '../images/1x1transparent.gif', className: 'cIcon icoHelp', 'alt':''})
			]);
			var tipWrap=CSDC.makeDom('div',{className:'cPageTipWrap'},[tipLink]);
			pageTitle.appendChild(tipWrap);
			YAHOO.util.Event.on(tipLink,'mouseover',showTip,this,true);
			YAHOO.util.Event.on(tipLink,'mouseout',hideTip,this,true);
		}
	}
	CSDC.util = function () { 
		return {
		include: function(modules, onsuccessfcn) 
		{
			var loader = CSDC.util._loader;
			if (!loader) {
	       		var loader = new YAHOO.util.YUILoader({ base:'../yui/build/'}); 
	       		var jsPath='../scripts/';
	       		var cssPath='../';
				loader.addModule({name:'csdc_message', type:'js', fullpath:jsPath+'message.js', requires:['csdc_message_css']});
				loader.addModule({name:'csdc_message_css', type:'css', fullpath:cssPath+'message.css'});

				loader.addModule({name:'csdc_model', type:'js', fullpath:jsPath+'csdcmodel.js'});
				loader.addModule({name:'csdc_autocomplete', type:'css', fullpath:cssPath+'autocomplete.css', requires:['autocomplete']});

				CSDC.util._loader = loader;
			}

       	   loader.onSuccess = onsuccessfcn; 
		   loader.dirty = true;       	   
	       loader.insert({ require:modules }); 
		},
		include_js: function(script_fname) 
		{
			// TODO: use YUILoader every time.
			document.write('<script type="text/javascript" src="' + encodeURI(script_fname) + '"><\/script>');
		},
	
		include_css: function(css_fname) 
		{
			document.write('<link rel="stylesheet" href="' + encodeURI(css_fname) + '"><\/link>');
		},
		showLoadContent:function(id){
			var hideElt=CSDC.getElt(id+'Loading');
			YAHOO.util.Dom.setStyle( id, 'display', 'block' );
			hideElt.parentNode.removeChild(hideElt);
		},
		hideWait: function()
		{
			var div = CSDC.getElt('idDivWait');
			if (div)
				div.style.display='none';
		},
		
		showWait: function()
		{
			var div = CSDC.getElt('idDivWait');
			if (div)
				div.style.display='block';
			else
			{
				var div = CSDC.makeDom('div', { id: 'idDivWait' }, 'Sending request, please wait...' );
				document.body.appendChild(div);
			}
		},
		formatKb: function(nr)
		{
			if (nr > 2048)
				return Math.round(10*nr/1024)/10+" Mb";
			return nr+" Kb";
		},
		pulsate:function(elId,config){
			if(YAHOO.util && YAHOO.util.ColorAnim){
				var el=CSDC.getElt(elId);
				if (el) {
					if(!config) config={};
					if(!config.repeat) config.repeat=2;
					if(!config.color) config.color='#FFFABF';
					if(!config.color2) config.color2='#ffffff';
					
					var count = 0;
					var color = (count % 2 == 0) ? config.color : config.color2;
					
					var anim = new YAHOO.util.ColorAnim(el, {}, 0.3);
					anim.attributes.backgroundColor={to:color};
					anim.onComplete.subscribe(function(){
						count++;
						if (count < config.repeat * 2) {
							var color = (count % 2 == 0) ? config.color : config.color2;
							anim.attributes.backgroundColor = {
								to: color
							};
							anim.animate();
						}
					});
					anim.animate();
				}
			}
		},
		notifications:{
			topMsgControl:function(qconfig){
				this.t=null;
				var successAnim;
				var config=CSDC.util.parseConfig(qconfig,{
					displayTime:3,
					hideTime:0.5
				});
				
				var _hideSuccess=function(){
					successAnim=new YAHOO.util.Anim('idSaveSuccess',{height:{to:0}},config.hideTime,  YAHOO.util.Easing.easeOut);
					successAnim.onComplete.subscribe(function(){
						var el = this.getEl(); 
						el.parentNode.removeChild(el); 
					}); 
					successAnim.animate();
					this.t=null;
				}
				var _startTimer=function(){
					this.t=setTimeout(_hideSuccess,config.displayTime*1000);
				}
				var _destroy=function(){
					if(this.t) clearTimeout(t);
					this.t=null;
					if(successAnim) successAnim.stop();
					successAnim=null;
					CSDC.setText('response','');
				}
				return {
					destroy:function(){
						_destroy();
					},
					display:function(txt){
						_destroy();
						displaySuccess(txt,'idSaveSuccess');
						_startTimer();
					},
					hideSuccess:function(){
						_hideSuccess();
					}
				}
			},
			
			Notification:function(qmsg,qconfig){
				var config=CSDC.util.parseConfig(qconfig,{
					displayTime:5,
					hideTime:0.5,
					msgType:'Success',
					msgColor:'#D1EFC2',
					msgColor2:'#CDFF00'
				});
				if(!CSDC.util.notifications.holder){
					CSDC.util.notifications.holder=new CSDC.util.notifications.NotificationHolder();
				}
				if (CSDC.util.notifications.holder) {
					this.div = CSDC.makeDom('div', {
						className: 'cNotification'+config.msgType
					});
					//message can be a string or an array of dom elements
					if(typeof qmsg==="string"){
						this.div.appendChild(document.createTextNode(qmsg));
					}else{
						CSDC.domUtils.appendChildren(this.div,qmsg);
					}
					CSDC.util.notifications.holder.div.appendChild(this.div);
					CSDC.util.pulsate(this.div,{repeat:2,color:config.msgColor2,color2:config.msgColor});
					var that = this;
					this.t = setTimeout(function(){
						that.destroy();
					}, 1000*config.displayTime);
					this.destroy = function(){
						var successAnim = new YAHOO.util.Anim(this.div, {
							height: {to:0}
						}, config.hideTime, YAHOO.util.Easing.easeIn);
						successAnim.onComplete.subscribe(function(){
							var el = this.getEl();
							el.parentNode.removeChild(el);
						});
						successAnim.animate();
						this.t = null;
					}
				}
			},
			NotificationHolder:function(){
				this.div = CSDC.getElt('idNotificationsBar');
				if (!this.div) {
					this.div = CSDC.makeDom('div',{'id': 'idNotificationsBar'});
					document.body.appendChild(this.div);
				}
			},
			holder:null			
		},
		//tries to format a string to M/D/YYYY
		formatDateStr:function(qvalue){
			var dateArr=qvalue.split(/[\.|\-\/]/);
			if(dateArr.length<=3 && dateArr.length>1){
				var month=dateArr[0]*1;
				var day=dateArr[1]*1;
				var year;
				if(dateArr.length<=2){
					var today=new Date();
					if(today.getMonth()>month-1){
						year=today.getFullYear()+1;
					}else{
						year=today.getFullYear();
					}
				}else{
					var tmpyear=dateArr[2]*1;
					if(dateArr[2].length<4){
						if(tmpyear<79){
							year=2000+tmpyear;
						}else{
							year=1900+tmpyear;
						}						
					}else{
						year=tmpyear;
					}
				}
				var dateValue=new Date();
				dateValue.setFullYear(year, month-1, day);
				return dateValue.format('m/d/Y');
			}else{
				//can't format string, just return the original
				return qvalue;
			}
		},
		DateFormat_Default : null,		// 3 hours ago
		DateFormat_NoAgo : "TODO",		// 3 hours
		DateFormat_DayOnly : "_",		// today, yesterday, 5 Jul
		DateFormat_DayOnly2 : "B",		// today, yesterday, 5 Jul
		DateFormat_TimeOnly : "g:iA",		// hh:mm + AM/PM
		DateFormat_DayTime: "jS F Y, g:iA",
		DateFormat_DayTimeShort: "F d, gA",
		DateFormat_DayISO: "d/m/Y",
		formatDate: function( adate, dateFormat, compareDate )
		{
			if (!adate)
				return '';
			var dt = new Date(adate);
			dateFormat = dateFormat || this.DateFormat_Default;
			if (dateFormat == this.DateFormat_Default || dateFormat == this.DateFormat_NoAgo) {
				var today = (compareDate)? new Date(compareDate) : new Date();
				var sSuffix = (dateFormat == this.DateFormat_Default) ? " ago" : ""; 
				var dif = Math.abs( Math.round( (today-dt)/1000 ) );
			
				if (dif < 60)
					return dif+" second"+((dif>1)?"s":"") + sSuffix;
				dif = Math.round(dif/60);	// now in mn
				if (dif < 60)
					return dif+" minute"+((dif>1)?"s":"") + sSuffix;
				dif = Math.round(dif/60); //now in hours
				if (dif <48)
					return dif+" hour"+((dif>1)?"s":"") + sSuffix;
				dif = Math.round(dif/24); // now in days
				if (dif <7)
					return dif+" day"+((dif>1)?"s":"") + sSuffix;
	
				if (dateFormat == this.DateFormat_Default) {
					if (dif <7)
						return dif+" day"+((dif>1)?"s":"") + sSuffix;
	
					return 'on '+dt.format(this.DateFormat_DayOnly);
				}			
				if (dif <30)
					return dif+" day"+((dif>1)?"s":"") + sSuffix;
				dif = Math.round(dif/30); // now in months
				if (dif <24)
					return dif+" month"+((dif>1)?"s":"") + sSuffix;
				dif = Math.round(dif/12)
				return dif+" year"+((dif>1)?"s":"") + sSuffix;
			}
			return dt.format(dateFormat);
		},
		
		fillYearDropdown : function(selectY,	qconfig)
		{
			if(!qconfig) qconfig={};
			qconfig.order=qconfig.order || 'asc';
			qconfig.startYear=qconfig.startYear || 1910;
			qconfig.endYear=qconfig.endYear || 2009;
			
			var dif=qconfig.endYear-qconfig.startYear;
			var dir=(qconfig.order=='asc')? 1 : -1;
			var startYear=(qconfig.order=='asc')? qconfig.startYear : qconfig.endYear;
			var year;
			for (var i=0;i<=dif;i++){
				year=startYear+(i*dir);
				selectY.options[(i+1)]= new Option(year, year);
			}
		},
		
		fillMonthDropdown : function(selM)
		{
			for (var ii=0;ii<12;ii++)
				selM.options[ii+1]=new Option(Date.ReplaceChars.longMonths[ii], ii+1);
		},
		hideElt : function(){
			for(var i=0;i<arguments.length;i++){
				var domElt=arguments[i];
				try {
					var tmpStyle=YAHOO.util.Dom.getStyle(domElt, 'display');
					if(tmpStyle!=="none"){
						domElt.csdcDisplayBak=tmpStyle;
						YAHOO.util.Dom.setStyle(domElt, 'display','none');
					}
				}catch(e){}
			}
		},
		showElt : function(){
			for(var i=0;i<arguments.length;i++){
				var domElt=arguments[i];
				try {
					if(YAHOO.util.Dom.getStyle(domElt, 'display')==="none"){
						var tmpStyle=(domElt.csdcDisplayBak)? domElt.csdcDisplayBak : 'inline';
						//inline should work in most of the cases
						YAHOO.util.Dom.setStyle(domElt, 'display', tmpStyle);
					}
				}catch(e){}
			}
		},
		checkEmptyField : function(idField, label) {
			if (CSDC.getElt(idField).value.length == 0)
			{
				alert('You must enter a '+label);
				CSDC.getElt(idField).focus();
				return false;
			}
			return true;
		},
		checkDateField : function(idField, label, bEmptyIsOk) {
			var dt = CSDC.getElt(idField).value;
			var re = /^\d{1,2}\/\d{1,2}\/\d{2,4}$/;
			if (dt.length == 0) {
				if (bEmptyIsOk)
					return true;
				if (!CSDC.util.checkEmptyField(idField, label))
					return false;
			}
			if (!dt.match(re))
			{
				alert('You must enter a valid date for the '+label);
				CSDC.getElt(idField).focus();
				return false;
			}
			return true;
		},
		// Display the message in a simple modal dialog
		//TODO - Perhaps add a second param to indicate fn to chain to (to redraw some part of the local page, for example)
		//TODO - i think there are more efficient ways to do this: (a) SimpleDialog is too complex, use a superclass
		displayMsg: function( response, fcn ) {
			if (!CSDC.util._dlgMsg) {
				var aDiv = CSDC.makeDom('div');
				document.body.appendChild(aDiv);
				CSDC.util._dlgMsg = new YAHOO.widget.SimpleDialog(aDiv, 
						 { width: '300px',
						   fixedcenter: true,
						   visible: false,
						   draggable: true,
						   close: false,
						   modal: true,
						   constraintoviewport: true,
						  buttons: [ { text:'Ok',  handler:function() { this.hide(); if (fcn) fcn(); } } ]
						 } );
				CSDC.util._dlgMsg.render();
			}			
			CSDC.util._dlgMsg.setBody(response.message);
			CSDC.util._dlgMsg.show();
		},
		displayMsgInPage : function (sMessage)
		{
			var elt = CSDC.getElt('idContentDiv');
			if (!elt)
				elt.document.body;
			elt.innerHTML = "";
			elt.appendChild(CSDC.makeDom('div', { className:'cMessageBox', innerText:sMessage}));
		},
		cutText:function(qstr,qlimit){
			if(!qlimit || qlimit<=0) qlimit=qstr.length;
			if(qstr.length>qlimit){
				qstr=qstr.substr(0,qlimit)+'...';
			}
			return qstr;
		},
		htmlEntities:function(qstr){
			var exp=/[(<"'>&]/g;
			var str=qstr.replace(exp,function(m){
				switch(m){
					case "<": return "&lt;";
					break;
					case ">": return "&gt;";
					break;
					case "\"": return "&quot;";
					break;
					case "'": return "&#039;";
					break;
					case "&": return "&amp;";
					break;
				}
			});
			return str;
		},
		encodeJson:function(str) {
			return encodeURIComponent(YAHOO.lang.JSON.stringify(str)); 
		},
		numToHour:function(qvalue){
			var hours=Math.floor(qvalue);
			var mins=Math.round(60*(qvalue-hours));
			
			var result=[];
			if(hours>0){
				result.push(hours+'h');
			}
			if(mins>0){
				result.push(mins+'m');
			}
			return result.join(' ');
		}
	};
	} ();
}

CSDC.util.isArray=function(obj) {   
	return Object.prototype.toString.call(obj) === '[object Array]'; 
}
//TODO: this method partially destroys the original config obj. It maybe shouldn't do that.
CSDC.util.parseConfig=function(qconfig,defaultValues){
	var config={};
	qconfig=qconfig || {};
	for(var value in defaultValues){
		config[value]=(typeof qconfig[value]=='undefined')? defaultValues[value] : qconfig[value];
		delete qconfig[value];
	}
	//copy all other params from qconfig without a default value
	for(var value in qconfig){
		config[value]=qconfig[value];
	}
	return config;
}
CSDC.domUtils={};
CSDC.domUtils.appendChildren=function(qparent,qchildren){
	if(!CSDC.util.isArray(qchildren)) qchildren=[qchildren];
	for(var i=0;i<qchildren.length;i++){
		qparent.appendChild(qchildren[i]);
	}
}
CSDC.domUtils.strToDomArray=function(str){
	var tmpElt=CSDC.makeDom('div',{});
	tmpElt.innerHTML=str;
	var children=YAHOO.util.Dom.getChildren(tmpElt);
	delete tmpElt;
	return children;
}
CSDC.domUtils.createFieldWrap=function(qid,qconfig){
	var config=CSDC.util.parseConfig(qconfig,{
		addLabel:false,
		label:'',
		content:null,
		tipTag:'',
		feedbackTag:'',
		tipPosition:'',
		cssClass:'cFieldGroup',
		addFieldWrap:'',
		'id':qid+'Group'
	});
	if(config.content==null) return;
	var label, fieldWrap, tipWrap, tip, feedback,clearer;
	
	var elt=CSDC.makeDom('div',{"id":config.id,	className:config.cssClass});
	
	if(config.addLabel){
		label=CSDC.makeDom('label',{	'id':qid+'Label',	'for':qid,	innerText:config.label});
	}
	
	if(config.tipTag!='' || config.feedbackTag!=''){
		tipWrap=CSDC.makeDom('div',{	className:'cFieldTip'	});
	}
	
	if(config.tipTag!=''){
		tip=CSDC.makeDom(config.tipTag,{className:"cFormFeedbackTip",	"id":qid+"Tip"});
		tipWrap.appendChild(tip);
	}
	
	if(config.feedbackTag!=''){
		feedback=CSDC.makeDom(config.feedbackTag,{className:"formFeedback",	"id":qid+"Feedback"});
		tipWrap.appendChild(feedback);
	}
	
	var clearer=CSDC.makeDom('div',{className:'cFieldFooter'});
	clearer.innerHTML='&nbsp';
	
	if(config.addFieldWrap!=''){
		var fieldWrap=CSDC.makeDom('div',{'id':qid+'Wrap',className:config.cssClass+'Wrap'});
	}
	
	if(typeof config.content=='string'){
		config.content=CSDC.domUtils.strToDomArray(config.content);
	}
	//add elements to the main elt
	switch(config.addFieldWrap){
		case 'all':
			elt.appendChild(fieldWrap);
			if(label) fieldWrap.appendChild(label);
			if(config.content) CSDC.domUtils.appendChildren(fieldWrap, config.content);
		break;
		case 'field':
			if(label) elt.appendChild(label);
			elt.appendChild(fieldWrap);
			if(config.content) CSDC.domUtils.appendChildren(fieldWrap, config.content);
		break;
		default:
			if(label) elt.appendChild(label);
			if(config.content) CSDC.domUtils.appendChildren(elt, config.content);
		break;
	}
	if(tipWrap){
		switch(config.tipPosition){
			case 'beforeWrap':
				elt.insertBefore(tipWrap,fieldWrap);
			break;
			case 'beforeField':
				content=(CSDC.util.isArray(config.content))? config.content[0]:config.content;
				content.parentNode.insertBefore(tipWrap,content);
			break;
			default:
			case 'afterField':
				content=(CSDC.util.isArray(config.content))? config.content[config.content.length-1]:config.content;
				content.parentNode.insertBefore(tipWrap,content.nextSibling);
			break;
			case 'afterWrap':
				fieldWrap.parentNode.insertBefore(tipWrap,fieldWrap.nextSibling)
			break;
		}
	}
	elt.appendChild(clearer);
	return elt;
}
CSDC.domUtils.parseUrls=function(str,config){
	if(!config.allowHtml) config.allowHtml=false;
	if(!config.shortenUrls) config.shortenUrls=false;
	if(!config.maxLength) config.maxLength=0;

	var urlRegEx=/((https?:\/\/|www.){1}([^\s\n\r\t<]+))/gi;
	if(config.shortenUrls){

	}else{
		if(config.allowHtml==false){
			var tmpel=document.createTextNode(str);
			var tmpel2=document.createElement('div');
			tmpel2.appendChild(tmpel);
			str=tmpel2.innerHTML;
			tmpel=tmpel2=null;
		}
		if(config.maxLength==0){
			str=str.replace(urlRegEx,'<a href="$1">$1</a>');
		}else{
			var strArr=urlRegEx.exec(str);
			var newStr='';
			while(strArr!=null){
				var url=(strArr[2]=='www.')? 'http://'+strArr[0]:strArr[0];
				var urlText=(strArr[0].length>config.maxLength)? '[link]':strArr[0];
				var newLink='<a href="'+url+'" target="_blank">'+urlText+'</a>';
				str=str.substr(0,strArr.index)+
					newLink+
					str.substr(strArr.index+strArr[0].length,str.length);
				urlRegEx.lastIndex=strArr.index+newLink.length;

				strArr=urlRegEx.exec(str);
			}
		}
	}
	return str;
}
CSDC.domUtils.checkMaxHeight=function(qel,qheight,maxHeight){
	if(!maxHeight) maxHeight=qheight+'px';
	var el=YAHOO.util.Dom.getRegion(qel);
	var elHeight=el.bottom-el.top;
	if(elHeight>qheight){
		YAHOO.util.Dom.setStyle(qel,'height',maxHeight);
	}
}
CSDC.GlobalVars=function(){
	var vars={};
	this.get=function(qvar, qdefault){
		if(qdefault===undefined){
			qdefault=null;
		}
		return vars[qvar] || qdefault;
	}
	
	this.set=function(qvar,qvalue){
		vars[qvar]=qvalue;
	}
}
CSDC.globals=new CSDC.GlobalVars();

CSDC.util.include_js("../yui/build/yahoo-dom-event/yahoo-dom-event.js");  
CSDC.util.include_js("../yui/build/connection/connection.js");
CSDC.util.include_js("../yui/build/yuiloader/yuiloader.js");
CSDC.util.include_js("../yui/build/animation/animation.js");
CSDC.util.include_js("../yui/build/container/container.js");
CSDC.util.include_js("../yui/build/json/json.js");
CSDC.util.include_js("../scripts/tooltip.js");

CSDC.util.include_css("../yui/build/container/assets/skins/sam/container.css");
CSDC.util.include_css("../csdc.css");
CSDC.util.include_css("../tooltip.css");
CSDC.util.include_css("../dialog.css");

var EntityType_User = "0";
var EntityType_Club = "2";
var EntityType_Community = "3";
var EntityType_Collection = "8";
var EntityType_Video = "10";
var EntityType_Photo = "15";
var EntityType_Document = "21";
var EntityType_Event = "22";
var EntityType_Post = "29";
var EntityType_Saying = "53";

var COMMENT_MAXLEN_TEXT = 500;
var INVITATION_MAXLEN_MESSAGE = 250;
var SIGNUPITEMUSER_MAXLEN_COMMENT=500;
var DISCUSSIONTOPIC_MAXLEN_TITLE=POST_MAXLEN_TITLE=255;
var POST_MAXLEN_DESCRIPTION=65535;
var EVENTRSVP_MAXLEN_COMMENT = 110;

var ENTITY_MAXLEN_DESCRIPTION = 500;

var EVENT_MAXLEN_TITLE=500;
var EVENT_MAXLEN_NOTES=1000;
var EVENT_MAXLEN_LOCATION=150;

function displaySuccess(txt,id)
{
	var div = CSDC.getElt('response');
	if (!div)
	{
		div = CSDC.makeDom("div", { className: 'response'});
		if (document.body.childNodes.length > 0)
			document.body.insertBefore(div, document.body.childNodes[0]);
		else
			document.body.appendChild(div);
	}
	var successId=(id)? id:'idCsdcSuccess';
	div.innerHTML = '<p class="csdcSuccess" id="'+successId+'">' + txt + '</p>';
}

function toggleGroupMenu(e)
{
	var domMenu = CSDC.getElt( 'idGroupMenu' );
	var domMenuTab=CSDC.getElt('idTopMenuCIRCLES');
	document.body.appendChild(domMenu);
	if( YAHOO.util.Dom.getStyle( domMenu, 'display') === 'none' ){
		var domTopGrpMenu = CSDC.getElt( 'idTopMenuCIRCLES' );
		var pos = YAHOO.util.Dom.getXY( domTopGrpMenu );
		pos[1] += domTopGrpMenu.offsetHeight;
		if(YAHOO.env.ua.ie){
			pos[0]-=2;
			pos[1]-=2;
		}
		domMenu.style.left=pos[0]+"px";
		domMenu.style.top=pos[1]+"px"; 
		YAHOO.util.Dom.setStyle( domMenu, 'display', 'block' );
		YAHOO.util.Event.addListener(document.body, "click", toggleGroupMenu);
	}else{
		if(e){
			var targetElt = YAHOO.util.Event.getTarget(e);
			if(targetElt.href && targetElt.href==="javascript:toggleGroupMenu();"){
				return;
			}
		}
		YAHOO.util.Dom.setStyle( domMenu, 'display', 'none' );
		YAHOO.util.Event.removeListener(document.body, "click", toggleGroupMenu);
	}	

	var el=YAHOO.util.Dom.getRegion('idGroupMenuEntries');
	var elHeight=el.bottom-el.top;
	if(elHeight>185){
		YAHOO.util.Dom.addClass('idGroupMenuEntries','cGroupMenuEntries');
	}
}

function clickGroupMenu( sUrl )
{
	var domMenu = CSDC.getElt( 'idGroupMenu' );
	CSDC.util.hideElt( domMenu );
	openLink( sUrl );
}

function displayError(txt, fcn)
{
	if (CSDC.util)
		CSDC.util.hideWait();
	if (CSDC.progressdlg)
		CSDC.progressdlg.close();

	var dlg = new YAHOO.widget.SimpleDialog("Error", 
			 { width: "300px",
			   fixedcenter: true,
			   visible: false,
			   draggable: true,
			   close: true,
			   modal: true,
			   text: txt,
			   icon: YAHOO.widget.SimpleDialog.ICON_BLOCK,
			   constraintoviewport: true,
			   buttons: [ { text:"Close",  handler:function() { this.hide(); if (fcn) fcn();} } ]
			 } );
	dlg.setHeader("Error");
	dlg.render(document.body);
	dlg.show();
}

function displayErrorInPage(sError)
{
	if (CSDC.util)
		CSDC.util.hideWait();
	if (CSDC.progressdlg)
		CSDC.progressdlg.close();
	var elt = CSDC.getElt('idContentDiv') || document.body;
	elt.innerHTML = "";
	var errorInfo=CSDC.makeDom('div', { 'id':'idErrorInfo',className:'cErrorInfo'});
	errorInfo.innerHTML='Something went wrong here. Please help us resolve this issue by <a href="../jsp/contactus.jsp" title="feedback">providing us feedback</a> on what you were doing before you got this message';
	
	CSDC.domUtils.appendChildren(elt,[
		CSDC.makeDom('div', { 'id':'idPageTitle',className:'cPageTitle', innerText:'Error'}),
		CSDC.makeDom('div', { className:'cErrorBox', innerText:sError}),
		errorInfo
	]);
	CSDC.util.pulsate('idErrorInfo',{
		color:'#FFEE89',
		color2:'#FFFFCF',
		repeat:2
	});
}

function displayNotFriendError(obj){
	var elt = CSDC.getElt('idContentDiv');

	displaySideContext(obj, {contactContext:true});
	var message=['<div class="cPageTitle">Private Page</div>'];
	message.push('<div class="cDefaultMessage">');
	message.push('The information on this page has been restricted by ');
	message.push('<a href="'+CSDC.lnkOpenUser(obj.Id)+'">'+obj.Name+'</a>.');
	if(elt) elt.innerHTML=message.join('');

}

function openLink(sUrl)
{
//	CSDC.util.showWait();
	document.location = sUrl;
}

function openContext(context)
{
 	if (context && context.jsp=='cc')
		openLink('../jsp/calendar.jsp?cid='+context.id);
 	if (context && context.jsp=='pc')
		openLink('../jsp/calendar.jsp');
}


function clearResponse()
{
	CSDC.getElt('response').innerHTML="";
}


function DOMAddRemoveClass(bAddOrRemove, id, className)
{
	if (bAddOrRemove)
		YAHOO.util.Dom.addClass(CSDC.getElt(id), className);
	else
		YAHOO.util.Dom.removeClass(CSDC.getElt(id), className);
}
/*************************************************************
 possible attributes for oConfig:
    noLink: false [ default], set to true will remove the a link.
    fcn: openUser [ default], function to call when the user click on the picture (n/a if noLink is true).
*/
function getUserLinkElt(oConfig)
{
	CSDC.tooltip.init();
	var displayName = oConfig.Name;
	if( !displayName || displayName.length==0 || displayName==" ")
		displayName = "Anonymous User"
	var elt = CSDC.makeDom( 'a',
							{ "id": oConfig.Id, 
							className:'cPersona ' + (oConfig.className || ''), 
							innerText: displayName });
	if( !oConfig.noLink )
		elt.href=oConfig.fcn ? 'javascript:'+oConfig.fcn +'('+oConfig.Id+')' : CSDC.lnkOpenUser(oConfig.Id);
	return elt;
}
// TODO: remove and replace with getUserLinkElt
function getUserLinkFromId( uid, userName, className )
{
	CSDC.tooltip.init();
	return "<a class='cPersona "+(className ? className : "")+"' id=" + uid + " href='" + CSDC.lnkOpenUser(uid) + "'>" + userName + "</a>";
}

function getUserLink( user, className )
{
	return getUserLinkFromId( user.Id, user.Name, className );
}

function getClubLink( club, className )
{  // TODO: replace by getClubLinkElt
	CSDC.tooltip.init();
	var lnk = club.EntityType == EntityType_Club ? CSDC.lnkOpenClub(club.Id) : CSDC.lnkOpenCty(club.Id);
	return '<a class="cClub ' + ( className ? className : "" ) + '" id="' + club.Id +'" href="'+lnk+'">' + club.Name + '</a>';
}

function getLinkForEntity(context, className)
{
	switch (''+context.EntityType) {
		case EntityType_Club: return getClubLink(context, className);
		case EntityType_Community: return getClubLink(context, className);
		case EntityType_Event: return '';//TODO? 
		case EntityType_User: return getUserLink(context, className);
	}
}
function getLinkEltForEntity(context, className)
{
	if( context.EntityType == EntityType_Club || context.EntityType == EntityType_Community )
		return getClubLinkElt(context, className);
	else if (context.EntityType == EntityType_Event)
		return getEventLinkElt(context, className);
	else if (context.EntityType == EntityType_User)
		return getUserLinkElt(context, className);
}
function getClubLinkElt(club, className)
{  
	CSDC.tooltip.init();
	var lnk = club.EntityType == EntityType_Club ? CSDC.lnkOpenClub(club.Id) : CSDC.lnkOpenCty(club.Id);
	return CSDC.makeDom('a', {className:'cClub ' + ( className || "" ), id: club.Id, href:lnk }, club.Name);
}

function getEventLinkElt(event, className)
{  
	CSDC.tooltip.init();
	var lnk = CSDC.lnkOpenEvent(event.Id,event.CalendarId);
	var id=['evLink',event.Id];
	var defaultClass;
	if(event.CalendarId){
		id.push(event.CalendarId);
		defaultClass='cEventLink';
	}else{
		defaultClass='cEvent'
	}
	return CSDC.makeDom('a', {'className':defaultClass + ' '+ ( className || "" ), 'id': id.join('_'), href:lnk }, event.Name);
}

function getContextParam( context )
{
	var result = '';
	switch (''+context.EntityType) {
		case EntityType_Club: 
			result = 'cid=' + context.Id;
			break;
		case EntityType_Community: 
			result = 'yid=' + context.Id;
			break;
		case EntityType_Event: 
			result = 'eid=' + context.Id;
			break;
		case EntityType_User: 
			result = 'uid=' + context.Id;
			break;
	}
	return result;
}

function getCommentableLinkElt( jsonEntity )
{
	var lnk = '#';
	var lnkText = jsonEntity.Name;
	switch( ''+jsonEntity.EntityType )
	{
		case EntityType_Photo: 
			lnk = CSDC.lnkOpenPhoto( jsonEntity.Id );
			break;
		case EntityType_Collection: 
			lnk = CSDC.lnkOpenCollection( jsonEntity.Id );
			break;
		case EntityType_Document: 
			lnk = CSDC.lnkOpenDocument( jsonEntity.Id );
			break;
		case EntityType_Post: 
			lnk = CSDC.lnkOpenPost( jsonEntity.Id, null );
			break;
		case EntityType_Saying: 
			lnk = CSDC.lnkOpenSayings( jsonEntity.Context.Id );
			lnkText = 'your mini-post'
			break;
	}
	return CSDC.makeDom('a', { id:jsonEntity.Id, href:lnk }, lnkText );
}

getPictureURL = function( jsonPicture, bThumb )
{
	var imgsrc = '../GetFile?action=getpicture&id=' + jsonPicture.Id;
	if( bThumb )
		imgsrc += "&size=thumb";
	return imgsrc;
}

getLibraryItemURL = function( jsonItem, bThumb )
{
	var imgsrc = '../GetFile?action=getfile&fid=' + jsonItem.Id;
	if(jsonItem.Type) imgsrc+='&ftype=' + jsonItem.Type;
	if(bThumb) imgsrc += "&size=thumb";
	return imgsrc;
}
/**
 possible attributes for oConfig:
    noLink: false [ default], set to true will remove the a link.
    fcn: openUser [ default], function to call when the user click on the picture (n/a/ if noLink is true).
*/
getUserPic = function( uid, pict, oConfig )
{
	var aimg = CSDC.makeDom('img');
	aimg.src = pict && pict.Id ? "../GetFile?action=getpicture&size=thumb&id=" + pict.Id : '../images/nophoto.gif';
	var imgClass=['cPersona'];
	if(oConfig.extraClass) imgClass.push(oConfig.extraClass);
	var aa = CSDC.makeDom('a', { id: uid, className:  imgClass.join(' ')});
	if (!oConfig.noLink)
	{
		var lnk = (oConfig && oConfig.fcn) ? "javascript:"+oConfig.fcn+"("+uid+")" : CSDC.lnkOpenUser(uid);
		aa.setAttribute('href', lnk);
	}
	aa.appendChild(aimg);
	return aa;
}
getUserDiv = function( user, oConfig )
{
	CSDC.tooltip.init();
	var adiv = CSDC.makeDom('div', { className: 'cUser'});
	var aa = getUserPic( user.Id, user.Picture, oConfig);

	aa.appendChild( CSDC.makeDom('p',{}, user.Name) );

	adiv.appendChild(aa);

	return adiv;
}

getUserDivForTT = function( user )
{
	var tr = CSDC.makeDom('tr');
	var elt = CSDC.makeDom('table', { className: 'cProfileContainer cTipContentWrap' }, [CSDC.makeDom('tbody', {}, [tr])]);
	tr.appendChild(CSDC.makeDom('td', {}, [CSDC.makeDom('img', {src:getPictureURL( user.Picture, true ) })]));
	var td = CSDC.makeDom('td');
	td.appendChild(CSDC.makeDom('b', {innerText:user.Name}));
	tr.appendChild(td);		
	if( user.Location ) 
		td.appendChild( CSDC.makeDom('p', {innerText:user.Location}) );
	return elt;
}
getClubOrganizers =function(orgs, qconfig) {
	var config=CSDC.util.parseConfig(qconfig,{
		label:'Organizer',
		showLabel:true
	});
	var txt = '';
	if(config.showLabel) txt+=config.label+(orgs.length > 1 ? "s: " : ": ");
	var orgsList=[];
	for (var ii=0;ii<orgs.length;ii++) {
		orgsList.push(orgs[ii].Name);			
	}
	txt+=orgsList.join(', ');
	return txt;
}
getClubDivForTT = function(club)
{
	var memberCount='';
	if (club.MemberCount) {
		memberCount = club.MemberCount+' member';
		memberCount+=(club.MemberCount!=1)?'s':'';
	}
	var tr = CSDC.makeDom('tr');
	var elt = CSDC.makeDom('table', { className: 'cProfileContainer cTipContentWrap' }, [CSDC.makeDom('tbody', {}, [tr])]);
	tr.appendChild(CSDC.makeDom('td', {}, [CSDC.makeDom('img', {id:'idClubPicture',src:getPictureURL( club.Picture, true ) })]));
	var td = CSDC.makeDom('td');
	td.appendChild(CSDC.makeDom('b', {innerText:club.Name}));
	if(club.Location!='' && club.Location!=undefined) td.appendChild(CSDC.makeDom('p', {innerText:club.Location}));
	
	var pMembers = CSDC.makeDom('p', {innerText:memberCount});
	if (club.ParentClub)
		pMembers.appendChild(CSDC.makeDom('span', {className:'ParentGroup', innerText:'Group of: '+CSDC.util.cutText(club.ParentClub.Name, 24)}));
	td.appendChild(pMembers);
	if (club.Organizers.length)
		td.appendChild(CSDC.makeDom('p', {id:'idClubOrganizer', innerText:CSDC.util.cutText(getClubOrganizers(club.Organizers), 50)}));
	tr.appendChild(td);
	return elt;
}

getEventsDivForTT = function(qevents)
{
	var eltBody=CSDC.makeDom('tbody',{});
	var elt=CSDC.makeDom('table',{'className':'cTipContentWrap'}, [eltBody]);
	for (var ii = 0; ii < qevents.length; ii++) {
		if(qevents[ii].EstLow!==undefined){
			var wraptd=CSDC.makeDom('td',{className:'cAsTooltipTD2'}, [getAssignmentDivForTT(qevents[ii], {
				limitTitle:50,
				showDescription:false,
				showDates:true,
				showRef:false,
				showFileIcon:false
			})] );
			var wrap=CSDC.makeDom('tr',{},[
				CSDC.makeDom('td',{className:'cAsTooltipTD1'},[
					CSDC.makeDom('img',{src:'../images/1x1transparent.gif', className:'cIcon icoAssignment'})
				]),
				wraptd
			]);
			eltBody.appendChild(wrap);
		}else{
			eltBody.appendChild(get1EventDivForTT(qevents[ii]));
		}
	}
	return elt;
}
getEventDivForTT = function(qevent)
{
	var eltBody=CSDC.makeDom('tbody',{});
	var elt=CSDC.makeDom('table',{'className':'cTipContentWrap'}, [eltBody]);
	eltBody.appendChild(get1EventDivForTT(qevent));
	return elt;
}
get1EventDivForTT = function(qevent)
{
	var tr = CSDC.makeDom('tr');
	var picture=CSDC.makeDom('td', {className:'cTTPicture'}, [CSDC.makeDom('img', {src:getPictureURL( qevent.Picture, true ) })]);
	var detailsWrap=CSDC.makeDom('td',{className:'cTTDetailsWrap'});
	var details=[];
	var titleClass=(qevent.evType)? ' cEvTypeTT cEvType'+qevent.evType:'';
	details.push(CSDC.makeDom("div",{className:'cTTMain'+titleClass},CSDC.util.cutText(qevent.Title, 180)));
	var contextTxt=(qevent.Context && qevent.Context.EntityType==EntityType_Club)? qevent.Context.Name:'';
	if(contextTxt!='' && !CSDC.getObject('CSDC.PageSettings.isGroup')){
		details.push(CSDC.makeDom('div',{className:'cTTContext'},[
			CSDC.makeDom('span',{},"For: "),
			document.createTextNode(contextTxt)
		]));
	}
	
	var szDayString = '';
	var startDate=new Date(Date.parse(qevent.DateStart));
	var endDate=new Date(Date.parse(qevent.DateStop));
	var bMultiDay=(startDate.format('d/m/Y')!=endDate.format('d/m/Y'))? true:false;
	
	if (qevent.Duration  && qevent.AllDay!=1)
		szDayString += ''+qevent.Duration+((qevent.Duration >=2) ? ' hours, ':' hour, ');
	
	if(bMultiDay){
		szDayString+=arrDay[startDate.getDay()===0?6:startDate.getDay()-1].substring(0,3)+
					' '+arrMonth[startDate.getMonth()].substring(0,3)+' '+fGetDayWithExt(startDate)+' '+fGetTime(startDate)+' to '+
					arrDay[endDate.getDay()===0?6:endDate.getDay()-1].substring(0,3)+
					' '+arrMonth[endDate.getMonth()].substring(0,3)+' '+fGetDayWithExt(endDate)+' '+fGetTime(endDate);
	}else{
		if(qevent.AllDay===1){
			var allDayDate=arrDay[startDate.getDay()===0?6:startDate.getDay()-1].substring(0,3)+
							' '+arrMonth[startDate.getMonth()]+' '+fGetDayWithExt(startDate);
			if (qevent.Duration){
				//just display the date
				szDayString+=allDayDate;
			}else{
				var allDayTxt;
				//if test, quiz, project due, in-class essay, seminar
				//don't show "all day"
				switch (qevent.evType) {
					case 11:
					case 12:
					case 14:
					case 18:
					case 19:
						allDayTxt='';
					break;
					default:
						allDayTxt=''; //', all day';
					break;
				}
				szDayString+=allDayDate+allDayTxt;
			}
		}else{
			szDayString+=arrDay[startDate.getDay()===0?6:startDate.getDay()-1].substring(0,3)+
					' '+arrMonth[startDate.getMonth()]+' '+fGetDayWithExt(startDate)+', '+fGetTime(startDate)+' - '
					+fGetTime(endDate);
		}
	}
	
	details.push(CSDC.makeDom("div",{className:'cTTSecondary'},szDayString));
	if(qevent.Context && qevent.Context.EntityType==EntityType_Club && qevent.Context.Organizers && qevent.Context.Organizers.length){
		details.push(CSDC.makeDom('div', {className:'cTTSecondary'},[
			CSDC.makeDom('strong',{},'Group Organizers: '),
			CSDC.makeDom('span',{},CSDC.util.cutText(getClubOrganizers(qevent.Context.Organizers,{showLabel:false}), 70))
		]));
	}
	
	details.push(CSDC.makeDom("div",{className:'cTTSecondary'},qevent.Location));
	//only added to group events
	if(qevent.UserInvitation && qevent.UserInvitation.Status && contextTxt!=''){
		var answers=["Unconfirmed","Yes","Maybe","No"];
		details.push(CSDC.makeDom('div',{className:'cTTSecondary'},[
			CSDC.makeDom('span',{},"Your Response: "),
			CSDC.makeDom('span',{className:'cTTResponse'+qevent.UserInvitation.Status},answers[qevent.UserInvitation.Status])
		]));
	}
	CSDC.domUtils.appendChildren(detailsWrap,details);
	CSDC.domUtils.appendChildren(tr,[
		picture,
		detailsWrap
	]);
	return tr;
}
getSignupDivForTT = function(signup)
{
	var tr = CSDC.makeDom('tr');
	var elt = CSDC.makeDom('table', { className: 'cProfileContainer cTipContentWrap' }, [CSDC.makeDom('tbody', {}, [tr])]);
	tr.appendChild(CSDC.makeDom('td', {}, [CSDC.makeDom('img', {id:'idClubPicture',src:getPictureURL( signup.Context.Picture, true ) })]));
	var td = CSDC.makeDom('td');
	td.appendChild(CSDC.makeDom('b', {className:'cTTMain', innerText:signup.Name}));
	
	td.appendChild(CSDC.makeDom('p', {className:'cTTSecondary', innerText:"For: "+signup.Context.Name}));
	td.appendChild(CSDC.makeDom('p', {className:'cTTSecondary', innerText:signup.OpenCount+" open items:"}));
	for (var ii=0;ii<signup.Items.length; ii++) {
		var txt = signup.Items[ii].Name +' '+CSDC.util.formatDate( signup.Items[ii].NeedBy, "D, M j" );
		td.appendChild(CSDC.makeDom('p', {className:'cTTSecondary cTTSignupItemList', innerText: txt} ))
	}
	
	tr.appendChild(td);
	return elt;
}
getSignupItemDivForTT = function(sitem)
{
	var tr = CSDC.makeDom('tr');
	var elt = CSDC.makeDom('table', { className: 'cProfileContainer cTipContentWrap' }, [CSDC.makeDom('tbody', {}, [tr])]);
	tr.appendChild(CSDC.makeDom('td', {}, [CSDC.makeDom('img', {id:'idClubPicture',src:getPictureURL( sitem.Context.Picture, true ) })]));
	var td = CSDC.makeDom('td');
	td.appendChild(CSDC.makeDom('b', {className:'cTTMain', innerText:sitem.Name}));
	
	td.appendChild(CSDC.makeDom('p', {className:'cTTSecondary', innerText:"In List: "+sitem.ListName}));
	td.appendChild(CSDC.makeDom('p', {className:'cTTSecondary', innerText:"For: "+sitem.Context.Name}));
	td.appendChild(CSDC.makeDom('p', {className:'cTTSecondary', innerText:"Due Date: "+CSDC.util.formatDate( sitem.NeedBy, "D, M j" )}));

	if (sitem.Volunteer) {
		td.appendChild(CSDC.makeDom('p', {className:'cTTSecondary', innerText:"Assigned To: "+sitem.Volunteer.Name}));
		if (sitem.Volunteer.Comment)
			td.appendChild(CSDC.makeDom('p', {className:'cTTSecondary', innerText:"Comments: "+sitem.Volunteer.Comment}));
	}	
	tr.appendChild(td);
	return elt;
}
var _linkParam = '%CTX%';
function displaySideContext( context,config )
{
	var elt = CSDC.getElt('idPageContext');
	
	//let's make sure that the context element is empty first
	if ( elt.hasChildNodes() )
	{
	    while ( elt.childNodes.length >= 1 )
	    {
	        elt.removeChild( elt.firstChild );       
	    } 
	}
	
	var linkParam = '';
	var thumbClass = '';
	var lnk;
	switch( context.EntityType )
	{
		case parseInt(EntityType_Club):
			thumbClass='cClubThumb';
			linkParam = 'cid='.concat( context.Id );
			lnk = CSDC.lnkOpenClub(context.Id);
			if (context.IsParent) {
				if (CSDC.getElt('CIRCLE_INSTANCE_SUBGROUPS'))
					CSDC.getElt('CIRCLE_INSTANCE_SUBGROUPS').style.display = 'block';
				if (CSDC.getElt('CIRCLE_INSTANCE_ASSIGNMENT'))
					CSDC.getElt('CIRCLE_INSTANCE_ASSIGNMENT').style.display = 'none';
				setGroupTypeName(context.GroupTypeName);
			}
			break;
		case parseInt(EntityType_User):
			thumbClass=(config && config.contactContext)? 'cContactThumb':'cUserThumb';
			linkParam = 'uid='.concat( context.Id );
			lnk = CSDC.lnkOpenUser(context.Id);
		break;
		default:
			thumbClass = 'cContextThumb';
		break;
	}

	if( context.Picture )
	{
		var photoDiv=CSDC.makeDom('div',{className:'cContextPhoto'},[
		    CSDC.makeDom('a', { href:lnk }, [
				CSDC.makeDom('img', { id:'idContextPicture', src:getPictureURL( context.Picture, true ),className:thumbClass})
			])
		]);
		elt.appendChild( photoDiv );
	}
	
	var submenu = CSDC.getElt('idNavDiv');
	if( context.EntityType == EntityType_Club )
	{
		YAHOO.util.Dom.addClass( submenu, 'cGroupNav' );
	}else if(context.EntityType==EntityType_User && config && config.contactContext){
		YAHOO.util.Dom.addClass( submenu, 'cContactNav' );
	}
	
	var contextName = context.Name;
	if( contextName )
	{
		var infoDiv = CSDC.makeDom('div', {className: 'cContextInfo'});
		infoDiv.appendChild(CSDC.makeDom('a', {id: 'idContextName', href:lnk, innerText: contextName}));
		elt.appendChild(infoDiv);
	}

	var domSubmenuLinks = submenu.getElementsByTagName('a');
	for( var i=0; i < domSubmenuLinks.length; i++ )
	{
		var thisLink = domSubmenuLinks[i];
		thisLink.setAttribute('href', thisLink.getAttribute('href').replace(_linkParam, linkParam ) );
	}
	_linkParam = linkParam;
	
	var footer=CSDC.makeDom('div',{className:'cContextFooter'});
	footer.innerHTML='&nbsp;';
	elt.appendChild(footer);
}

getContextDiv = function(context)
{
	if( !context )
		return CSDC.makeDom('span');
	var elt;
	if( context.EntityType == EntityType_Club || context.EntityType == EntityType_Community )
		elt = getClubLinkElt(context);
	else if (context.EntityType == EntityType_User)
		elt = getUserLinkElt(context);
		
	if( context.Context )
	{
		var elt2 = CSDC.makeDom('span');
		elt2.appendChild(getContextDiv(context.Context));
		elt2.appendChild(document.createTextNode(" : "));
		elt2.appendChild(elt);
		return elt2;
	}
	return elt;
}

create2ButtonsDialog =function(title, innerHTML, width, okLabel, onOkCallback, dlgDivId)
{
	var dlgDiv = CSDC.getElt( dlgDivId );
	if( !dlgDiv )
		dlgDiv = CSDC.makeDom( 'div', { id: dlgDivId });
	dlgDiv.style.visibility = 'hidden';
	dlgDiv.innerHTML = '<div class="hd">'+title+'</div><div class="bd"><form>'+innerHTML+'</form></div>';;
	document.body.appendChild(dlgDiv);
		
	var dlg = new YAHOO.widget.Dialog(dlgDiv, 
			{ width: width,
			  fixedcenter: true,
			  visible: false, 
			  constraintoviewport: true,
			  postmethod: "none",
			  draggable: false,
			  modal: true,
			  effect: {effect: YAHOO.widget.ContainerEffect.FADE, duration:0.35 },
			  buttons: [ { text:okLabel, handler: onOkCallback, isDefault: true },
						  { text:"Cancel", handler: function() { CSDC.util.hideWait(); this.cancel(); } } ]
			 } );
	
	dlg.render();
	return dlg;
}

function addDlg(dlgDiv, onSubmitFcn, idAutoComplete, dataSrcAutoComplete,doDestroy, qconfig)
{
	document.body.appendChild(dlgDiv);

	if (idAutoComplete)
	{
		var myAutoComp = new YAHOO.widget.AutoComplete(idAutoComplete, "idDivAutoComplete", dataSrcAutoComplete); 
	   	myAutoComp.prehighlightClassName = "yui-ac-prehighlight";   
		myAutoComp.typeAhead = true;   
		myAutoComp.useShadow = true;   
		myAutoComp.minQueryLength = 0;   
	}
	var okFcn;
	var cancelFcn;
	if(doDestroy){
		okFcn=function(){ onSubmitFcn(); this.hide();}
		cancelFcn=function() { this.cancel(); }
	}else{
		okFcn=function(){ onSubmitFcn(); this.destroy();}
		cancelFcn=function() { this.cancel();this.destroy(); }
	}
	
	var config={ width: "380px",
			  fixedcenter: true,
			  visible: false, 
			  constraintoviewport: true,
			  postmethod: "none",
			  modal: true,
			  buttons: [ { text:"Ok", handler: okFcn, isDefault: true },
						  { text:"Cancel", handler: cancelFcn } ]
			 }
	if(qconfig){
		for(var a in qconfig){
			config[a]=qconfig[a];
		}
	}
	var dlgAdd = new YAHOO.widget.Dialog(dlgDiv.id, config );
			 

	dlgAdd.render();
	return dlgAdd;
}

/**
 * Display a "login or register" dialog in the current page. Intended to be 
 * used when a reply from the server indicates that a logged-in user session is
 * required in order to continue. After a successful login or registration, the 
 * dialog disappears and the user can retry their action. No automagic 
 * redirection takes place because of security concerns about this. 
 */
showLoginDialog = function(qjson)
{
	var params='';
	var t=null;
	var tcount=3;
	if (qjson) {
		params = qjson.iid ? "&iid=" + qjson.iid : "";
		params += qjson.inviteCode ? "&inviteCode=" + qjson.inviteCode : "";
	}
	var redirectToLogin=function(){
		cancelTimer();
		var redir='../jsp/login.jsp?redirect='+encodeURIComponent(document.location.href)+params;
		document.location=redir;
		this.hide();
	}
	
	var cancelTimer=function(){
		if(t){
			clearTimeout(t);
			t=null;
		} 
	}
	
	var checkLoginRedirect=function(){
		if(tcount>0) tcount--;
		var el=CSDC.getElt('idLoginTimer');
		if(el) el.innerHTML=tcount;
		if(tcount<=0){
			redirectToLogin();
		}else{
			t=setTimeout(checkLoginRedirect,1000);
		}
	}
	
	var dlgHTML=[
		'You need to sign in to continue.<br/>You will be redirected to the login page in <span id="idLoginTimer">',tcount,'</span> seconds.'
	].join('');
	var dlgLogin = create2ButtonsDialog('You need to sign in to continue',
		dlgHTML,
		'360px',
		'Continue',
		redirectToLogin,
		'idDivLoginDlg');
	dlgLogin.cancelEvent.subscribe(cancelTimer)
	t=setTimeout(checkLoginRedirect,1000);
	dlgLogin.show();
}

loginRegister = function()
{
	document.location = "../account/register.jsp?redirect=" + escape( document.location.href );
}
	

/**
 * TextBubble class
 * YR
 * Will generate a bubble shape text holder with drop shadow and pointing arrow
 * Used in discussions and home page, style in CSDC.css
 */
function TextBubble(){

	if(!TextBubble.oDomTemplate){
	
		TextBubble.oDomTemplate={};
		var arrRoundCornerDoms=[];
		for(var i=0;i<10;i++){
			arrRoundCornerDoms[i]=CSDC.makeDom("div",{className:"cTextBubbleCorner corner"+i},' ');
		}
		var domTemplateBubble=CSDC.makeDom("div",{className:"cTextBubble"},arrRoundCornerDoms);
		
		TextBubble.oDomTemplate.templateDomContentHolder=CSDC.makeDom("div",{className:"cTextBubbleContentHolder"},' ');
		domTemplateBubble.insertBefore(TextBubble.oDomTemplate.templateDomContentHolder,arrRoundCornerDoms[5]);
		
		var domTemplateShadow=domTemplateBubble.cloneNode(true);
		domTemplateShadow.className+=" cShadowBubble";
		
		var arrTemplateArrow=[];
		for(var j=0;j<6;j++){
			arrTemplateArrow[j]=CSDC.makeDom("div",{className:"cTextBubbleArrow",style:"width:"+j+"px;"},' ');
		}
		var domTemplateArrow=CSDC.makeDom("div",{className:"cTextBubbleArrowHolder"},arrTemplateArrow);
		TextBubble.oDomTemplate.domTop=CSDC.makeDom("div",{className:"cTextBubbleTop"},[domTemplateShadow,domTemplateArrow,domTemplateBubble]);
	}
	this.domTop=TextBubble.oDomTemplate.domTop.cloneNode(true);
	this.domContentHolder=this.domTop.lastChild.childNodes[5]; // ! modification of the template will impact this line.
	this.domShadowContentHolder=this.domTop.firstChild.childNodes[5];

	/**
	 * Call this method to set the bubble content.
	 */
	this.setInnerHTML=function(szIn){
		this.domContentHolder.innerHTML=szIn;
		fCallBar= function(){
			var _R=YAHOO.util.Dom.getRegion(this.domContentHolder);
			this.domShadowContentHolder.style.height=(_R.bottom-_R.top)+"px";
		}
		YAHOO.util.Event.onDOMReady(fCallBar,null,this);
	};
}
/*
d --> Day of the month, 2 digits with leading zeros 01 to 31 
D --> A textual representation of a day, three letters Mon through Sun 
j --> Day of the month without leading zeros 1 to 31 
l --> (lowercase 'L') A full textual representation of the day of the week Sunday through Saturday 
N --> ISO-8601 numeric representation of the day of the week (added in PHP 5.1.0) 1 (for Monday) through 7 (for Sunday) 
S --> English ordinal suffix for the day of the month, 2 characters st, nd, rd or th. Works well with j  
w --> Numeric representation of the day of the week 0 (for Sunday) through 6 (for Saturday) 

Month 
F --> A full textual representation of a month, such as January or March January through December 
m --> Numeric representation of a month, with leading zeros 01 through 12 
M --> A short textual representation of a month, three letters Jan through Dec 
n --> Numeric representation of a month, without leading zeros 1 through 12 
t --> Number of days in the given month 28 through 31 
Year 
Y --> A full numeric representation of a year, 4 digits Examples: 1999 or 2003 
y --> A two digit representation of a year Examples: 99 or 03 
Time 
a --> Lowercase Ante meridiem and Post meridiem am or pm 
A --> Uppercase Ante meridiem and Post meridiem AM or PM 
g --> 12-hour format of an hour without leading zeros 1 through 12 
G --> 24-hour format of an hour without leading zeros 0 through 23 
h --> 12-hour format of an hour with leading zeros 01 through 12 
H --> 24-hour format of an hour with leading zeros 00 through 23 
i --> Minutes with leading zeros 00 to 59 
s --> Seconds, with leading zeros 00 through 59 
Timezone  
O --> Difference to Greenwich time (GMT) in hours Example: +0200 
P --> Difference to Greenwich time (GMT) with colon between hours and minutes (added in PHP 5.1.3) Example: +02:00 
T (unsuported) Timezone setting of this machine Examples: EST, MDT ... 
Z Timezone offset in seconds. The offset for timezones west of UTC is always negative, and for those east of UTC is always positive. -43200 through 43200 
Full Date/Time 
r --> RFC 2822 formatted date Example: Thu, 21 Dec 2000 16:01:07 +0200 
U --> Seconds since the Unix Epoch (January 1 1970 00:00:00 GMT) See also time() 
*/
		Date.prototype.format = function(format) 
		{
			var returnStr = '';
			var replace = Date.ReplaceChars;
			for (var i = 0; i < format.length; i++) {
				var curChar = format.charAt(i);
				if (replace[curChar])
					returnStr += replace[curChar].call(this);
				else
					returnStr += curChar;
			}
			return returnStr;
		}
		Date.prototype.sameDay= function(dt) { return dt.getDate() == this.getDate() && dt.getMonth() == this.getMonth() && dt.getFullYear() == this.getFullYear(); }
		Date.prototype.convertToUTC=function(){
			var d=new Date(Date.parse("Thu Jan 01 1970 00:00:00 GMT"));
			d.setUTCDate(this.getDate());
			d.setUTCMonth(this.getMonth());
			d.setUTCFullYear(this.getFullYear());
			return d;
		}
		Date.ReplaceChars= {
			shortMonths: ['Jan', 'Feb', 'Mar', 'Apr', 'May', 'Jun', 'Jul', 'Aug', 'Sep', 'Oct', 'Nov', 'Dec'],
			longMonths: ['January', 'February', 'March', 'April', 'May', 'June', 'July', 'August', 'September', 'October', 'November', 'December'],
			shortDays: ['Sun', 'Mon', 'Tue', 'Wed', 'Thu', 'Fri', 'Sat'],
			longDays: ['Sunday', 'Monday', 'Tuesday', 'Wednesday', 'Thursday', 'Friday', 'Saturday'],
	

		// "Today" or "Yesterday" or "dd MMM YYYY"
		_: function() {
				var today = new Date();
				if (this.sameDay(today)) 
					return "Today";
				today.setDate(today.getDate() - 1);
				if (this.sameDay(today)) 
					return "Yesterday";
				
				return this.format("M j X");  // dd MMM YYYY
		},
		// "Today" or "Yesterday" or "D MMM dd YYYY"
		B: function() {
				var today = new Date();
				if (this.sameDay(today)) 
					return "Today";
				today.setDate(today.getDate() - 1);
				if (this.sameDay(today)) 
					return "Yesterday";
				
				return this.format("D, M j X");  // dd MMM YYYY
		},
		// day Month [Year]
		x: function() { return this.format("j FX"); },
		
		// nothing if current year, otherwise full year.
		X: function() { return this.getFullYear() == new Date().getFullYear() ? ' ' : ' '+this.getFullYear(); },

		// Day
		d: function() { return (this.getDate() < 10 ? '0' : '') + this.getDate(); },
		D: function() { return Date.ReplaceChars.shortDays[this.getDay()]; },
		j: function() { return this.getDate(); },
		l: function() { return Date.ReplaceChars.longDays[this.getDay()]; },
		N: function() { return this.getDay() + 1; },
		S: function() { return (this.getDate() % 10 == 1 && this.getDate() != 11 ? 'st' : (this.getDate() % 10 == 2 && this.getDate() != 12 ? 'nd' : (this.getDate() % 10 == 3 && this.getDate() != 13 ? 'rd' : 'th'))); },
		w: function() { return this.getDay(); },
		// Month
		F: function() { return Date.ReplaceChars.longMonths[this.getMonth()]; },
		m: function() { return (this.getMonth()+1 < 10 ? '0' : '') + (this.getMonth() + 1); },
		M: function() { return Date.ReplaceChars.shortMonths[this.getMonth()]; },
		n: function() { return this.getMonth() + 1; },
		// Year
		Y: function() { return this.getFullYear(); },
		y: function() { return ('' + this.getFullYear()).substr(2); },
		// Time
		a: function() { return this.getHours() < 12 ? 'am' : 'pm'; },
		A: function() { return this.getHours() < 12 ? 'AM' : 'PM'; },
		g: function() { return this.getHours() == 0 ? 12 : (this.getHours() > 12 ? this.getHours() - 12 : this.getHours()); },
		G: function() { return this.getHours(); },
		h: function() { var h = this.getHours() == 0 ? 12 : (this.getHours() > 12 ? this.getHours() - 12 : this.getHours()); return (h < 10 ? '0' : '') + h; },
		H: function() { return (this.getHours() < 10 ? '0' : '') + this.getHours(); },
		i: function() { return (this.getMinutes() < 10 ? '0' : '') + this.getMinutes(); },
		s: function() { return (this.getSeconds() < 10 ? '0' : '') + this.getSeconds(); },
		// Timezone
		O: function() { return (this.getTimezoneOffset() < 0 ? '-' : '+') + (this.getTimezoneOffset() / 60 < 10 ? '0' : '') + (this.getTimezoneOffset() / 60) + '00'; },
		Z: function() { return this.getTimezoneOffset() * 60; },
		// Full Date/Time
		r: function() { return this.toString(); },
		U: function() { return this.getTime() / 1000; }
	};

var arrMonth = ["January","February","March","April","May","June","July","August","September","October","November","December"];
var arrDay = ["Monday","Tuesday","Wednesday","Thursday","Friday","Saturday","Sunday"];
		
function fGetDayWithExt (dt){
	var ext = 'th';
	switch (dt.getDate()) {
		case 1:
		case 21:
		case 31:
			ext='st';
			break;
		case 2:
		case 22:
			ext='nd';
			break;
		case 3:
		case 23:
			ext='rd';
			break;
	}
	return '' + dt.getDate() + ext;
};
function fGetTime(dt){
	if (typeof dt=='string')
		dt = new Date(dt);
	var _h=dt.getHours(),
		ampm="a",
		_m=dt.getMinutes();
	if(_h>12){
		_h=_h-12;
		ampm="p";
	}
	if(_h==12){
		ampm="p";
	}
	if(_h==0){
		_h=12;
	}
	if(_m<10){
		_m="0"+_m;
	}

	return _h+((_m!=="00")?("."+_m):"")+ampm;
};

/*
  recipient: { Name:String, Id:Number}, optional 
 */
function showSendMessagePanel(recipient)
{
	CSDC.util.include(["csdc_message" ], function() {
		var pane = new CSDC.MessagePane();
		pane.showMessagePane(recipient);
	});
}

/**
 * Function to fill a portlet with a list of upcoming events. Used on user and group homepages.
 * 
 * @param jsonList
 * @return
 */
function fillEventBox( jsonList, qid )
{
	var md=CSDC.makeDom;
	
	var domBox = CSDC.getElt( 'idDivEventList' );
	if( !domBox )
	{	
		domBox = md( 'div', { id:'idDivEventList', className:'cRightBox' } );
		domBox.innerHTML="<h4 class='cRightBoxTitle cUpcomingHeader'><img class='cIcon icoCalendar' src='../images/1x1transparent.gif' /> Upcoming Activities</h4>";
		var domRightCol = CSDC.getElt( 'idRightDiv' );
		domRightCol.appendChild( domBox );
	}
	
	var oEvents = jsonList.EventList;
	var evBox=md('div',{className:'cRightBoxContent'});
	domBox.appendChild(evBox);
	evBox.appendChild(
		md('p',{className:'cRightBoxLink'},[
			md('a',{'href':CSDC.lnkOpenCalendar(qid), 'title':'View Calendar'},'View Calendar')
		])
	);
	if( oEvents.length == 0 )
		evBox.appendChild(md('div',{className:'cRightNoContent'},'No upcoming activities'));
	else
	{
		var currentDate=null;
		var allDayEvents=[];
		var standardEvents=[];
		var signups=[];
		for( var nIndex in oEvents )
		{	
			var oEvent = oEvents[nIndex];
			
			var newDate = CSDC.util.formatDate( oEvent.StartDate || oEvent.NeedBy, "D, M j" );
			if( currentDate !== newDate )
			{
				//first clear buffer
				if(allDayEvents.length>0) CSDC.domUtils.appendChildren(evBox, allDayEvents);
				if(standardEvents.length>0) CSDC.domUtils.appendChildren(evBox, standardEvents);
				if(signups.length>0) CSDC.domUtils.appendChildren(evBox, signups);
				
				//then add new date header
				currentDate = newDate;
				evBox.appendChild(md('div',{className:'cRightBoxEntry cEventBoxDate'}, currentDate));
				
				allDayEvents=[];
				standardEvents=[];
				signups=[];
			}
			

			if (oEvent.NeedBy) {
				var tmpSignupLabel=oEvent.Name;
				if (qid)
					tmpSignupLabel += " ("+ (oEvent.Volunteer ? oEvent.Volunteer.Name: "Open") +")";
				var tmpSignup=md('div',{className: 'cRightBoxEntry'},[
					md('img',{className:'cIcon icoVolunteer', src:'../images/1x1transparent.gif'}),
					md('a',{className:'cSignupItemLink', 'id':oEvent.Id, 'href':'../jsp/signup.jsp?id='+oEvent.ListId}, tmpSignupLabel)
				]);
				signups.push(tmpSignup);
			}
			else {
				var eventLinkClass=(oEvent.Color!=undefined)? 'cEventLinkName cEventLink_'+oEvent.Color:'cEventLinkName';
				try{
					var eventType=CSDC.events.types.getTypeById(oEvent.evType);
					if(eventType && eventType.config.hasCalIcon){
						eventLinkClass+=' cMiniEvType cEvType'+eventType.id;
					}
				}catch(error){}
				
				var eventLinkDate=md('span',{className:'cEventLinkDate'});
				eventLinkDate.innerHTML=(oEvent.AllDay)? '' /*'All Day'*/:CSDC.util.formatDate( oEvent.StartDate, CSDC.util.DateFormat_TimeOnly );
				eventLinkDate.innerHTML+='&nbsp;&nbsp;';
				var tmpEvent=md('div',{className:'cRightBoxEntry'},[
					md('a',{
						'href':'../jsp/event.jsp?eid='+oEvent.Id+'&calid='+oEvent.CalendarId,
						className:'cEventLink',
						'id':'evLink_'+oEvent.Id+'_'+oEvent.CalendarId
					},[
						eventLinkDate,
						md('span',{className:eventLinkClass}, CSDC.util.cutText(oEvent.Name,90))
					])
				]);
				if(oEvent.AllDay){
					allDayEvents.push(tmpEvent);
				}else{
					standardEvents.push(tmpEvent);
				}
			}
		}
		//add any remaining events in buffer
		if(allDayEvents.length>0) CSDC.domUtils.appendChildren(evBox, allDayEvents);
		if(standardEvents.length>0) CSDC.domUtils.appendChildren(evBox, standardEvents);
		if(signups.length>0) CSDC.domUtils.appendChildren(evBox, signups);
	}
	CSDC.tooltip.init();
	md=null;
}
var _groupTypeName = "Group";
var _isParentGroup = false;
function setGroupTypeName(typename)
{
	_isParentGroup = true;
	_groupTypeName = typename || "Group";
	var elts = YAHOO.util.Dom.getElementsByClassName('cTypeName', 'span');
	for (var jj=0;jj< elts.length;jj++)
		elts[jj].innerHTML = _groupTypeName;
}

function minutesToHours(qvalue){
	qvalue=parseInt(qvalue,10);
	var hours=Math.floor(qvalue/60);
	var minutes=qvalue%60;
	
	var str=[];
	if(hours>0){
		str.push(hours+'h');
	}
	if(minutes>0){
		str.push(minutes+'m');
	}
	if(str.length>0){
		return str.join(' ');
	}else{
		return '0';
	}
}
//used for assignments
function parseEstimate(qmin,qmax,qformat){
	var timeEstimateStr=[];
	if(qmin!==null || qmin!==''){
		timeEstimateStr.push(minutesToHours(qmin));
	}
	if((qmax!==null || qmax!=='') && qmax!==0){
		timeEstimateStr.push('to '+minutesToHours(qmax));
	}
	if(timeEstimateStr.length==1 && timeEstimateStr[0]==0){
		timeEstimateStr=[];
	}
	return timeEstimateStr;
}