if (!activeHelpBubbles) var activeHelpBubbles = Array();

var App = 
{
	interval: 0,
	params: null, 
	
	init: function(section)
	{
		this.params = [];
		Page.init(section);
	},
	
	setParam: function(key, val)
	{
		this.params[key] = val;
	},
	
	getComponent: function()
	{
		return this.params['component'];
	},
	
	load: function(url, target, params)
	{
		if (!params) params = {};
		return App.request(url, 'GET', params, target);
	},

	send: function(id, target, params)
	{
		if ($(id)) var form = $(id);
		else return false;
		if (!params) params = {};
		params = Object.extend(params, form.serialize(true));
		return App.request(form.action, form.method, params, target);
	},
	
	request: function(url, method, params, target)
	{
		var success = false;
		params.AJAX = '1';
		
		if (target && $(target))
		{
			var loader = (this.params['ajax_loader'] != null) ? this.params['ajax_loader'] : $('ajax_loader').innerHTML;
			$(target).update(loader);
			this.params['ajax_loader'] = null;
		}
		
		var req = new Ajax.Request(url,
		{
			method: method,
			parameters: params,
			evalScripts:true,
			onSuccess: function(transport)
			{
				if (transport.responseText.isJSON())
				{
					var response = transport.responseText.evalJSON(true);
					
					$A(response.actions).each(function(e)
					{
						if (!e.vars) e.vars = {};
						
						if (e.success) App.onFailure = null;
						else App.onSuccess = null;
						
						switch (e.action)
						{
							case 'alert': alert(Page.getMsg(e.alert, e.vars)); break;
							case 'redirect': window.parent.location = e.redirect; break;
							case 'reload': window.parent.location.reload(); break;
							case 'error': Component.showError(Page.getMsg(e.error, e.vars)); break;
							case 'notice': Component.showNotice(Page.getMsg(e.notice, e.vars)); break;
							case 'success': Component.showSuccess(Page.getMsg(e.success, e.vars)); break;
						}
						
					});
				}
				else
				{
					if ($(target)) $(target).update(transport.responseText);
				}
				
				if (App.onSuccess)
				{
					App.onSuccess(transport.responseText);
					App.onSuccess = null;
				}
				else if (App.onFailure)
				{
					App.onFailure(transport.responseText);
					App.onFailure = null;
				}
				
				success = true;
			},
			onFailure: function()
			{
				alert(Page.getMsg('msg_default_error'));
			}
		});
		
		return success;
	},
	
	getURLParam: function(name)
	{
		var found = false;
		var strReturn = "";
		
		if (window.location.href.substrCount("#") > 0) { var href = window.location.href.split("#")[0]; } else { var href = window.location.href; }
		if (href.indexOf("?") > -1 ) {
			var strQueryString = href.substr(href.indexOf("?") + 1);
			var aQueryString = strQueryString.split("&");
			
			for (var iParam = 0; iParam < aQueryString.length; iParam++ ) {
				var paramParts = aQueryString[iParam].split("=");
				
				if (paramParts[0] == name) {
					strReturn = paramParts[1];
					found = true;
				}
			}
		}
		
		if (found == true) return unescape(strReturn);
		else return false;
	},

	urlParamExists: function(name)
	{
		var found = false;
		
		if (window.location.href.substrCount("#") > 0) { var href = window.location.href.split("#")[0]; } else { var href = window.location.href; }
		if (href.indexOf("?") > -1 ) {
			var strQueryString = href.substr(href.indexOf("?") + 1);
			var aQueryString = strQueryString.split("&");
			
			for (var iParam = 0; iParam < aQueryString.length; iParam++ ) {
				var paramParts = aQueryString[iParam].split("=");
				if (paramParts[0] == name) { found = true; }
			}
		}
		
		if (found == true) return true;
		else return false;
	},
	
	classExists: function(c)
	{
		if (typeof(c) == "object") return true;
		else return false;
	},
	
	getMouse: function(e)
	{
		return (e && e.pageX) ? {"x":e.pageX, "y":e.pageY} : {"x":event.clientX + (document.documentElement.scrollLeft ? document.documentElement.scrollLeft : document.body.scrollLeft), "y":event.clientY + (document.documentElement.scrollTop ? document.documentElement.scrollTop : document.body.scrollTop)};
	},
	
	getBrowser: function()
	{
		var browser = "unknown";
		var agent = navigator.userAgent.toLowerCase();
		var possibles = new Array('safari','msie 6','msie','firefox','netscape','omniweb','avantbrowser','msn','konqueror','camino','chrome');
		
		for (var i=0;i<possibles.length;i++)
		{
			if (agent.indexOf(possibles[i]) > -1)
			{
				browser = possibles[i];
				break;
			}
		}
		
		return browser;
	},
	
	autoload: function(url, target, params)
	{
		if (App.interval > -1) App.load(url, target, params);
	},
	
	initAutoload:function(url, target, params)
	{
		App.interval--;
		App.resetAutoload.delay(0.7);
		App.autoload.delay(0.73, url, target, params);
	},
	
	resetAutoload: function ()
	{
		App.interval++;
	},
	
	__void__: function()
	{
		// see, nothing at all
	}
};

var Page = 
{
	win: null,
	
	init: function(section)
	{
		this.registerComponents();
		this.registerToggleElements();
		
		if ($('nav_' + section))
		{
			var e = $('nav_' + section);
			e.className = "active";
		}
	},
	
	absPos: function(el)
	{
		var pos = {"x":el.offsetLeft,"y":el.offsetTop,"width":el.offsetWidth,"height":el.offsetHeight};
		
		while(el && el.offsetParent)
		{
			while (el.parentNode!=el.offsetParent && (el.parentNode.scrollLeft || el.parentNode.scrollTop))
			{
				el=el.parentNode;
				pos['x'] -= el.scrollLeft ? el.scrollLeft : 0;
				pos['y'] -= el.scrollTop ? el.scrollTop : 0;
			}
			
			pos['x'] += el.offsetParent.offsetLeft;
			pos['y'] += el.offsetParent.offsetTop;
			
			el = el.offsetParent;
		}
		
		pos['n'] = pos['y'];
		pos['w'] = pos['x'];
		pos['s'] = pos['y']+pos['height'];
		pos['e'] = pos['x']+pos['width'];
		
		return pos;
	},
	
	getPoint: function(el, dir, buffer)
	{
		var pos = Page.absPos(el);
		
		switch(dir)
		{
			case 'nw': return {'x':pos.w-buffer, 			'y':pos.n-buffer};
			case 'n':  return {'x':pos.w+(pos.e-pos.w)/2, 	'y':pos.n-buffer};
			case 'ne': return {'x':pos.e+buffer, 			'y':pos.n-buffer};
			case 'e':  return {'x':pos.e+buffer, 			'y':pos.n+(pos.s-pos.n)/2};
			case 'se': return {'x':pos.e+buffer, 			'y':pos.s+buffer};
			case 's':  return {'x':pos.w+(pos.e-pos.w)/2, 	'y':pos.s+buffer};
			case 'sw': return {'x':pos.w-buffer, 			'y':pos.s+buffer};
			case 'w':  return {'x':pos.w-buffer, 			'y':pos.n+(pos.s-pos.n)/2};
		}
	},
	
	registerComponents: function()
	{
		$$(".component").each(function(e)
		{
			Object.extend(e, Component);
			e.registerTabs();
			e.registerInlineTabs();
			e.init();
		});
	},
	
	registerToggleElements: function()
	{
		$$(".toggle").each(function(e)
		{
			e.observe('click', function(event)
			{
				var el = Event.element(event);
				el.toggleClassName("plus");
				el.up('div').down(".toggle-content").toggle();
				el.title = (el.className.include("plus")) ? $('str_expand').innerHTML : $('str_collapse').innerHTML;
 			});
		});
	},
	
	showHelperBubble: function(text, option)
	{
		Page.showHelpBubble(text, option);
	},
		
	showHelp: function(e, id, target)
	{
		if (!e || !$(id)) return;
		e.down('.help-icon').toggleClassName("help-icon-bg");
		if (target) e = target;
		
		if (!e.down('.help-body'))
		{
			var tpl = new Template($('help_template').innerHTML);
			e.insert(tpl.evaluate({content: $(id).innerHTML}));
		}
		
		e.down('.help-body').toggle();
	},
	
	showHelpBubble: function(text, options, fade_time)
	{
		if (!fade_time) var fade_time = false;
		
		var helperContainer = "bubble_loader";
		
		if (text) {
			if (typeof(text) != "string") helperContainer = text.id;
			else if ($(text)) helperContainer = text;
			else $('bubble_loader').innerHTML = text;
		}
		
		helpBubble.show(helperContainer, options, fade_time);
	},
	
	hideHelpBubble: function(text)
	{
		var helperContainer = "bubble_loader";
		
		if (text) {
			if (typeof(text) != "string") helperContainer = text.id;
			else if ($(text)) helperContainer = text;
			else $('bubble_loader').innerHTML = text;
		}
		
		helpBubble.hide(helperContainer);
	},
	
	getMsg: function(id, vars)
	{
		if (!vars) vars = {};
		var tmpl = new Template($(id) ? $(id).innerHTML : $('msg_default_error').innerHTML);
		return tmpl.evaluate(vars);
	},
	
	validateForm: function(fields)
	{
		var response = { 'valid':true };
		
		fields.each(function(e)
		{
			if ($(e) && $F(e).blank())
			{
				var msg = (e.startsWith('confirm_')) ? 'msg_confirm_' + e.substring(8) : 'msg_missing_' + e;
			}
			else if ($(e) && e.startsWith('confirm_') && $F(e) != $F(e.substring(8)))
			{
				var msg = 'msg_match_' + e.substring(8);
			}
			else if ($(e) && e.include("username"))
			{
				var valid = true;
				var username = $F(e).strip();
				
				if (username.match(" "))
				{
					valid = false;
				}
				
				if (valid == false) var msg = 'msg_invalid_' + e;
			}
			else if ($(e) && e.include("email"))
			{
				var valid = true;
				var email = $F(e).strip();
				var at = email.indexOf("@");
				var dot = email.lastIndexOf(".");
				
				if (at < 1 || dot < 3 || dot == email.length -1 || (dot - at) < 2)
				{
					valid = false;
				}
				else
				{
					var invalidCharsLocal = '()[]:;"<>';
					var invalidCharsDomain = '!#$%^*()+{}[]|/:;"\'\\>?<,';
					for (var i = 0; i < at; i++) { if (invalidCharsLocal.indexOf(email.charAt(i)) != -1) valid = false; }
					for (var i = at; i < email.length; i++) { if (invalidCharsDomain.indexOf(email.charAt(i)) != -1) valid = false; }
				}
				
				if (valid == false) var msg = 'msg_invalid_' + e;
			}
			else if ($(e) && e.include("phone"))
			{
				var valid = true;
				var phone = $F(e).strip();
				phone = phone.replace(/[A-Wa-w\WY-Zy-z]/g, "");
				if(phone.length<10) valid = false;
				if(valid==false) var msg = 'msg_invalid_' + e;
			}
			else if ($(e) && e.include("zip"))
			{
				var valid = true;
				var zip = $F(e).strip();
				if(!zip.match(/(^\d{5}(-\d{4})?$)|(^[ABCEGHJKLMNPRSTVXY]{1}\d{1}[A-Z]{1} *\d{1}[A-Z]{1}\d{1}$)/))
					valid = false;
				if(valid==false) var msg = 'msg_invalid_' + e;
			}
			
			if (msg)
			{
				Page.highlightElement(e);
				response = { 'valid':false, 'element':e, 'msg':msg };
				throw $break;
			}
			
		});
		
		return response;
	},
	
	highlightElement: function(e, className)
	{
		if ($(e))
		{
			if (!className) var className = 'invalid';
			$(e).addClassName(className);
			new Form.Element.Observer(e, 0.2, function(el, value) { el.removeClassName(className); });
		}
	},
	
	loadActionBox: function(top,title)
	{
		$('action-box-container').style.visibility = 'hidden';
		$('action-box-container').style.display = 'block';
		
		if (title) {
			$('action-box-title').style.display = "block";
			$('action-box-title').innerHTML = title;
		}
		
		if (App.getBrowser() == "msie 6") {
			var selects = document.getElementsByTagName('select');
			for (i = 0; i < selects.length; i++) selects[i].style.visibility = 'hidden';
		}
		
		Page.correctActionBox(false,top);
		
		$('action-box-container').style.visibility = 'visible';
	},
	
	showActionBox: function(creator, obj)
	{
		if (obj.url || obj.raw)
		{
			if (!obj.params) obj.params = {};
			if (!obj.method) obj.method = 'GET';
			
			if (obj.title) obj.title = "'"+obj.title+"'";
			else obj.title = false;
			
			if (obj.top) obj.top = "'"+obj.top+"'";
			else obj.top = false;
			
			if (obj.url) {
				App.onSuccess = function() { setTimeout("Page.loadActionBox("+obj.top+","+obj.title+")",200); }
				App.request(obj.url, 'GET', obj.params, 'action-content');
			} else if (obj.raw) {
				$('action-content').innerHTML = obj.raw;
				setTimeout("Page.loadActionBox("+obj.top+","+obj.title+")",200);
			}
		}
	},
	
	hideActionBox: function()
	{
		if (App.getBrowser() == "msie 6") {
			var selects = document.getElementsByTagName('select');
			for (i = 0; i < selects.length; i++) selects[i].style.visibility = 'visible';
		}
		
		$('action-box-container').style.display = 'none';
	},
	
	correctActionBox: function(noTop,top)
	{
		if (navigator.userAgent.toLowerCase().indexOf("msie") > -1)
		{
			var scrollOffsets = document.viewport.getScrollOffsets();
			if (!noTop) $('action-box-container').style.top = (scrollOffsets[1]+((document.viewport.getHeight()/2)-($('action-box').clientHeight/2)))+"px";
			
			$('action-box-container').style.left = ((document.body.offsetWidth/2)-($('action-box').clientWidth/2))+"px";
			
			$('action-box-backdrop').style.width = ($('action-box').clientWidth+29.5)+"px";
			$('action-box-backdrop').style.height = ($('action-box').clientHeight+29.5)+"px";

			if (location.href.indexOf("shapeupthenation.com") > -1) {
				$('action-box-backdrop').style.top = ($('action-box').offsetTop)+"px";
				$('action-box-backdrop').style.left = ($('action-box').offsetLeft+3.5)+"px";
			} else {
				$('action-box-backdrop').style.top = ($('action-box').offsetTop-3.5)+"px";
				$('action-box-backdrop').style.left = ($('action-box').offsetLeft-0.5)+"px";
			}
		}
		else
		{
			var scrollOffsets = document.viewport.getScrollOffsets();
			if (!noTop) $('action-box-container').style.top = (scrollOffsets[1]+((document.viewport.getHeight()/2)-($('action-box').clientHeight/2)))+"px";
			
			$('action-box-container').style.left = ((window.innerWidth/2)-($('action-box').clientWidth/2))+"px";
			
			$('action-box-backdrop').style.width = ($('action-box').clientWidth+29.5)+"px";
			$('action-box-backdrop').style.height = ($('action-box').clientHeight+29.5)+"px";
			
			if (location.href.indexOf("shapeupthenation.com") > -1) {
				$('action-box-backdrop').style.top = ($('action-box').offsetTop)+"px";
				$('action-box-backdrop').style.left = ($('action-box').offsetLeft+3.5)+"px";
			} else {
				$('action-box-backdrop').style.top = ($('action-box').offsetTop-3.5)+"px";
				$('action-box-backdrop').style.left = ($('action-box').offsetLeft-0.5)+"px";
			}
		}
		
		if (!noTop && top) {
			$('action-box-container').style.top = top+"px";
			$('action-box-backdrop').style.top = (top-103)+"px";
		}
		
		// If the reach extends beyong the viewport, shrink it
		var viewHeight = document.viewport.getHeight();
		var boxReach = $('action-box-backdrop').viewportOffset().top + parseFloat($('action-box-backdrop').style.height.strReplace("px",""));
		
		if (boxReach > viewHeight) {
			var correctedHeight = viewHeight - $('action-box-backdrop').viewportOffset().top;
			
			$('action-content').style.height = (correctedHeight-63)+"px";
			$('action-box-backdrop').style.height = (correctedHeight)+"px";
			
			if (navigator.userAgent.toLowerCase().indexOf("msie") < 0) $('action-content').style.overflow = "auto";
		} else {
			if (navigator.userAgent.toLowerCase().indexOf("msie") < 0) $('action-content').style.overflow = "none";
		}
	},
	
	showLightbox: function(creator, obj)
	{
		if (!obj) obj = {};
		var xPos = 0; var yPos = 0;
		
		if (navigator.userAgent.toLowerCase().indexOf("msie") + 1 > 0)
		{
			if (self.pageYOffset) yPos = self.pageYOffset;
			else if (document.documentElement && document.documentElement.scrollTop) yPos = document.documentElement.scrollTop; 
			else if (document.body) yPos = document.body.scrollTop;
		}
		
		bod = document.getElementsByTagName('body')[0];
		bod.style.height = '100%';
		bod.style.overflow = 'hidden';
		
		htm = document.getElementsByTagName('html')[0];
		htm.style.height = '100%';
		htm.style.overflow = 'hidden';
		
		var selects = document.getElementsByTagName('select');
		for (i = 0; i < selects.length; i++) selects[i].style.visibility = 'hidden';
		window.scrollTo(0, 0); 
		
		$('lightbox-overlay').show();
		
		var lightbox = $('lightbox');
		Object.extend(lightbox, Object);
		lightbox.show();
		lightbox.creator = creator;
		
		if (obj.url)
		{
			if (!obj.params) obj.params = {};
			if (!obj.method) obj.method = 'GET';
			
			new Ajax.Updater({ success:$('lightbox-content')}, obj.url,
			{
				method:obj.method, evalScripts:true, parameters:obj.params
			});
		}
	},
	
	hideLightbox: function(url, params)
	{
		$('lightbox-content').update(" ");
		$('lightbox').hide();
		$('lightbox-overlay').hide();
		
		bod = document.getElementsByTagName('body')[0];
		bod.style.height = 'auto';
		bod.style.overflow = 'auto';
  
		htm = document.getElementsByTagName('html')[0];
		htm.style.height = 'auto';
		htm.style.overflow = 'auto';
		
		var selects = document.getElementsByTagName('select');
		for (i = 0; i < selects.length; i++) selects[i].style.visibility = '';
		window.scrollTo(0, 0); 		
	}
};

var Component = 
{
	msgDiv: null, 
	
	init: function()
	{
		this.params = [];
		
		this.observe('click', function(event)
		{
			App.setParam('component', this);
		});
		
		$$('.msg').each(function(e)
		{
			e.observe('click', function(event) { e.hide(); });
		});
	},
	
	setParam: function(key, val)
	{
		this.params[key] = val;
	},
	
	setMsg: function(id)
	{
		if ($(id))
		{
			$(id).hide();
			this.msgDiv = $(id);
		}
	},
	
	getMsg: function()
	{
		return (this.msgDiv !== null) ? this.msgDiv : App.getComponent().down(".msg");
	},
	
	showNotice: function(msg)
	{
		this.showMsg(msg, "notice");
	},
	
	showError: function(msg)
	{
		this.showMsg(msg, "error");
	},
	
	showSuccess: function(msg)
	{
		this.showMsg(msg, "success");
	},
	
	showMsg: function(msg, className)
	{
		this.clearMsg();
		var e = this.getMsg();
		if (!e) return;
		
		e.observe('click', function(event) { this.hide(); });
		e.addClassName(className);
		e.update(msg);
		e.show();
		
		if (e.up('.scroll'))
		{
			var s = e.up('.scroll');
			// s.scrollTop = e.getOffsetParent().offsetTop;
			
		}
		if (e.viewportOffset().top < 0 || e.viewportOffset().top > document.viewport.getDimensions().height) e.scrollTo();
	},
	
	clearMsg: function()
	{
		var e = this.getMsg();
		if (!e) return;
		if (e.className == 'msg') return;
		
		e.stopObserving('click');
		e.removeClassName('notice');
		e.removeClassName('error');
		e.removeClassName('success');
		e.update("");
	},
	
	registerTabs: function()
	{
		try
		{
			$$(".component-tabs").each(function(el)
			{
				if (el.down("tr").childElements())
				{
					var tabs = [];
					
					el.down("tr").childElements().each(function(e)
					{
						if (e.className.match('component-tab')) tabs.push(e);
					});
					
					tabs.each(function(e)
					{
						e.observe('click', function(event)
						{
							tabs.each(function(el)
							{
								el.removeClassName("tab-on");
								el.down(".tab-content").removeClassName("tab-content-on");
							});
							
							this.addClassName("tab-on");
							this.down(".tab-content").addClassName("tab-content-on");
			 			});
					});
				 }
			});
		}
		catch (err)	{ }
	},
	
	activateTab: function(id)
	{
		if ($(id))
		{
			$(id).addClassName("tab-on");
			$(id).down(".tab-content").addClassName("tab-content-on");
		}
	},
	
	deactivateTab: function(id)
	{
		if ($(id))
		{
			$(id).removeClassName("tab-on");
			$(id).down(".tab-content").removeClassName("tab-content-on");
		}
	},
	
	loadTabContent: function(event, action, params)
	{
		var e = Event.element(event);
		var tab_content = e.up('.component-container').down('.component-content');
		
		App.request('/cp/' + action + '/', 'GET', params, tab_content.id);
	},

	registerInlineTabs: function()
	{
		try
		{
			$$(".inline-component-tabs").each(function(el)
			{
				if (el.down("ul").childElements())
				{
					var tabs = [];
					
					el.down("ul").childElements().each(function(e)
					{
						tabs.push(e);
					});
					
					tabs.each(function(e)
					{
						e.observe('click', function(event)
						{
							tabs.each(function(el)
							{
								el.removeClassName("active");
							});
							
							this.addClassName("active");
			 			});
					});
				 }
			});
		}
		catch (err)	{ }
	},
	
	loadInlineTabContent: function(event, action, params)
	{
		if (typeof(event) == "string") var container = event;
		else {
			var e = Event.element(event);
			var tab_content = e.up('.tab_content').down('.component-tab-content');
			var container = tab_content.id;
		}
		
		App.request('/cp/' + action + '/', 'GET', params, container);
	},
	
	toggleTabIcon: function(className, id)
	{
		$$('.' + className).each(function(e) { if (e) e.src = e.src.replace('_on', '_off'); });
		
		if ($(id))
		{
			var e = $(id);
			if (e) e.src = e.src.replace('_off', '_on');
		}	
	}
};

var Util = 
{
	getTimezoneOffset: function()
	{
		var d = new Date();
		return (d.getTimezoneOffset() / 60) * (-1);
	}
};

function displayChange(elem)
{
	if($('select_')) var junk = $('select_');
	var subs = elem.parentNode.descendants();
	
	for(j = 0; j < subs.length; j++)
	{
		if(subs[j] != elem)
		{
			if(subs[j].tagName=="SELECT") subs[j].value = "";
			if(subs[j].tagName=="DIV") subs[j].hide();
		}
	}
	if ($(elem.value) == null)
	{
	}
	else
	{
		$(elem.value).show();
	}
}

function getCheckedValue(radioObj)
{
	if(!radioObj) return "";
	var radioLength = radioObj.length;
	
	if (radioLength == undefined)
		if(radioObj.checked)
			return radioObj.value;
		else
			return "";
	for(var i = 0; i < radioLength; i++) {
		if(radioObj[i].checked) {
			return radioObj[i].value;
		}
	}
	return "";
}

function hasClass(element,cls)
{
	return element.className.match(new RegExp('(\\s|^)'+cls+'(\\s|$)'));
}

function addClass(element,cls)
{
	if (!this.hasClass(element,cls)) element.className += " "+cls;
}

function removeClass(element,cls)
{
	if (hasClass(element,cls)) {
		var reg = new RegExp('(\\s|^)'+cls+'(\\s|$)');
		element.className = element.className.replace(reg,' ');
	}
}

function isLetter(val)
{
	if(val.charCode) val = String.fromCharCode(val.charCode);
	return (val.toString().search(/^[a-zA-Z]+$/) == 0);
}

function isInt(val)
{
	if(val.charCode) val = String.fromCharCode(val.charCode);
	return (val.toString().search(/^-?[0-9]+$/) == 0);
}

function isNumeric(val)
{
	if(val.charCode) val = String.fromCharCode(val.charCode);
	return (val.toString().search(/^-?[0-9\.]+$/) == 0);
}

function daysInMonth(mon,year)
{
	return 32 - new Date(year,mon,32).getDate();
}

function isArray(mixed_var)
{
    return (mixed_var instanceof Array);
}

function strtotime(str,now)
{
	if (!now) var now = new Date();
	
    var i, match, s, strTmp = '', parse = '';
    
    strTmp = str;    
    strTmp = strTmp.replace(/\s{2,}|^\s|\s$/g,' ');
    strTmp = strTmp.replace(/[\t\r\n]/g, '');
 
    if (strTmp == 'now') return (new Date()).getTime()/1000;    
    else if (!isNaN(parse = Date.parse(strTmp))) return (parse/1000);
    else if (now) now = new Date(now*1000);
    else now = new Date();
    
    strTmp = strTmp.toLowerCase();
    
	var __is = {
				day: {
        			'sun': 0,
        			'mon': 1,
        			'tue': 2,
        			'wed': 3,
        			'thu': 4,
        			'fri': 5,
        			'sat': 6
    			},
    			mon: {
    				'jan': 0,
    				'feb': 1,
    				'mar': 2,
    				'apr': 3,
    				'may': 4,
    				'jun': 5,
    				'jul': 6,
    				'aug': 7,
    				'sep': 8,
    				'oct': 9,
    				'nov': 10,
    				'dec': 11
    			}
	};
		
	var process = function (m) {
		var ago = (m[2] && m[2] == 'ago');
		var num = (num = m[0] == 'last' ? -1 : 1) * (ago ? -1 : 1);
		
		switch (m[0]) {
        	case 'last':
        	case 'next':
        		switch (m[1].substring(0, 3)) {
                	case 'yea':
                		now.setFullYear(now.getFullYear() + num);
                    break;
                    
                	case 'mon':
                		now.setMonth(now.getMonth() + num);
                    break;
                
                	case 'wee':
                		now.setDate(now.getDate() + (num * 7));
                	break;
                	
                	case 'day':
                		now.setDate(now.getDate() + num);
                    break;
                	
                	case 'hou':
                		now.setHours(now.getHours() + num);
                    break;
                
                	case 'min':
                		now.setMinutes(now.getMinutes() + num);
                    break;
                    
                	case 'sec':
                		now.setSeconds(now.getSeconds() + num);
                    break;
                
                	default:
                		var day;
                		if (typeof (day = __is.day[m[1].substring(0, 3)]) != 'undefined') {
                			var diff = day - now.getDay();
                			if (diff == 0) {
                				diff = 7 * num;
                			} else if (diff > 0) {
                				if (m[0] == 'last') { diff -= 7; }
                			} else {
                				if (m[0] == 'next') { diff += 7; }
                			}
                			
                			now.setDate(now.getDate() + diff);
                		}
        		}
            break;
            
        	default:
        		if (/\d+/.test(m[0])) {
        			num *= parseInt(m[0], 10);
        			
        			switch (m[1].substring(0, 3)) {
                    	case 'yea':
                    		now.setFullYear(now.getFullYear() + num);
                        break;
                        
                    	case 'mon':
                    		now.setMonth(now.getMonth() + num);
                        break;
                        
                    	case 'wee':
                    		now.setDate(now.getDate() + (num * 7));
                        break;
                    
                    	case 'day':
                    		now.setDate(now.getDate() + num);
                    	break;
                    
                    	case 'hou':
                    		now.setHours(now.getHours() + num);
                        break;
                    
                    	case 'min':
                    		now.setMinutes(now.getMinutes() + num);
                        break;
                    
                    	case 'sec':
                    		now.setSeconds(now.getSeconds() + num);
                        break;
        			}
        		} else {
        			return false;
        		}
        	break;
		}
		
		return true;
	};
	
	match = strTmp.match(/^(\d{2,4}-\d{2}-\d{2})(?:\s(\d{1,2}:\d{2}(:\d{2})?)?(?:\.(\d+))?)?$/);
	if (match != null) {
		if (!match[2]) match[2] = '00:00:00';
        else if (!match[3]) match[2] += ':00';
		
        s = match[1].split(/-/g);
        
        for (i in __is.mon) {
        	if (__is.mon[i] == s[1] - 1) s[1] = i;
        }
        
        s[0] = parseInt(s[0], 10); 
        s[0] = (s[0] >= 0 && s[0] <= 69) ? '20'+(s[0] < 10 ? '0'+s[0] : s[0]+'') : (s[0] >= 70 && s[0] <= 99) ? '19'+s[0] : s[0]+'';
        
        return parseInt(this.strtotime(s[2] + ' ' + s[1] + ' ' + s[0] + ' ' + match[2])+(match[4] ? match[4]/1000 : ''), 10);
	}
    
	var regex = '([+-]?\\d+\\s'+
        '(years?|months?|weeks?|days?|hours?|min|minutes?|sec|seconds?'+
        '|sun\\.?|sunday|mon\\.?|monday|tue\\.?|tuesday|wed\\.?|wednesday'+
        '|thu\\.?|thursday|fri\\.?|friday|sat\\.?|saturday)'+
        '|(last|next)\\s'+        '(years?|months?|weeks?|days?|hours?|min|minutes?|sec|seconds?'+
        '|sun\\.?|sunday|mon\\.?|monday|tue\\.?|tuesday|wed\\.?|wednesday'+
        '|thu\\.?|thursday|fri\\.?|friday|sat\\.?|saturday))'+
        '(\\sago)?';
	
    match = strTmp.match(new RegExp(regex, 'gi')); // Brett: seems should be case insensitive per docs, so added 'i'
    
    if (match == null) return false;
    
    for (i = 0; i < match.length; i++) {
    	if (!process(match[i].split(' '))) return false;
    }
    
    return (now.getTime()/1000);
}

function arrayMerge() {
    var args = Array.prototype.slice.call(arguments);
    var retObj = {}, k, j = 0, i = 0;
    var retArr;
    
    for (i=0, retArr=true; i < args.length; i++) {
        if (!(args[i] instanceof Array)) {
            retArr=false;            
            break;
        }
    }
    
    if (retArr) return args;
    
    var ct = 0;
    
    for (i=0, ct=0; i < args.length; i++) {        
    	if (args[i] instanceof Array) for (j=0; j < args[i].length; j++) retObj[ct++] = args[i][j];
        else {            
        	for (k in args[i]) {
                if (this.is_int(k)) retObj[ct++] = args[i][k];
                else retObj[k] = args[i][k];
            }
        }
    }
    
    return retObj;
}

Array.prototype.nsort = function(sort_flags) {
	var valArr = [], keyArr = [], k = '', i = 0, sorter = false, that = this, populateArr = [];
	
	switch (sort_flags) {
		case 'SORT_STRING':
			sorter = function (a, b) {
                return that.strnatcmp(a, b);
            };
        break;
        
        case 'SORT_NUMERIC':
            sorter = function (a, b) {
                return (a - b);
            };
        break;
            
        case 'SORT_REGULAR':
        default:
            sorter = function (a, b) {
                if (a > b) return 1;
                if (a < b) return -1;
                return 0;
            };
        break;
    }
	
    for (k in this) {
        if (this.hasOwnProperty) valArr.push(this[k]);
    } 
    
    valArr.sort(sorter);
    for (i = 0; i < valArr.length; i++) if (isNumeric(valArr[i])) populateArr[i] = valArr[i];
    return populateArr;
}

Array.prototype.rsort = function(sort_flags)
{
	var inputArr = this;
	var valArr=[], keyArr=[], k, i, ret, sorter, that = this, strictForIn = false, populateArr = [];
	 
    switch (sort_flags) {
        case 'SORT_STRING':
            sorter = function (a, b) {
            	return that.strnatcmp(b, a);
            };
        break;
        
        case 'SORT_NUMERIC':
            sorter = function (a, b) {
                return (a - b);
            };
        break;
        
        case 'SORT_REGULAR':
        default:
            sorter = function (a, b) {
        		if (a > b) return 1;
                if (a < b) return -1;
                return 0;
            };
        break;
    } 
    
    var bubbleSort = function (keyArr, inputArr) {
        var i, j, tempValue, tempKeyVal;
        for (i = inputArr.length-2; i >= 0; i--) {
            for (j = 0; j <= i; j++) {
            	ret = sorter(inputArr[j+1], inputArr[j]);
                if (ret > 0) {
                    tempValue = inputArr[j];
                    inputArr[j] = inputArr[j+1];
                    inputArr[j+1] = tempValue;
                    tempKeyVal = keyArr[j];
                    keyArr[j] = keyArr[j+1];
                    keyArr[j+1] = tempKeyVal;
                }
            }
        }
    };
    
    for (k in inputArr) {
        if (inputArr.hasOwnProperty) {
        	valArr.push(inputArr[k]);
            keyArr.push(k);
        }
    }
    
    try { bubbleSort(keyArr, valArr); } catch (e) { return false; }
    
    return valArr;
}

Array.prototype.array_unique = function()
{
	var retArr = Array();
    var chkArr = this;
	
    for (var i = 0; i < chkArr.length; i++) {
    	if (chkArr[i] != "") {
    		if (!retArr.inArray(chkArr[i])) retArr.push(chkArr[i]);
    	}
    }
    
    return retArr;
}

Array.prototype.quickSort = function(compare,left,right)
{
	left = typeof(left) != 'undefined' ? left : 0;
	right = typeof(right) != 'undefined' ? right : this.length-1;
	
	var pivot;
	var l_hold;
	var r_hold;
	
	l_hold = left;
	r_hold = right;
	pivot = this[left];
	
	while (left < right ) {
		while (compare(this[right],pivot) && (left < right)) right--;
		if (left != right) {
			this[left] = this[right];
			left++;
		}
		
		while (compare(pivot,this[left]) && (left < right)) left++;
		if (left != right) {
			this[right] = this[left];
			right--;
		}
	}
	
	this[left] = pivot;
	
	pivot = left;
	left = l_hold
	right = r_hold;

	if (left < pivot) this.quickSort(compare,left, pivot-1);
	if (right > pivot) this.quickSort(compare,pivot+1, right);
}

Array.prototype.inArray = function(p_val)
{
	for (var i = 0, l = this.length; i < l; i++) if (this[i] == p_val) return true;
	return false;
}

Array.prototype.removeItems = function(item)
{
	var i = 0;
	while (i < this.length) {
		if (this[i] == item) {
			this.splice(i, 1);
		} else {
			i++;
		}
	}
	
	return this;
}

String.prototype.capFirst = function()
{
	return this.substr(0,1).toUpperCase()+this.substr(1);
}

String.prototype.trim = function()
{
    return this.replace(/^\s+|\s+$/,"");
}

String.prototype.substrCount = function(needle,offset,length)
{
	var pos = 0, cnt = 0;
	
	if (isNaN(offset)) offset = 0;
	if (isNaN(length)) length = 0;
	
	offset--;
	while((offset = this.indexOf(needle, offset+1)) != -1) {
		if (length > 0 && (offset+needle.length) > length) return false;
		else cnt++;
	}
	
	return cnt;
}

String.prototype.isDate = function()
{
	var txt = this;
	if (txt.length > 10 && txt.substr(10,1) == " ") txt = txt.substr(0,10);
	
	var objDate, mSeconds;  
	
	if (txt.length != 10) return false;  
	
	var year = txt.substr(0,4);  
	var month = txt.substr(5,2);  
	var day = txt.substr(8,2);  
	
	if (txt.substr(4,1) != '/') return false;  
	if (txt.substr(7,1) != '/') return false;  
	
	if (year < 999 || year > 3000) return false;  
	
	mSeconds = (new Date(year,month,day)).getTime();  
	
	objDate = new Date();  
	objDate.setTime(mSeconds);  
	
	if (objDate.getFullYear() != year) return false;  
	if (objDate.getMonth() != month) return false;  
	if (objDate.getDate() != day) return false;  
	
	return mSeconds;  
};

String.prototype.pad = function(len, chr, pos)
{
	if (!len || this.length >= len || !chr) return this;
	var str = new String(this);

	switch (pos) {
		case 'right':
			while (str.length < len) { str += chr };
		break;
		
		default: // left;
			var s = new String();
			while (s.length < (len - str.length)) s += chr;
			str = s.concat(str);
		break;
	}
	return str;
};

String.prototype.substrCount = function(haystack,needle,offset,length)
{
	var pos = 0, cnt = 0;
	
	if (isNaN(offset)) offset = 0;
	if (isNaN(length)) length = 0;
	
	offset--;
	while((offset = haystack.indexOf(needle, offset+1)) != -1)
	{
		if (length > 0 && (offset+needle.length) > length) return false;
		else cnt++;
	}
	
	return cnt;
};

String.prototype.strReplace = function(search,replace,subject)
{
	if (!subject) var subject = this;
	
	var ra = isArray(replace);
    var sa = isArray(subject);
    
	var search = [].concat(search);
    var replace = [].concat(replace);
    var i = (subject = [].concat(subject)).length;
 
    while (j = 0, i--) while (subject[i] = subject[i].split(search[j]).join(ra ? replace[j] || "" : replace[0]), ++j in search){};
     
    return sa ? subject : subject[0];
};

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.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'],
	
	// 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(); },
	z: function() { return "Not Yet Supported"; },
	// Week
	W: function() { return "Not Yet Supported"; },
	// Month
	F: function() { return Date.replaceChars.longMonths[this.getMonth()]; },
	m: function() { return (this.getMonth() < 9 ? '0' : '') + (this.getMonth() + 1); },
	M: function() { return Date.replaceChars.shortMonths[this.getMonth()]; },
	n: function() { return this.getMonth() + 1; },
	t: function() { return "Not Yet Supported"; },
	// Year
	L: function() { return "Not Yet Supported"; },
	o: function() { return "Not Supported"; },
	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'; },
	B: function() { return "Not Yet Supported"; },
	g: function() { return this.getHours() == 0 ? 12 : (this.getHours() > 12 ? this.getHours() - 12 : this.getHours()); },
	G: function() { return this.getHours(); },
	h: function() { return (this.getHours() < 10 || (12 < this.getHours() < 22) ? '0' : '') + (this.getHours() < 10 ? this.getHours() + 1 : this.getHours() - 12); },
	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
	e: function() { return "Not Yet Supported"; },
	I: function() { return "Not Supported"; },
	O: function() { return (this.getTimezoneOffset() < 0 ? '-' : '+') + (this.getTimezoneOffset() / 60 < 10 ? '0' : '') + (this.getTimezoneOffset() / 60) + '00'; },
	T: function() { return "Not Yet Supported"; },
	Z: function() { return this.getTimezoneOffset() * 60; },
	// Full Date/Time
	c: function() { return "Not Yet Supported"; },
	r: function() { return this.toString(); },
	U: function() { return this.getTime() / 1000; }
}

var DatePicker = 
{
	d: new Array(),
	data: new Array(),
	dayArrayShort: new Array('Su', 'Mo', 'Tu', 'We', 'Th', 'Fr', 'Sa'),
	dayArrayMed: new Array('Sun', 'Mon', 'Tue', 'Wed', 'Thu', 'Fri', 'Sat'),
	dayArrayLong: new Array('Sunday', 'Monday', 'Tuesday', 'Wednesday', 'Thursday', 'Friday', 'Saturday'),
	monthArrayShort: new Array('Jan', 'Feb', 'Mar', 'Apr', 'May', 'Jun', 'Jul', 'Aug', 'Sep', 'Oct', 'Nov', 'Dec'),
	monthArrayMed: new Array('Jan', 'Feb', 'Mar', 'Apr', 'May', 'June', 'July', 'Aug', 'Sept', 'Oct', 'Nov', 'Dec'),
	monthArrayLong: new Array('January', 'February', 'March', 'April', 'May', 'June', 'July', 'August', 'September', 'October', 'November', 'December'),
	params: { format:'Y-m-d H:i:s', showTime:true, minuteIncrement:5 },
	
	init: function(event, fieldName, dateString, params)
	{
		event.cancelBubble = true;
		var e = (event.srcElement) ? event.srcElement : event.target;
		
		if (params) for (var i in params) { this.params[i] = params[i]; }
		
		if (!this.data[fieldName]) this.data[fieldName] = (dateString) ? new Date(this.parseDate(dateString)) : new Date();
		this.d[fieldName] = new Date(this.data[fieldName].getTime());
		
		if (document.getElementById("dp_" + fieldName))
		{
			this.exit(fieldName);
		}
		else this.display(fieldName, e);
	},
	
	parseDate: function(dateStr)
	{
		var a = dateStr.split(" ");
		if (!a[0]) return "";
		var d = a[0].split("-");
		if (!d[0]) return "";
		a[0] = new Array(this.monthArrayShort[d[1] - 1], parseInt(d[2]), parseInt(d[0])).join(" ");
		return a.join(" ");
	},
	
	display: function(fieldName, parent)
	{
		var x = parent.offsetLeft;
		var y = parent.offsetTop + parent.offsetHeight;
		
		while (parent.offsetParent)
		{
			parent = parent.offsetParent;
			x += parent.offsetLeft;
			y += parent.offsetTop;
		}
		
		var node = document.createElement("div");
		node.setAttribute("id", "dp_" + fieldName);
		node.setAttribute("class", "dp_div");
		node.setAttribute("className", "dp_div");
		document.body.appendChild(node);
		
		var div = document.getElementById("dp_" + fieldName);
			
		with (div)
		{
			style.position = "absolute";
			style.left = x + "px";
			style.top = y + "px";
			style.zIndex = 1000000;
		}
		
		div.innerHTML = this.build(fieldName);
		
		if (navigator.userAgent.toLowerCase().indexOf("opera") != -1) return;
		
		try
		{
			if (!document.getElementById("dp_iframe_" + fieldName))
			{
				var newNode = document.createElement("iframe");
				newNode.setAttribute("id", "dp_iframe_" + fieldName);
				newNode.setAttribute("src", "javascript:false;");
				newNode.setAttribute("scrolling", "no");
				newNode.setAttribute ("frameborder", "0");
				document.body.appendChild(newNode);
			}
			
			var iframe = document.getElementById("dp_iframe_" + fieldName);

			try
			{
				with (iframe.style)
				{
					position = "absolute";
					width = div.offsetWidth;
					height = div.offsetHeight;
					top = div.style.top;
					left = div.style.left;
					zIndex = div.style.zIndex - 1;
					visibility = div.style.visibility;
					display = div.style.display;
				}
			} 
			catch(e) {}
		}
		catch (ee) {}
	},
	
	build: function(fieldName)
	{
		var d = this.d[fieldName];
		
		var crlf = "\r\n";
		var html = '<table class="dp_table">' + crlf;
		html += '<tbody>' + crlf;
		
		// header
		html += '<tr>' + crlf;
		html += '<td class="dp_btn" onclick="DatePicker.showHelp();" title="Help">?</td>' + crlf;
		html += '<td class="dp_month" colspan="5">' + this.monthArrayLong[d.getMonth()] +  '</td>' + crlf;
		html += '<td class="dp_btn" onclick="DatePicker.exit(\'' + fieldName + '\');" title="Close">x</td>' + crlf;
		html += '</tr>' + crlf;
		
		// next/prev month/year buttons
		html += '<tr>' + crlf;
		html += '<td class="dp_btn" onclick="DatePicker.setYear(event, -1);" title="Previous Year">&laquo;</td>' + crlf;
		html += '<td class="dp_btn" onclick="DatePicker.setMonth(event, -1);" title="Previous Month">&lt;</td>' + crlf;
		html += '<td class="dp_year" colspan="3">' + d.getFullYear() + '</td>' + crlf;
		html += '<td class="dp_btn" onclick="DatePicker.setMonth(event, 1);" title="Next Month">&gt;</td>' + crlf;
		html += '<td class="dp_btn" onclick="DatePicker.setYear(event, 1);" title="Next Year">&raquo;</td>' + crlf;
		html += '</tr>' + crlf;
		
		// spacer
		html += '<tr height="5" />' + crlf;
		
		// days of week
		html += '<tr>' + crlf;
		for (var i = 0; i < this.dayArrayMed.length; i++) {	html += '<td class="dp_wkdy">' + this.dayArrayMed[i] + '</td>' + crlf; }
		html += '</tr>' + crlf;
		
		html += '<tr id="dp_days">' + this.buildMonth(fieldName) + '</tr>' + crlf;
		
		// spacer
		html += '<tr height="5" />' + crlf;
		
		if (this.params.showTime)
		{
			// time
			html += '<tr>' + crlf;
			html += '<td colspan="7">';
			
			// ::hour
			html += '<select class="dp_select" onchange="DatePicker.setHour(event, this.selectedIndex);">' + crlf;
			
			var setVal = d.getHours();
			
			if (setVal > 11) setVal -= 12;
			
			for (var i = 0; i < 12; i++)
			{
				var selected = (setVal == i) ? " selected" : "";
				var txt = (i == 0) ? "12" : i.toString();
				if (txt.length < 2) txt = "0" + txt;
				
				html += '<option class="dp_select" value="' + i + '"' + selected + '>' + txt + '</option>' + crlf;
			}
			html += "</select>&nbsp;<b>:</b>&nbsp;" 
			
			// ::minute
			html += '<select class="dp_select" onchange="DatePicker.setMinute(event, this.options[this.selectedIndex].value);">' + crlf;
			
			var setVal = d.getMinutes();
			var inc = this.params.minuteIncrement;
			if (d.getMinutes() % inc > 0) setVal += (inc - (d.getMinutes() % inc));
			
			for (var i = 0; i < 60; i += inc)
			{
				var selected = (setVal == i) ? " selected" : "";
				var val = (i < 10) ? "0" + i.toString() : i.toString();
				html += '<option class="dp_select"' + selected + ' value="' + parseInt(val) + '">' + val + '</option>' + crlf;
			}
			html += '</select>&nbsp;';
			
			// ::meridian
			html += '<select class="dp_select" onchange="DatePicker.setMeridian(event, this.selectedIndex);">' + crlf;
			
			var meridianOptions = new Array("AM", "PM");
			var setVal = (d.getHours() < 12) ? 0 : 1;
				
			for (var i = 0; i < meridianOptions.length; i++)
			{
				var selected = (i == setVal) ? " selected" : "";
				html += '<option class="dp_select"' + selected + '>' + meridianOptions[i] + '</option>' + crlf;
			}
			html += '</select>';
			
			html += '</td>' + crlf;
			html += '</tr>' + crlf;
		}
		
		html += '</tbody>' + crlf;
		html += '</table>';
		
		return html;
	},
	
	buildMonth: function(fieldName)
	{
		var d = new Date(this.d[fieldName].getTime());
		d.setDate(1);
		
		var cols = 0;
		var html = "";
		
		var m = new Date(d.getTime());
		m.setMonth(m.getMonth() - 1);
		var daysInPrevMonth = 32 - new Date(m.getFullYear(), m.getMonth(), 32).getDate();
		
		for (var i = 0; i < d.getDay(); i++)
		{
			cols++;
			m.setDate(daysInPrevMonth - (d.getDay() - i) + 1);
	  		html += '<td class="dp_day">' + m.getDate() + '</td>';
		}
		
		do {
			cols++;
			var className = this.match(d, this.data[fieldName]) ? "dp_day_on" : "dp_day_off";
			var onClick = ' onclick="DatePicker.setDate(event, \'' + d.getDate() +  '\');DatePicker.exit(\'' + fieldName + '\');"';
			html += '<td class="' + className + '"' + onClick + '>' + d.getDate() + '</td>';
			if (d.getDay() == 6) html += '</tr><tr>';
			d.setDate(d.getDate() + 1);
		}
		while (d.getDate() > 1);
		
		if (cols < 42)
		{
			m = new Date(d.getTime());
			m.setMonth(d.getMonth());
			m.setDate(1);
			
			for (var i = cols; i < 42; i++)
			{
		  		html += '<td class="dp_day">' + m.getDate() + '</td>';
				if (m.getDay() == 6) html += '</tr><tr>';
				m.setDate(m.getDate() + 1);
			}
		}
		
		return html;
	},
	
	match: function(d1, d2)
	{
		return (d1.getFullYear() == d2.getFullYear() && d1.getMonth() == d2.getMonth() && d1.getDate() == d2.getDate());
	},
	
	setYear: function(event, val)
	{
		this.set(event, 'year', val);
	},
	
	setMonth: function(event, val)
	{
		this.set(event, 'month', val);
	},
	
	setDate: function(event, val)
	{
		this.set(event, 'date', val);
	},
	
	setHour: function(event, val)
	{
		this.set(event, 'hour', val);
	},
	
	setMinute: function(event, val)
	{
		this.set(event, 'minute', val);
	},
	
	setMeridian: function(event, val)
	{
		this.set(event, 'meridian', val);
	},
	
	set: function(event, key, val)
	{
		event.cancelBubble = true;
		var e = (event.srcElement) ? event.srcElement : event.target;
		
		var fieldName = this.getFieldName(event);
		var d = this.d[fieldName];
		var save = false;
		
		switch (key.toLowerCase())
		{
			case 'date':
				d.setDate(val);
				save = true;
			break;
			
			case 'month':
				d.setMonth(d.getMonth() + val);
				var arr = this.getElementsByClassName(e.parentNode.parentNode, "dp_month");
				if (arr[0]) arr[0].innerHTML = this.monthArrayLong[d.getMonth()];
				
				if (d.getMonth() == 0 && val > 0) { key = 'year'; val = 0; }
				else if (d.getMonth() == 11 && val < 0) { key = 'year'; val = 0; }
				else break;
			
			case 'year':
				d.setFullYear(d.getFullYear() + val);
				var arr = this.getElementsByClassName(e.parentNode.parentNode, "dp_year");
				if (arr[0]) arr[0].innerHTML = d.getFullYear();
			break;
			
			case 'minute':
				d.setMinutes(val);
				save = true;
			break;
			
			case 'hour':
				var childNodes = e.parentNode.childNodes;
				if (childNodes[childNodes.length - 1].selectedIndex == 1) val += 12; // adjust for meridian
				d.setHours(val);
				save = true;
			break;
			
			case 'meridian':
				if (val == 0 && d.getHours() > 11) d.setHours(d.getHours() - 12);
				else if (val == 1 && d.getHours() < 12) d.setHours(d.getHours() + 12);
				save = true;
			break;
		}
		
		if (save) this.data[fieldName] = new Date(d.getTime());
		
		var div = document.getElementById("dp_" + fieldName);
		div.innerHTML = this.build(fieldName);
	},
	
	getContainer: function(e, className)
	{
		var parent = e.parentNode;
		
		while (parent.nodeName.toLowerCase() != "body")
		{
			if (parent.className == className) break;
			parent = parent.parentNode;
		}
		
		return parent;
	},
	
	getFieldName: function(event)
	{
		event.cancelBubble = true;
		var e = (event.srcElement) ? event.srcElement : event.target;
		var parent = this.getContainer(e, "dp_div");
		return (parent.id) ? parent.id.substr(3) : "";
	},
	
	getElementsByClassName: function(parent, className)
	{
		if (!parent) var parent = document;
		var arr = new Array(); 
		var elements = parent.getElementsByTagName("*");
		
		for (var cls, i = 0; (e = elements[i]); i++)
		{
			if (e.className == className) arr[arr.length] = e;
		}
		return arr;
	},
	
	showHelp: function()
	{
		var crlf = "\r\n";
		var str = "Date Selection:" + crlf;
		str += "- Use the &laquo; and &raquo; buttons to change the year." + crlf;
		str += "- Use the &lt; and &gt; buttons to change the month." + crlf;
		
		var html_entity_decode = function(s)
		{
			var ta = document.createElement("textarea");
  			ta.innerHTML = s.replace(/</g, "&lt;").replace(/>/g, "&gt;");
  			return ta.value;
		};
		
		alert(html_entity_decode(str));
	},
	
	update: function(fieldName)
	{
		var d = this.data[fieldName];
		$(fieldName).value = d.format(this.params.format);
	},
	
	exit: function(fieldName)
	{
		this.update(fieldName);
		
		var div = document.getElementById("dp_" + fieldName);
		if (div) div.parentNode.removeChild(div);
		
		var iframe = document.getElementById("dp_iframe_" + fieldName);
		if (iframe) iframe.parentNode.removeChild(iframe);

	}
};

var TrackingDatePicker = 
{
	d: new Array(),
	data: new Array(),
	dayArrayShort: new Array('Su', 'Mo', 'Tu', 'We', 'Th', 'Fr', 'Sa'),
	dayArrayMed: new Array('Sun', 'Mon', 'Tue', 'Wed', 'Thu', 'Fri', 'Sat'),
	dayArrayLong: new Array('Sunday', 'Monday', 'Tuesday', 'Wednesday', 'Thursday', 'Friday', 'Saturday'),
	monthArrayShort: new Array('Jan', 'Feb', 'Mar', 'Apr', 'May', 'Jun', 'Jul', 'Aug', 'Sep', 'Oct', 'Nov', 'Dec'),
	monthArrayMed: new Array('Jan', 'Feb', 'Mar', 'Apr', 'May', 'June', 'July', 'Aug', 'Sept', 'Oct', 'Nov', 'Dec'),
	monthArrayLong: new Array('January', 'February', 'March', 'April', 'May', 'June', 'July', 'August', 'September', 'October', 'November', 'December'),
	params: { format:'Y-m-d H:i:s', showTime:true, minuteIncrement:5 },
	reporting: new Array(),
	needed: new Array(),
	customer_support_user_id: '',
	
	init: function(e, fieldName, dateString, params, user_id, customer_support_user_id, reporting, needed)
	{
		this.reporting = reporting;
		this.needed = needed;
		this.customer_support_user_id = customer_support_user_id;
		this.user_id = user_id;
		//event.cancelBubble = true;
		//var e = (event.srcElement) ? event.srcElement : event.target;
		
		if (params) for (var i in params) { this.params[i] = params[i]; }
		
		if (!this.data[fieldName]) this.data[fieldName] = (dateString) ? new Date(this.parseDate(dateString)) : new Date();
		this.d[fieldName] = new Date(this.data[fieldName].getTime());

		mysql_date = getRealDate(this.d[fieldName], true);
		
		var today = new Date();
		today.setSeconds(0);
		today.setMinutes(0);
		today.setHours(0);
		var temp = this.d[fieldName];
		temp.setSeconds(0);
		temp.setMinutes(0);
		temp.setHours(0);
		var difference = temp - today;
		var diff_days = Math.round(difference/(1000*60*60*24));
		if(diff_days>0)
		{
			//alert("no dice!");
			$('tracking_right_side').hide();
			$('no_tracking').show();
		}
		else
		{
			$('no_tracking').hide();
			$('tracking_right_side').show();
		}
		
		//load the tracking data via ajax
		App.onSuccess = function(response) {
			responses = response.split('~');
			responses.each(function(e)
			{
				parts = e.split('::');
				if(parts[2]==0)
				{
					$(parts[0]).value = parts[1];
				}
				else
				{
					if(parts[1]==1)
					{
						$(parts[0]+'_yes').checked = true;
					}
					else
					{
						$(parts[0]+'_no').checked = true;
					}
				}
			});
		}
		
		App.request('/cp/TrackData', 'POST', {'do':'get_data', 'data_date':mysql_date, 'user_id':this.user_id, 'customer_support_user_id':this.customer_support_user_id});
		
		$('big_date').innerHTML = this.getBigDate(this.d[fieldName]);
		$('data_date').value = mysql_date;
		
		if (document.getElementById("dp_" + fieldName))
		{
			//this.exit(fieldName);
		}
		else this.display(fieldName, e);
	},
	
	parseDate: function(dateStr)
	{
		var a = dateStr.split(" ");
		if (!a[0]) return "";
		var d = a[0].split("-");
		if (!d[0]) return "";
		a[0] = new Array(this.monthArrayShort[d[1] - 1], parseInt(d[2]), parseInt(d[0])).join(" ");
		return a.join(" ");
	},
	
	display: function(fieldName, parent)
	{
		var x = parent.offsetLeft;
		var y = parent.offsetTop + parent.offsetHeight;
		
		while (parent.offsetParent)
		{
			parent = parent.offsetParent;
			x += parent.offsetLeft;
			y += parent.offsetTop;
		}
		
		//alert(parent.id);
		//var node = document.createElement("input");
		//$('calendar_div').appendChild(node);
		
		var node = document.createElement("div");
		node.setAttribute("id", "dp_" + fieldName);
		node.setAttribute("class", "dp_div");
		node.setAttribute("className", "dp_div");
		$('calendar_div').appendChild(node);
		
		var div = document.getElementById("dp_" + fieldName);
			
//		with (div)
//		{
//			style.border = "1px solid blue";
//			style.position = "absolute";
//			//style.left = x + "px";
//			//style.top = y + "px";
//			//style.zIndex = 999;
//		}
		
		div.innerHTML = this.build(fieldName);
		
		if (navigator.userAgent.toLowerCase().indexOf("opera") != -1) return;
		
		try
		{
//			if (!document.getElementById("dp_iframe_" + fieldName))
//			{
//				var newNode = document.createElement("iframe");
//				newNode.setAttribute("id", "dp_iframe_" + fieldName);
//				newNode.setAttribute("src", "javascript:false;");
//				newNode.setAttribute("scrolling", "no");
//				newNode.setAttribute ("frameborder", "0");
//				document.body.appendChild(newNode);
//			}
//			
//			var iframe = document.getElementById("dp_iframe_" + fieldName);
//
//			try
//			{
//				with (iframe.style)
//				{
//					position = "absolute";
//					width = div.offsetWidth;
//					height = div.offsetHeight;
//					top = div.style.top;
//					left = div.style.left;
//					zIndex = div.style.zIndex - 1;
//					visibility = div.style.visibility;
//					display = div.style.display;
//				}
//			} 
//			catch(e) {}
		}
		catch (ee) {}
	},
	
	build: function(fieldName)
	{
		var d = this.d[fieldName];
		
		var crlf = "\r\n";
		var html = '<table class="dp_table" style="width:300px; font-size:18px;">' + crlf;
		html += '<tbody>' + crlf;
		
		// header
		html += '<tr>' + crlf;
		html += '' + crlf;
		html += '<td class="dp_month" colspan="7" style="padding-left:8px;">' + this.monthArrayLong[d.getMonth()] +  '</td>' + crlf;
		html += '' + crlf;
		html += '</tr>' + crlf;
		
		// next/prev month/year buttons
		html += '<tr>' + crlf;
		html += '<td class="dp_btn" style="border-right:none; width:40px;" onclick="TrackingDatePicker.setYear(event, -1);" title="Previous Year">&laquo;</td>' + crlf;
		html += '<td class="dp_btn" style="width:40px;" onclick="TrackingDatePicker.setMonth(event, -1);" title="Previous Month">&lt;</td>' + crlf;
		html += '<td class="dp_year" colspan="3">' + d.getFullYear() + '</td>' + crlf;
		html += '<td class="dp_btn" style="width:40px;" onclick="TrackingDatePicker.setMonth(event, 1);" title="Next Month">&gt;</td>' + crlf;
		html += '<td class="dp_btn" style="border-left:none; width:40px;" onclick="TrackingDatePicker.setYear(event, 1);" title="Next Year">&raquo;</td>' + crlf;
		html += '</tr>' + crlf;
		
		// spacer
		html += '<tr height="5" />' + crlf;
		
		// days of week
		html += '<tr>' + crlf;
		for (var i = 0; i < this.dayArrayMed.length; i++)
		{
			if(i>0)
				html += '<td class="dp_wkdy" style="border-left:none; width:40px;">' + this.dayArrayMed[i] + '</td>' + crlf;
			else
				html += '<td class="dp_wkdy" style="width:40px;">' + this.dayArrayMed[i] + '</td>' + crlf;
		}
		html += '</tr>' + crlf;
		
		html += '<tr id="dp_days">' + this.buildMonth(fieldName) + '</tr>' + crlf;
		
		// spacer
		html += '<tr height="5" />' + crlf;
		
		if (this.params.showTime)
		{
			// time
			html += '<tr>' + crlf;
			html += '<td colspan="7">';
			
			// ::hour
			html += '<select class="dp_select" onchange="DatePicker.setHour(event, this.selectedIndex);">' + crlf;
			
			var setVal = d.getHours();
			
			if (setVal > 11) setVal -= 12;
			
			for (var i = 0; i < 12; i++)
			{
				var selected = (setVal == i) ? " selected" : "";
				var txt = (i == 0) ? "12" : i.toString();
				if (txt.length < 2) txt = "0" + txt;
				
				html += '<option class="dp_select" value="' + i + '"' + selected + '>' + txt + '</option>' + crlf;
			}
			html += "</select>&nbsp;<b>:</b>&nbsp;" 
			
			// ::minute
			html += '<select class="dp_select" onchange="DatePicker.setMinute(event, this.options[this.selectedIndex].value);">' + crlf;
			
			var setVal = d.getMinutes();
			var inc = this.params.minuteIncrement;
			if (d.getMinutes() % inc > 0) setVal += (inc - (d.getMinutes() % inc));
			
			for (var i = 0; i < 60; i += inc)
			{
				var selected = (setVal == i) ? " selected" : "";
				var val = (i < 10) ? "0" + i.toString() : i.toString();
				html += '<option class="dp_select"' + selected + ' value="' + parseInt(val) + '">' + val + '</option>' + crlf;
			}
			html += '</select>&nbsp;';
			
			// ::meridian
			html += '<select class="dp_select" onchange="DatePicker.setMeridian(event, this.selectedIndex);">' + crlf;
			
			var meridianOptions = new Array("AM", "PM");
			var setVal = (d.getHours() < 12) ? 0 : 1;
				
			for (var i = 0; i < meridianOptions.length; i++)
			{
				var selected = (i == setVal) ? " selected" : "";
				html += '<option class="dp_select"' + selected + '>' + meridianOptions[i] + '</option>' + crlf;
			}
			html += '</select>';
			
			html += '</td>' + crlf;
			html += '</tr>' + crlf;
		}
		
		html += '</tbody>' + crlf;
		html += '</table>';
		
		return html;
	},
	
	buildMonth: function(fieldName)
	{
		var d = new Date(this.d[fieldName].getTime());
		d.setDate(1);
		
		var cols = 0;
		var html = "";
		
		var m = new Date(d.getTime());
		m.setMonth(m.getMonth() - 1);
		var daysInPrevMonth = 32 - new Date(m.getFullYear(), m.getMonth(), 32).getDate();
		
		for (var i = 0; i < d.getDay(); i++)
		{
			cols++;
			m.setDate(daysInPrevMonth - (d.getDay() - i) + 1);
			if(i==0)
				html += '<td class="dp_day" style="border:none; height:30px; border-bottom:1px solid #cccccc; border-left:1px solid #cccccc; border-right:1px solid #cccccc;">' + m.getDate() + '</td>';
			else if(i==d.getDay()-1)
				html += '<td class="dp_day" style="border:none; height:30px; border-bottom:1px solid #cccccc; border-right:1px solid #cccccc;">' + m.getDate() + '</td>';
			else
				html += '<td class="dp_day" style="border:none; height:30px; border-bottom:1px solid #cccccc; border-right:1px solid #cccccc;">' + m.getDate() + '</td>';
		}
		
		do {
			cols++;
			
			var realDate = getRealDate(d);
			if(this.needed.indexOf(realDate)>-1) 
				var backColor = "background-color:#fce1e7;";
			else if(this.reporting.indexOf(realDate)>-1 && d.getTime()!=this.d[fieldName].getTime())
				var backColor = "background-color:#e1fce4;";
			else var backColor="";
			
			var className = this.match(d, this.data[fieldName]) ? "dp_day_on_track" : "dp_day_off_track";
			var leftSide = (d.getDay() == 0) ? " border-left:1px solid #ccc;" : "";
			var borderInfo = this.match(d, this.data[fieldName]) ? " border-right:1px solid #ccc; border-bottom:1px solid #ccc;"+leftSide : "";
			var onClick = ' onclick="TrackingDatePicker.setDate(event, \'' + d.getDate() +  '\'); TrackingDatePicker.trackingDateSelected(\''+d.getDate()+'\', \''+(d.getMonth()+1)+'\', \''+d.getFullYear()+'\');"';
			if(d.getDay() == 0)
				html += '<td class="' + className + '" style="border-top:none; height:30px;'+ borderInfo + backColor +'"' + onClick + '>' + d.getDate() + '</td>';
			else
				html += '<td class="' + className + '" style="border-top:none; border-left:none; height:30px;'+ borderInfo + backColor +'"' + onClick + '>' + d.getDate() + '</td>';
			if (d.getDay() == 6) html += '</tr><tr>';
			d.setDate(d.getDate() + 1);
		}
		while (d.getDate() > 1);
		
		if (cols < 42)
		{
			m = new Date(d.getTime());
			m.setMonth(d.getMonth());
			m.setDate(1);
			
			for (var i = cols; i < 42; i++)
			{
				if(m.getDay() == 0)
					html += '<td class="dp_day" style="border-bottom:1px solid #cccccc; border-right:1px solid #cccccc; border-left:1px solid #cccccc; height:30px;">' + m.getDate() + '</td>';
				else
					html += '<td class="dp_day" style="border-bottom:1px solid #cccccc; border-right:1px solid #cccccc; height:30px;">' + m.getDate() + '</td>';
				if (m.getDay() == 6) html += '</tr><tr>';
				m.setDate(m.getDate() + 1);
			}
		}
		
		return html;
	},
	
	match: function(d1, d2)
	{
		return (d1.getFullYear() == d2.getFullYear() && d1.getMonth() == d2.getMonth() && d1.getDate() == d2.getDate());
	},
	
	setYear: function(event, val)
	{
		this.set(event, 'year', val);
	},
	
	setMonth: function(event, val)
	{
		this.set(event, 'month', val);
	},
	
	setDate: function(event, val)
	{
		this.set(event, 'date', val);
	},
	
	setHour: function(event, val)
	{
		this.set(event, 'hour', val);
	},
	
	setMinute: function(event, val)
	{
		this.set(event, 'minute', val);
	},
	
	setMeridian: function(event, val)
	{
		this.set(event, 'meridian', val);
	},
	
	set: function(event, key, val)
	{
		event.cancelBubble = true;
		var e = (event.srcElement) ? event.srcElement : event.target;
		
		var fieldName = this.getFieldName(event);
		var d = this.d[fieldName];
		var save = false;
		
		switch (key.toLowerCase())
		{
			case 'date':
				d.setDate(val);
				save = true;
			break;
			
			case 'month':
				d.setMonth(d.getMonth() + val);
				var arr = this.getElementsByClassName(e.parentNode.parentNode, "dp_month");
				if (arr[0]) arr[0].innerHTML = this.monthArrayLong[d.getMonth()];
				
				if (d.getMonth() == 0 && val > 0) { key = 'year'; val = 0; }
				else if (d.getMonth() == 11 && val < 0) { key = 'year'; val = 0; }
				else break;
			
			case 'year':
				d.setFullYear(d.getFullYear() + val);
				var arr = this.getElementsByClassName(e.parentNode.parentNode, "dp_year");
				if (arr[0]) arr[0].innerHTML = d.getFullYear();
			break;
			
			case 'minute':
				d.setMinutes(val);
				save = true;
			break;
			
			case 'hour':
				var childNodes = e.parentNode.childNodes;
				if (childNodes[childNodes.length - 1].selectedIndex == 1) val += 12; // adjust for meridian
				d.setHours(val);
				save = true;
			break;
			
			case 'meridian':
				if (val == 0 && d.getHours() > 11) d.setHours(d.getHours() - 12);
				else if (val == 1 && d.getHours() < 12) d.setHours(d.getHours() + 12);
				save = true;
			break;
		}
		
		if (save) this.data[fieldName] = new Date(d.getTime());
		
		var div = document.getElementById("dp_" + fieldName);
		div.innerHTML = this.build(fieldName);
	},
	
	setNextDay: function(day, month, year)
	{
		var fieldName = 'tracking';
		var d = this.d[fieldName];
		var save = false;
		
		d.setDate(day);
		d.setMonth(month);
		d.setFullYear(year);
		save = true;

		if (save) this.data[fieldName] = new Date(d.getTime());
			
		var div = document.getElementById("dp_" + fieldName);
		div.innerHTML = this.build(fieldName);
		
	},
	
	getContainer: function(e, className)
	{
		var parent = e.parentNode;
		
		while (parent.nodeName.toLowerCase() != "body")
		{
			if (parent.className == className) break;
			parent = parent.parentNode;
		}
		
		return parent;
	},
	
	getFieldName: function(event)
	{
		event.cancelBubble = true;
		var e = (event.srcElement) ? event.srcElement : event.target;
		var parent = this.getContainer(e, "dp_div");
		return (parent.id) ? parent.id.substr(3) : "";
	},
	
	getElementsByClassName: function(parent, className)
	{
		if (!parent) var parent = document;
		var arr = new Array(); 
		var elements = parent.getElementsByTagName("*");
		
		for (var cls, i = 0; (e = elements[i]); i++)
		{
			if (e.className == className) arr[arr.length] = e;
		}
		return arr;
	},
	
	showHelp: function()
	{
		var crlf = "\r\n";
		var str = "Date Selection:" + crlf;
		str += "- Use the &laquo; and &raquo; buttons to change the year." + crlf;
		str += "- Use the &lt; and &gt; buttons to change the month." + crlf;
		
		var html_entity_decode = function(s)
		{
			var ta = document.createElement("textarea");
  			ta.innerHTML = s.replace(/</g, "&lt;").replace(/>/g, "&gt;");
  			return ta.value;
		};
		
		alert(html_entity_decode(str));
	},
	
	update: function(fieldName)
	{
		var d = this.data[fieldName];
		$(fieldName).value = d.format(this.params.format);
	},
	
	exit: function(fieldName)
	{
		this.update(fieldName);
		
		var div = document.getElementById("dp_" + fieldName);
		if (div) div.parentNode.removeChild(div);
		
		var iframe = document.getElementById("dp_iframe_" + fieldName);
		if (iframe) iframe.parentNode.removeChild(iframe);

	},
	
	getBigDate: function(d)
	{
		return this.dayArrayLong[d.getDay()] + ", " + this.monthArrayLong[d.getMonth()] + " " + d.getDate() + ", " + d.getFullYear();
	},
	
	trackingDateSelected: function(tracking_day, tracking_month, tracking_year)
	{
		mysql_date = getRealDate(new Date(tracking_year, tracking_month-1, tracking_day), true);
		
		//clear the tracking fields
		$$('.tracking_inputs').each(function(e)
		{
			if(e.type=="radio")
			{
				e.checked = false;
			}
			else
			{
				e.value='';
			}
		});
		
		var new_date = new Date(tracking_year, tracking_month-1, tracking_day);
		var today = new Date();
		today.setSeconds(0);
		today.setMinutes(0);
		today.setHours(0);
		var difference = new_date - today;
		var diff_days = Math.round(difference/(1000*60*60*24));
		if(diff_days>0)
		{
			//alert("no dice!");
			$('tracking_right_side').hide();
			$('no_tracking').show();
		}
		else
		{
			$('no_tracking').hide();
			$('tracking_right_side').show();
		}
		
		//load the tracking data via ajax
		App.onSuccess = function(response) {
			responses = response.split('~');
			responses.each(function(e)
			{
				parts = e.split('::');
				//if($(parts[0]))
				if(parts[2]==0)
				{
					if($(parts[0]))
						$(parts[0]).value = parts[1];
				}
				else
				{
					if(parts[1]==1)
					{
						$(parts[0]+'_yes').checked = true;
					}
					else
					{
						$(parts[0]+'_no').checked = true;
					}
				}
			});
		}
		
		App.request('/cp/TrackData', 'POST', {'do':'get_data', 'data_date':mysql_date, 'user_id':this.user_id, 'customer_support_user_id':this.customer_support_user_id});
		
		$('big_date').innerHTML = this.getBigDate(new Date(tracking_year, tracking_month-1, tracking_day));
		$('data_date').value = mysql_date;
	}
	
};

function getRoundData(comp_id, round, customer_support_user_id, user_id)
{
	//clear the tracking fields
	$$('.tracking_inputs').each(function(e)
	{
		if(e.type=="radio")
		{
			e.checked = false;
		}
		else
		{
			e.value='';
		}
	});

	//load the tracking data via ajax
	App.onSuccess = function(response) {
		responses = response.split('~');
		responses.each(function(e)
		{
			parts = e.split('::');
			if($(parts[0]=="initial"))
			{
				$('initial_weight_input').value = parts[1];
			}
			else
			{
				if(parts[2]==0)
				{
					$(parts[0]).value = parts[1];
				}
				else
				{
					if(parts[1]==1)
					{
						$(parts[0]+'_yes').checked = true;
					}
					else
					{
						$(parts[0]+'_no').checked = true;
					}
				}
			}
		});
	}
	
	App.request('/cp/TrackData', 'POST', {'do':'get_round_data', 'comp_id':comp_id, 'round':round, 'customer_support_user_id':customer_support_user_id, 'user_id':user_id});
	
}

var GoalDatePicker = 
{
	d: new Array(),
	data: new Array(),
	dayArrayShort: new Array('Su', 'Mo', 'Tu', 'We', 'Th', 'Fr', 'Sa'),
	dayArrayMed: new Array('Sun', 'Mon', 'Tue', 'Wed', 'Thu', 'Fri', 'Sat'),
	dayArrayLong: new Array('Sunday', 'Monday', 'Tuesday', 'Wednesday', 'Thursday', 'Friday', 'Saturday'),
	monthArrayShort: new Array('Jan', 'Feb', 'Mar', 'Apr', 'May', 'Jun', 'Jul', 'Aug', 'Sep', 'Oct', 'Nov', 'Dec'),
	monthArrayMed: new Array('Jan', 'Feb', 'Mar', 'Apr', 'May', 'June', 'July', 'Aug', 'Sept', 'Oct', 'Nov', 'Dec'),
	monthArrayLong: new Array('January', 'February', 'March', 'April', 'May', 'June', 'July', 'August', 'September', 'October', 'November', 'December'),
	params: { format:'Y-m-d H:i:s', showTime:true, minuteIncrement:5 },
	reporting: new Array(),
	needed: new Array(),
	customer_support_user_id: '',
	
	init: function(e, fieldName, dateString, params, user_id, customer_support_user_id, reporting, needed)
	{
		this.reporting = reporting;
		this.needed = needed;
		this.customer_support_user_id = customer_support_user_id;
		this.user_id = user_id;
		//event.cancelBubble = true;
		//var e = (event.srcElement) ? event.srcElement : event.target;
		
		if (params) for (var i in params) { this.params[i] = params[i]; }
		
		if (!this.data[fieldName]) this.data[fieldName] = (dateString) ? new Date(this.parseDate(dateString)) : new Date();
		this.d[fieldName] = new Date(this.data[fieldName].getTime());

		mysql_date = getRealDate(this.d[fieldName], true);
		
		var today = new Date();
		today.setSeconds(0);
		today.setMinutes(0);
		today.setHours(0);
		var temp = this.d[fieldName];
		temp.setSeconds(0);
		temp.setMinutes(0);
		temp.setHours(0);
		var difference = temp - today;
		var diff_days = Math.round(difference/(1000*60*60*24));
		if(diff_days<0)
		{
			//alert("no dice!");
			$('tracking_right_side').hide();
			$('no_tracking').show();
		}
		else
		{
			$('no_tracking').hide();
			$('tracking_right_side').show();
		}
		
		//load the goal data via ajax
		App.onSuccess = function(response) {
			responses = response.split('~');
			responses.each(function(e)
			{
				parts = e.split('::');
				if(parts[2]==0)
				{
					$(parts[0]).value = parts[1];
				}
				else
				{
					if(parts[1]==1)
					{
						$(parts[0]+'_yes').checked = true;
					}
					else
					{
						$(parts[0]+'_no').checked = true;
					}
				}
			});
		}
		
		App.request('/cp/TrackGoals', 'POST', {'do':'get_data', 'data_date':mysql_date, 'user_id':this.user_id, 'customer_support_user_id':this.customer_support_user_id});
		
		$('big_date').innerHTML = this.getBigDate(this.d[fieldName]);
		$('data_date').value = mysql_date;
		
		if (document.getElementById("dp_" + fieldName))
		{
			//this.exit(fieldName);
		}
		else this.display(fieldName, e);
	},
	
	parseDate: function(dateStr)
	{
		var a = dateStr.split(" ");
		if (!a[0]) return "";
		var d = a[0].split("-");
		if (!d[0]) return "";
		a[0] = new Array(this.monthArrayShort[d[1] - 1], parseInt(d[2]), parseInt(d[0])).join(" ");
		return a.join(" ");
	},
	
	display: function(fieldName, parent)
	{
		var x = parent.offsetLeft;
		var y = parent.offsetTop + parent.offsetHeight;
		
		while (parent.offsetParent)
		{
			parent = parent.offsetParent;
			x += parent.offsetLeft;
			y += parent.offsetTop;
		}
		
		//alert(parent.id);
		//var node = document.createElement("input");
		//$('calendar_div').appendChild(node);
		
		var node = document.createElement("div");
		node.setAttribute("id", "dp_" + fieldName);
		node.setAttribute("class", "dp_div");
		node.setAttribute("className", "dp_div");
		$('calendar_div').appendChild(node);
		
		var div = document.getElementById("dp_" + fieldName);
			
//		with (div)
//		{
//			style.border = "1px solid blue";
//			style.position = "absolute";
//			//style.left = x + "px";
//			//style.top = y + "px";
//			//style.zIndex = 999;
//		}
		
		div.innerHTML = this.build(fieldName);
		
		if (navigator.userAgent.toLowerCase().indexOf("opera") != -1) return;
		
		try
		{
//			if (!document.getElementById("dp_iframe_" + fieldName))
//			{
//				var newNode = document.createElement("iframe");
//				newNode.setAttribute("id", "dp_iframe_" + fieldName);
//				newNode.setAttribute("src", "javascript:false;");
//				newNode.setAttribute("scrolling", "no");
//				newNode.setAttribute ("frameborder", "0");
//				document.body.appendChild(newNode);
//			}
//			
//			var iframe = document.getElementById("dp_iframe_" + fieldName);
//
//			try
//			{
//				with (iframe.style)
//				{
//					position = "absolute";
//					width = div.offsetWidth;
//					height = div.offsetHeight;
//					top = div.style.top;
//					left = div.style.left;
//					zIndex = div.style.zIndex - 1;
//					visibility = div.style.visibility;
//					display = div.style.display;
//				}
//			} 
//			catch(e) {}
		}
		catch (ee) {}
	},
	
	build: function(fieldName)
	{
		var d = this.d[fieldName];
		
		var crlf = "\r\n";
		var html = '<table class="dp_table" style="width:300px; font-size:18px;">' + crlf;
		html += '<tbody>' + crlf;
		
		// header
		html += '<tr>' + crlf;
		html += '' + crlf;
		html += '<td class="dp_month" colspan="7" style="padding-left:8px;">' + this.monthArrayLong[d.getMonth()] +  '</td>' + crlf;
		html += '' + crlf;
		html += '</tr>' + crlf;
		
		// next/prev month/year buttons
		html += '<tr>' + crlf;
		html += '<td class="dp_btn" style="border-right:none; width:40px;" onclick="GoalDatePicker.setYear(event, -1);" title="Previous Year">&laquo;</td>' + crlf;
		html += '<td class="dp_btn" style="width:40px;" onclick="GoalDatePicker.setMonth(event, -1);" title="Previous Month">&lt;</td>' + crlf;
		html += '<td class="dp_year" colspan="3">' + d.getFullYear() + '</td>' + crlf;
		html += '<td class="dp_btn" style="width:40px;" onclick="GoalDatePicker.setMonth(event, 1);" title="Next Month">&gt;</td>' + crlf;
		html += '<td class="dp_btn" style="border-left:none; width:40px;" onclick="GoalDatePicker.setYear(event, 1);" title="Next Year">&raquo;</td>' + crlf;
		html += '</tr>' + crlf;
		
		// spacer
		html += '<tr height="5" />' + crlf;
		
		// days of week
		html += '<tr>' + crlf;
		for (var i = 0; i < this.dayArrayMed.length; i++)
		{
			if(i>0)
				html += '<td class="dp_wkdy" style="border-left:none; width:40px;">' + this.dayArrayMed[i] + '</td>' + crlf;
			else
				html += '<td class="dp_wkdy" style="width:40px;">' + this.dayArrayMed[i] + '</td>' + crlf;
		}
		html += '</tr>' + crlf;
		
		html += '<tr id="dp_days">' + this.buildMonth(fieldName) + '</tr>' + crlf;
		
		// spacer
		html += '<tr height="5" />' + crlf;
		
		if (this.params.showTime)
		{
			// time
			html += '<tr>' + crlf;
			html += '<td colspan="7">';
			
			// ::hour
			html += '<select class="dp_select" onchange="DatePicker.setHour(event, this.selectedIndex);">' + crlf;
			
			var setVal = d.getHours();
			
			if (setVal > 11) setVal -= 12;
			
			for (var i = 0; i < 12; i++)
			{
				var selected = (setVal == i) ? " selected" : "";
				var txt = (i == 0) ? "12" : i.toString();
				if (txt.length < 2) txt = "0" + txt;
				
				html += '<option class="dp_select" value="' + i + '"' + selected + '>' + txt + '</option>' + crlf;
			}
			html += "</select>&nbsp;<b>:</b>&nbsp;" 
			
			// ::minute
			html += '<select class="dp_select" onchange="DatePicker.setMinute(event, this.options[this.selectedIndex].value);">' + crlf;
			
			var setVal = d.getMinutes();
			var inc = this.params.minuteIncrement;
			if (d.getMinutes() % inc > 0) setVal += (inc - (d.getMinutes() % inc));
			
			for (var i = 0; i < 60; i += inc)
			{
				var selected = (setVal == i) ? " selected" : "";
				var val = (i < 10) ? "0" + i.toString() : i.toString();
				html += '<option class="dp_select"' + selected + ' value="' + parseInt(val) + '">' + val + '</option>' + crlf;
			}
			html += '</select>&nbsp;';
			
			// ::meridian
			html += '<select class="dp_select" onchange="DatePicker.setMeridian(event, this.selectedIndex);">' + crlf;
			
			var meridianOptions = new Array("AM", "PM");
			var setVal = (d.getHours() < 12) ? 0 : 1;
				
			for (var i = 0; i < meridianOptions.length; i++)
			{
				var selected = (i == setVal) ? " selected" : "";
				html += '<option class="dp_select"' + selected + '>' + meridianOptions[i] + '</option>' + crlf;
			}
			html += '</select>';
			
			html += '</td>' + crlf;
			html += '</tr>' + crlf;
		}
		
		html += '</tbody>' + crlf;
		html += '</table>';
		
		return html;
	},
	
	buildMonth: function(fieldName)
	{
		var d = new Date(this.d[fieldName].getTime());
		d.setDate(1);
		
		var cols = 0;
		var html = "";
		
		var m = new Date(d.getTime());
		m.setMonth(m.getMonth() - 1);
		var daysInPrevMonth = 32 - new Date(m.getFullYear(), m.getMonth(), 32).getDate();
		
		for (var i = 0; i < d.getDay(); i++)
		{
			cols++;
			m.setDate(daysInPrevMonth - (d.getDay() - i) + 1);
			if(i==0)
				html += '<td class="dp_day" style="border:none; height:30px; border-bottom:1px solid #cccccc; border-left:1px solid #cccccc; border-right:1px solid #cccccc;">' + m.getDate() + '</td>';
			else if(i==d.getDay()-1)
				html += '<td class="dp_day" style="border:none; height:30px; border-bottom:1px solid #cccccc; border-right:1px solid #cccccc;">' + m.getDate() + '</td>';
			else
				html += '<td class="dp_day" style="border:none; height:30px; border-bottom:1px solid #cccccc; border-right:1px solid #cccccc;">' + m.getDate() + '</td>';
		}
		
		do {
			cols++;
			
			var realDate = getRealDate(d);
			if(this.needed.indexOf(realDate)>-1) 
				var backColor = "background-color:#fce1e7;";
			else if(this.reporting.indexOf(realDate)>-1)
				var backColor = "background-color:#e1fce4;";
			else var backColor="";
			
			var className = this.match(d, this.data[fieldName]) ? "dp_day_on_track" : "dp_day_off_track";
			var leftSide = (d.getDay() == 0) ? " border-left:1px solid #ccc;" : "";
			var borderInfo = this.match(d, this.data[fieldName]) ? " border-right:1px solid #ccc; border-bottom:1px solid #ccc;"+leftSide : "";
			var onClick = ' onclick="GoalDatePicker.setDate(event, \'' + d.getDate() +  '\'); GoalDatePicker.trackingDateSelected(\''+d.getDate()+'\', \''+(d.getMonth()+1)+'\', \''+d.getFullYear()+'\');"';
			if(d.getDay() == 0)
				html += '<td class="' + className + '" style="border-top:none; height:30px;'+ borderInfo + backColor +'"' + onClick + '>' + d.getDate() + '</td>';
			else
				html += '<td class="' + className + '" style="border-top:none; border-left:none; height:30px;'+ borderInfo + backColor +'"' + onClick + '>' + d.getDate() + '</td>';
			if (d.getDay() == 6) html += '</tr><tr>';
			d.setDate(d.getDate() + 1);
		}
		while (d.getDate() > 1);
		
		if (cols < 42)
		{
			m = new Date(d.getTime());
			m.setMonth(d.getMonth());
			m.setDate(1);
			
			for (var i = cols; i < 42; i++)
			{
				if(m.getDay() == 0)
					html += '<td class="dp_day" style="border-bottom:1px solid #cccccc; border-right:1px solid #cccccc; border-left:1px solid #cccccc; height:30px;">' + m.getDate() + '</td>';
				else
					html += '<td class="dp_day" style="border-bottom:1px solid #cccccc; border-right:1px solid #cccccc; height:30px;">' + m.getDate() + '</td>';
				if (m.getDay() == 6) html += '</tr><tr>';
				m.setDate(m.getDate() + 1);
			}
		}
		
		return html;
	},
	
	match: function(d1, d2)
	{
		return (d1.getFullYear() == d2.getFullYear() && d1.getMonth() == d2.getMonth() && d1.getDate() == d2.getDate());
	},
	
	setYear: function(event, val)
	{
		this.set(event, 'year', val);
	},
	
	setMonth: function(event, val)
	{
		this.set(event, 'month', val);
	},
	
	setDate: function(event, val)
	{
		this.set(event, 'date', val);
	},
	
	setHour: function(event, val)
	{
		this.set(event, 'hour', val);
	},
	
	setMinute: function(event, val)
	{
		this.set(event, 'minute', val);
	},
	
	setMeridian: function(event, val)
	{
		this.set(event, 'meridian', val);
	},
	
	set: function(event, key, val)
	{
		event.cancelBubble = true;
		var e = (event.srcElement) ? event.srcElement : event.target;
		
		var fieldName = this.getFieldName(event);
		var d = this.d[fieldName];
		var save = false;
		
		switch (key.toLowerCase())
		{
			case 'date':
				d.setDate(val);
				save = true;
			break;
			
			case 'month':
				d.setMonth(d.getMonth() + val);
				var arr = this.getElementsByClassName(e.parentNode.parentNode, "dp_month");
				if (arr[0]) arr[0].innerHTML = this.monthArrayLong[d.getMonth()];
				
				if (d.getMonth() == 0 && val > 0) { key = 'year'; val = 0; }
				else if (d.getMonth() == 11 && val < 0) { key = 'year'; val = 0; }
				else break;
			
			case 'year':
				d.setFullYear(d.getFullYear() + val);
				var arr = this.getElementsByClassName(e.parentNode.parentNode, "dp_year");
				if (arr[0]) arr[0].innerHTML = d.getFullYear();
			break;
			
			case 'minute':
				d.setMinutes(val);
				save = true;
			break;
			
			case 'hour':
				var childNodes = e.parentNode.childNodes;
				if (childNodes[childNodes.length - 1].selectedIndex == 1) val += 12; // adjust for meridian
				d.setHours(val);
				save = true;
			break;
			
			case 'meridian':
				if (val == 0 && d.getHours() > 11) d.setHours(d.getHours() - 12);
				else if (val == 1 && d.getHours() < 12) d.setHours(d.getHours() + 12);
				save = true;
			break;
		}
		
		if (save) this.data[fieldName] = new Date(d.getTime());
		
		var div = document.getElementById("dp_" + fieldName);
		div.innerHTML = this.build(fieldName);
	},
	
	setNextDay: function(day, month, year)
	{
		var fieldName = 'tracking';
		var d = this.d[fieldName];
		var save = false;
		
		d.setDate(day);
		d.setMonth(month);
		d.setFullYear(year);
		save = true;

		if (save) this.data[fieldName] = new Date(d.getTime());
			
		var div = document.getElementById("dp_" + fieldName);
		div.innerHTML = this.build(fieldName);
		
	},
	
	getContainer: function(e, className)
	{
		var parent = e.parentNode;
		
		while (parent.nodeName.toLowerCase() != "body")
		{
			if (parent.className == className) break;
			parent = parent.parentNode;
		}
		
		return parent;
	},
	
	getFieldName: function(event)
	{
		event.cancelBubble = true;
		var e = (event.srcElement) ? event.srcElement : event.target;
		var parent = this.getContainer(e, "dp_div");
		return (parent.id) ? parent.id.substr(3) : "";
	},
	
	getElementsByClassName: function(parent, className)
	{
		if (!parent) var parent = document;
		var arr = new Array(); 
		var elements = parent.getElementsByTagName("*");
		
		for (var cls, i = 0; (e = elements[i]); i++)
		{
			if (e.className == className) arr[arr.length] = e;
		}
		return arr;
	},
	
	showHelp: function()
	{
		var crlf = "\r\n";
		var str = "Date Selection:" + crlf;
		str += "- Use the &laquo; and &raquo; buttons to change the year." + crlf;
		str += "- Use the &lt; and &gt; buttons to change the month." + crlf;
		
		var html_entity_decode = function(s)
		{
			var ta = document.createElement("textarea");
  			ta.innerHTML = s.replace(/</g, "&lt;").replace(/>/g, "&gt;");
  			return ta.value;
		};
		
		alert(html_entity_decode(str));
	},
	
	update: function(fieldName)
	{
		var d = this.data[fieldName];
		$(fieldName).value = d.format(this.params.format);
	},
	
	exit: function(fieldName)
	{
		this.update(fieldName);
		
		var div = document.getElementById("dp_" + fieldName);
		if (div) div.parentNode.removeChild(div);
		
		var iframe = document.getElementById("dp_iframe_" + fieldName);
		if (iframe) iframe.parentNode.removeChild(iframe);

	},
	
	getBigDate: function(d)
	{
		return this.dayArrayLong[d.getDay()] + ", " + this.monthArrayLong[d.getMonth()] + " " + d.getDate() + ", " + d.getFullYear();
	},
	
	trackingDateSelected: function(tracking_day, tracking_month, tracking_year)
	{
		mysql_date = getRealDate(new Date(tracking_year, tracking_month-1, tracking_day), true);
		
		//clear the tracking fields
		$$('.tracking_inputs').each(function(e)
		{
			if(e.type=="radio")
			{
				e.checked = false;
			}
			else
			{
				e.value='';
			}
		});
		
		var new_date = new Date(tracking_year, tracking_month-1, tracking_day);
		var today = new Date();
		today.setSeconds(0);
		today.setMinutes(0);
		today.setHours(0);
		var difference = new_date - today;
		var diff_days = Math.round(difference/(1000*60*60*24));
		if(diff_days<0)
		{
			//alert("no dice!");
			$('tracking_right_side').hide();
			$('no_tracking').show();
		}
		else
		{
			$('no_tracking').hide();
			$('tracking_right_side').show();
		}
		
		//load the tracking data via ajax
		App.onSuccess = function(response) {
			responses = response.split('~');
			responses.each(function(e)
			{
				parts = e.split('::');
				//if($(parts[0]))
				if(parts[2]==0)
				{
					$(parts[0]).value = parts[1];
				}
				else
				{
					if(parts[1]==1)
					{
						$(parts[0]+'_yes').checked = true;
					}
					else
					{
						$(parts[0]+'_no').checked = true;
					}
				}
			});
		}
		
		App.request('/cp/TrackGoals', 'POST', {'do':'get_data', 'data_date':mysql_date, 'user_id':this.user_id, 'customer_support_user_id':this.customer_support_user_id});
		
		$('big_date').innerHTML = this.getBigDate(new Date(tracking_year, tracking_month-1, tracking_day));
		$('data_date').value = mysql_date;
	}
	
};

function getRoundGoals(comp_id, round, customer_support_user_id, user_id)
{
	//clear the tracking fields
	$$('.tracking_inputs').each(function(e)
	{
		if(e.type=="radio")
		{
			e.checked = false;
		}
		else
		{
			e.value='';
		}
	});

	//load the tracking data via ajax
	App.onSuccess = function(response) {
		responses = response.split('~');
		responses.each(function(e)
		{
			parts = e.split('::');
			//if($(parts[0]))
			if(parts[2]==0)
			{
				$(parts[0]).value = parts[1];
			}
			else
			{
				if(parts[1]==1)
				{
					$(parts[0]+'_yes').checked = true;
				}
				else
				{
					$(parts[0]+'_no').checked = true;
				}
			}
		});
	}
	
	App.request('/cp/TrackGoals', 'POST', {'do':'get_round_data', 'comp_id':comp_id, 'round':round, 'customer_support_user_id':customer_support_user_id, 'user_id':user_id});
	
}

function getMeasureUnits(item_id)
{
	App.request('/cp/TrackData', 'POST', {'do':'get_measure_units', 'item_id':item_id}, 'measure_units');
}

function addNewCategory(item_id, unit_id)
{
	if(item_id==0) return;
	
	//check that it has not already been added
	var already = false;
	$$('.tracking_inputs').each(function(e)
	{
		parts = e.id.split('_');
		if(parts[1]==item_id && parts[2]==unit_id)
		{
			already = true;
		}
	});
	
	if(already) return;
	
	//use ajax to get the measurement word, unit word and the input
	App.onSuccess = function(response)
	{
		var parts = response.split('~~');
		
		var table = $('tracking_categories_table');
        var rowCount = table.rows.length;
        var row = table.insertRow(rowCount);

        var cell1 = row.insertCell(0);
        cell1.innerHTML = parts[2];
        cell1.setAttribute("style", "text-align:right; font-weight:bold;");

        var cell2 = row.insertCell(1);
        if(parts[4]=='1')
        {
        	cell2.innerHTML = '<input type="radio" class="tracking_inputs" name="data_value['+parts[0]+'|'+parts[1]+']" id="measurement_'+parts[0]+'_'+parts[1]+'_yes" value="bool1" style="font-size:16px;"/><label for="measurement_'+parts[0]+'_'+parts[1]+'_yes">Yes</label> <input type="radio" class="tracking_inputs" name="data_value['+parts[0]+'|'+parts[1]+']" id="measurement_'+parts[0]+'_'+parts[1]+'_no" value="bool0" style="font-size:16px;"/><label for="measurement_'+parts[0]+'_'+parts[1]+'_no">No</label>';
        }
        else
        {
        	cell2.innerHTML = '<input type="text" class="tracking_inputs" size="8" name="data_value['+parts[0]+'|'+parts[1]+']" id="measurement_'+parts[0]+'_'+parts[1]+'" style="font-size:16px;"/>';
        }

        var cell3 = row.insertCell(2);
        cell3.innerHTML = parts[3];
        cell3.setAttribute("style", "text-align:left;");
		
	};
	
	App.request('/cp/TrackData', 'POST', {'do':'get_new_category', 'item_id':item_id, 'unit_id':unit_id});
}

function getRealDate(d, mysql)
{
	if(mysql == undefined)
		mysql = false;
	
	var month = d.getMonth()+1;
	if(month.toString().length==1) month = "x0" + month; else month = "x" + month;
	var year = d.getFullYear();
	var day = d.getDate();
	if(day.toString().length==1) day = "x0" + day; else day = "x" + day;
	
	if(mysql)
	{
		var fdate = year + "-" + month + "-" + day;
	}
	else
	{	
		var fdate = year + month + day;
	}
	return fdate.replace(/x/g, '');
}

var Forum = 
{
	load: function(forum_id, page)
	{
		var params = { 'forum_id':forum_id };
		if (page) params.page = page;
		
		$('forum').update($('ajax_loader').innerHTML);
		
		App.load('/cp/ForumComponent/', 'forum', params);
	}
};

var ForumTopic = 
{
	loadPosts: function(forum_id, topic_id)
	{
		if ($('topic_posts_' + topic_id))
		{
			var e = $('topic_posts_' + topic_id);
			
			if (e.innerHTML.blank())
			{
				e.show();
				
				var params = { 'do':'get_posts', 'forum_id':forum_id, 'topic_id':topic_id };
				
				App.load('/cp/ForumComponent/', 'topic_posts_' + topic_id, params);
			}
			else e.toggle();
		}
	},
	
	save: function(event, forum_id)
	{
		App.send('create_topic_form', 'forum');
	}
};

var ForumPost =
{
	toggle: function(event)
	{
		var e = Event.element(event);
		e.up('li').down('.forum_post_abrv').toggle();
		e.up('li').down('.forum_post_full').toggle();
	},
	
	showReply: function(event)
	{
		var e = Event.element(event);
		e.up(1).down('.forum_post_reply').show();
	},
	
	discardReply: function(event)
	{
		var e = Event.element(event);
		e.up('form').reset();
		e.up(3).down('.forum_post_reply').hide();
	},
	
	save: function(event, forum_id, topic_id, post_id)
	{
		App.onSuccess = function()
		{
			$('topic_posts_' + topic_id).update(' ');
			ForumTopic.loadPosts(forum_id, topic_id);
		};
		
		App.send('save_post_form_' + post_id);
	}
};

var DHTMLWin = 
{
	load: function(event, template, params, parent)
	{
		if ($('dhtml_win')) $('dhtml_win').remove();
		if (!params) params = {};
		if (!parent) parent = document.body;
	
		var e = Event.element(event);
		
		var tpl = new Template($(template).innerHTML);
		var div = new Element('div', { id:'dhtml_win' }).update(tpl.evaluate(params));
		div.style.display = 'none';
		parent.appendChild(div);
		
		if (Element.viewportOffset(e).top > div.getHeight()) var offset_top = 0 - div.getHeight();
		else if ((document.viewport.getHeight() - Element.viewportOffset(e).top)  > (div.getHeight() + e.getHeight())) var offset_top = e.getHeight();
		
		if ((document.viewport.getWidth() - Element.viewportOffset(e).left)  > div.getWidth()) var offset_left = 0;
		else var offset_left = 2 - (div.getWidth() - e.getWidth());
		
		offset_left += e.getWidth();
		
		Element.absolutize(div);
		try { Element.clonePosition(div, e, {offsetLeft:offset_left, offsetTop:offset_top}); }
		catch (ee) { Element.clonePosition(div, e, {offsetLeft:offset_left, offsetTop:offset_top}); }
		
		div.style.zIndex = 999;
		div.show();
		
		if (params.url)
		{
			if (!params.params) params.params = {};
			params.params.AJAX = '1';
			div.down('.dhtml_win_content').id = 'dhtml_win_content';
			
			App.load(params.url, $('dhtml_win_content'), params.params);
		}
	}
};

var Standings = 
{
	user_id: null,
	record_id: null,
	team_id: null,
	standings_round: null,
	challenge_id: null,
	entity_type: null,
	entity_id: null,
	pe: null,
	
	init: function(params, tabs)
	{
		Object.keys(params).each(function(e) { Standings[e] = params[e]; });
		
		var a = [$('entity_' + tabs[0]), $('challenge_' + tabs[1])];
		a.each(function(e) { if (e) e.src = e.src.replace('_off', '_on'); });
	},
	
	load: function(type, id, col)
	{
		switch (type)
		{
			case 'entity':
				this.entity_type = col;
				this.entity_id = id;
			break;
			
			case 'challenge':
				this.challenge_id = id;
			break;
		}

		Component.toggleTabIcon('standings_' + type, type + '_' + col + '_' + id);

		var params =
		{
				'do':'build',
				'id':this.record_id,
				'entity_type':this.entity_type,
				'entity_id':this.entity_id,
				'challenge_id':this.challenge_id
		};
		
		App.load('/cp/Standings/', 'standings_content', params);
	},
	
	addRival: function(event, rival_id)
	{
		var obj =
		{
			'do':'add_rival',
			'id':this.record_id,
			'rival_id':rival_id
		};
		
		var el = Event.element(event);
		
		App.onSuccess = function() { el.hide();	};
		App.request('/cp/Rivals/', 'POST', obj);
	},
	
	delRival: function(event, rival_id)
	{
		var obj =
		{
			'do':'del_rival',
			'id':this.record_id,
			'rival_id':rival_id
		};
		
		var el = Event.element(event);
		App.onSuccess = function() { el.up('tr').hide(); };
		App.request('/cp/Rivals/', 'POST', obj);
	},
	
	updateScroll: function(event)
	{
		if (this.team_id == null) return;
		
		if (event)
		{
			event.cancelBubble = true;
			window.detachEvent("onload", Standings.updateScroll);
		}
		
		var s = $('standings_scroll');
		var e = $("team_" + this.team_id.toString());
		var r = $("rival_" + this.team_id.toString());
		
		if (r) r.update("&nbsp;");
		
		if (s && e)
		{
			s.scrollTop = e.offsetTop - (s.offsetHeight / 2) + e.offsetHeight;
			e.className = "standings_row_team";
		}
	}
};

var CalorieCalc = 
{
	target: null,
	calories: 0,
	
	setTarget: function(target)
	{
		CalorieCalc.target = target;
	},
	
	getTarget: function(target)
	{
		return CalorieCalc.target;
	},
	
	init: function(val)
	{
		if (isNaN(parseInt(val))) return;
		CalorieCalc.calories = parseInt(val);
		$(CalorieCalc.getTarget().id).value = CalorieCalc.calories;
		if ($('total_calories')) $('total_calories').value = CalorieCalc.calories;
	},
	
	incQty: function(id)
	{
		if ($('qty_' + id))
		{
			$('qty_' + id).value++;
			$('qty_' + id).onchange();
			$('calories_' + id).onchange();
		}
	},
	
	decQty: function(id)
	{
		if ($('qty_' + id))
		{
			if ($('qty_' + id).value < 2) $('qty_' + id).value="";
			else $('qty_' + id).value--;
			$('qty_' + id).onchange();
			$('calories_' + id).onchange();
		}
	},
	
	updateCalories: function(id)
	{
		var qty = $('qty_' + id).value;
		var gms = $('gms_' + id).value;
		var cals = $('cals_' + id).value;
		
		if (qty.blank() || qty < 1) var calories = "";
		else calories = qty * (gms * cals);
		
		$('calories_' + id).value = Math.round(calories);
		if (calories < 1) calories = "";
		
		CalorieCalc.calories += parseInt($('calories_' + id).value);
	},
	
	updateTotal: function()
	{
		var total = 0;
		$$('.calories_input').each(function(e) { total += parseInt(e.value); });
		if (!isNaN(total)) CalorieCalc.init(total);
	}
};

var InfoBox =
{
	show: function(record_id) {
		if ($(record_id+"_info_hover")) {
			$(record_id+"_info_hover").style.display = "inline";
			$(record_id+"_info_backdrop").style.display = "block";
		}
		
		InfoBox.correct(record_id);
	},
	
	correct: function(record_id) {
		var el = $(record_id+"_info_box");
		if (el) {
			var abs = Page.absPos(el);
			
			if (App.getBrowser() == "msie 6") {
				$(record_id+"_info_hover").style.left = (abs['w']-354)+"px";
				if ($(record_id+"_info_box_content") && $(record_id+"_info_box_content").innerHTML != "") $(record_id+"_info_hover").style.width = "30em";
			} else if (App.getBrowser() == "msie") {
				if ($(record_id+"_info_box_content") && $(record_id+"_info_box_content").innerHTML != "") $(record_id+"_info_hover").style.width = "30em";
			}
			
			var abs = Page.absPos($(record_id+"_info"));
			
			if ($(record_id+"_info_hover")) {
				$(record_id+"_info_backdrop").style.width = ($(record_id+"_info_hover").clientWidth+21.5)+"px";
				$(record_id+"_info_backdrop").style.height = ($(record_id+"_info_hover").clientHeight+21.5)+"px";
				
				$(record_id+"_info_hover").style.left = abs['w']+"px";
				$(record_id+"_info_backdrop").style.left = (abs['w']-4)+"px";
				
				if (App.getBrowser() != "msie" && App.getBrowser() != "msie 6") {
					$(record_id+"_info_hover").style.top = (abs['n']-18)+"px";
					$(record_id+"_info_backdrop").style.top = (abs['n']-3)+"px";
				} else {
					$(record_id+"_info_hover").style.top = (abs['n']+6)+"px";
					$(record_id+"_info_backdrop").style.top = (abs['n']+20)+"px";
				}
			}
		}
	},

	hide: function(record_id)
	{
		if ($(record_id+"_info_hover"))
		{
			$(record_id+"_info_hover").style.display = "none";
			$(record_id+"_info_backdrop").style.display = "none";
		}
	}
};

var UserBox = 
{
	show: function(user_id)
	{
		if ($(user_id+"_user_hover")) {
			$(user_id+"_user_hover").style.display = "inline";
			$(user_id+"_user_backdrop").style.display = "block";
		}
		
		UserBox.correct(user_id);
	},
	
	correct: function(user_id) {
		var el = $(user_id+"_user_box");
		var abs = Page.absPos(el);
		
		if (App.getBrowser() == "msie 6") {
			$(user_id+"_user_hover").style.left = (abs['w']-354)+"px";
			if ($(user_id+"_user_box_content") && $(user_id+"_user_box_content").innerHTML != "") $(user_id+"_user_hover").style.width = "30em";
		} else if (App.getBrowser() == "msie") {
			if ($(user_id+"_user_box_content") && $(user_id+"_user_box_content").innerHTML != "") $(user_id+"_user_hover").style.width = "30em";
		}
		
		var abs = Page.absPos($(user_id+"_user"));
		
		if ($(user_id+"_user_hover")) {
			$(user_id+"_user_backdrop").style.width = ($(user_id+"_user_hover").clientWidth+21.5)+"px";
			$(user_id+"_user_backdrop").style.height = ($(user_id+"_user_hover").clientHeight+21.5)+"px";
			
			$(user_id+"_user_hover").style.left = abs['w']+"px";
			$(user_id+"_user_backdrop").style.left = (abs['w']-4)+"px";
			
			if (App.getBrowser() != "msie" && App.getBrowser() != "msie 6") {
				$(user_id+"_user_hover").style.top = (abs['n']-18)+"px";
				$(user_id+"_user_backdrop").style.top = (abs['n']-3)+"px";
			} else {
				$(user_id+"_user_hover").style.top = (abs['n']+6)+"px";
				$(user_id+"_user_backdrop").style.top = (abs['n']+20)+"px";
			}
		}
	},

	hide: function(user_id)
	{
		if ($(user_id+"_user_hover"))
		{
			$(user_id+"_user_hover").style.display = "none";
			$(user_id+"_user_backdrop").style.display = "none";
		}
	}
};

var Tutorial = 
{
	tutorialActive: false,
	inTutorialPlayer: false,
	
	childBubbles: Array(),
	loadingBubbles: Array(),
	
	bubbleTimer: false,
	
	toggleTutorial: function(user) {
		if (!Tutorial.tutorialActive) Tutorial.activateTutorial(user);
		else Tutorial.inactivateTutorial(user);
	},

	activateTutorial: function(user) {
		var check = confirm("Are you sure you want start the tutorial?");
		if (check) {
			var params = { 'do':'activate_tutorial', 'user':user };
			
			App.onSuccess = function() {
				Tutorial.beginTutorial();
			}
			
			App.request('/cp/Tutorial/', 'POST', params);
		}
	},
	
	inactivateTutorial: function(user) {
		var check = confirm("Are you sure you want to leave the tutorial?");
		if (check) {
			var params = { 'do':'inactivate_tutorial', 'user':user };
			
			App.onSuccess = function() {
				Tutorial.clearEverything(user);
			}
			
			App.request('/cp/Tutorial/', 'POST', params);
		}
	},
	
	beginTutorial: function() {
		Tutorial.tutorialActive = true;
		Tutorial.showallParentBubbles();
		Tutorial.showPlayer();
	},
	
	showTutorialBubble: function(bubble,target,anchor) {
		if (Tutorial.tutorialActive && !Tutorial.inTutorialPlayer) Page.showHelpBubble($(bubble),{'target':target, 'hideall':true, 'width':'400px', 'anchor':anchor, 'hideact':'mouseout'});
	},
	
	prepareTutorialTimer: function(bubble,target,anchor) {
		if (!anchor) var anchor = "w";
		Tutorial.bubbleTimer = setTimeout("Tutorial.showTutorialBubble('"+bubble+"','"+target+"','"+anchor+"')",200);
	},

	killTutorialTimer: function(bubble,target,anchor) {
		clearTimeout(Tutorial.bubbleTimer);
	},
	
	registerBubble: function(bubble,loading) {
		if (loading) Tutorial.loadingBubbles.push(bubble);
		else Tutorial.childBubbles.push(bubble);
	},
	
	clearBubbles: function() {
		if (Tutorial.tutorialActive) {
			for(var i = 0; i < Tutorial.loadingBubbles.length; i++) Tutorial.hideTutorialBubble(Tutorial.loadingBubbles[i]);
			for(var i = 0; i < Tutorial.childBubbles.length; i++) Tutorial.hideTutorialBubble(Tutorial.childBubbles[i]);
		}
	},
	
	hideTutorialBubble: function(bubble) {
		Page.hideHelpBubble($(bubble));
	},
	
	showallParentBubbles: function() {
		if (Tutorial.tutorialActive && !Tutorial.inTutorialPlayer) {
			for(var i = 0; i < Tutorial.loadingBubbles.length; i++) Tutorial.showParentBubble(Tutorial.loadingBubbles[i]);
		}
	},
	
	showParentBubble: function(bubble) {
		if (Tutorial.tutorialActive && !Tutorial.inTutorialPlayer) Page.showHelpBubble($(bubble),{'target':false, 'y':5, 'x':5, 'protect':true, 'hideall':true, 'anchor':'s', 'hideact':'mouseout'});
	},
	
	showChildBubble: function(bubble,y,x,protect,hideall,anchor) {
		if (Tutorial.tutorialActive && !Tutorial.inTutorialPlayer && $(bubble)) {
			if (!x) var x = 5;
			if (!y) var y = 5;
			if (!protect) var protect = true;
			if (!hideall) var hideall = true;
			if (!anchor) var anchor = 's';
			
			Page.showHelpBubble($(bubble),{'target':false, 'y':y, 'x':x, 'protect':protect, 'hideall':hideall, 'anchor':anchor, 'hideact':'mouseout'});
		}
	},
	
	hideTutorialBubble: function(bubble) { if ($(bubble)) Page.hideHelpBubble(bubble); },
	hideTutorial: function() { Tutorial.inactivateTutorial(); },

	arrowMin: false,
	arrowMax: false,
	arrowCurrentMotion: "out",
	arrowAnimateTimer: false,
	arrowMaxBounces: 0,
	arrowTotalBounces: 0,
	
	hideAllArrows: function() {
		if ($('tutorial_arrow_up')) $('tutorial_arrow_up').style.display = "none";
		if ($('tutorial_arrow_down')) $('tutorial_arrow_down').style.display = "none";
		if ($('tutorial_arrow_left')) $('tutorial_arrow_left').style.display = "none";
		if ($('tutorial_arrow_right')) $('tutorial_arrow_right').style.display = "none";
	},
	
	highlightObject: function(anchor,direction,maxBounces,extraLeftOffset,extraTopOffset) {
		Tutorial.killAnimateArrow();
		
		if (!extraLeftOffset) var extraLeftOffset = 0;
		if (!extraTopOffset) var extraTopOffset = 0;
		
		if (!maxBounces) var maxBounces = 2;
		Tutorial.arrowMaxBounces = maxBounces;
		
		var obj = $(anchor);
		var dir = "up";
		
		var bubble_pos = Page.absPos(obj);
		var point = Page.getPoint(obj, direction, 5);
		
		var leftShift = 0;
		var topShift = 0;
		
		if (direction == "e") {
			dir = "left";
			arrow = $('tutorial_arrow_'+dir); 
			
			arrow.style.display = "block";
			leftShift = (point.x - (obj.clientWidth/2))+extraLeftOffset;
			topShift = (point.y - (obj.clientHeight))+extraTopOffset;
		} else if (direction == "s") {
			dir = "up";
			arrow = $('tutorial_arrow_'+dir); 
			
			arrow.style.display = "block";
			leftShift = (point.x - (obj.clientWidth/2))+extraLeftOffset;
			topShift = (point.y + (obj.clientHeight))+extraTopOffset;
		} else if (direction == "w") {
			dir = "right";
			arrow = $('tutorial_arrow_'+dir); 
			
			arrow.style.display = "block";
			leftShift = (point.x - (obj.clientWidth*2))+extraLeftOffset;
			topShift = (point.y - (obj.clientHeight))+extraTopOffset;
		} else if (direction == "n") {
			dir = "down";
			arrow = $('tutorial_arrow_'+dir); 
			
			arrow.style.display = "block";
			leftShift = (point.x - (obj.clientWidth/2))+extraLeftOffset;
			topShift = (point.y - (obj.clientHeight+(arrow.clientHeight)))+extraTopOffset;
		}
		
		arrow.style.left = leftShift+"px";
		arrow.style.top = topShift+"px";
		
		Tutorial.animateArrow(arrow,direction,leftShift,topShift);
	},
	
	animateArrow: function(arrow,direction,left,top) {
		if (direction == "e") {
			Tutorial.arrowMin = left;
			Tutorial.arrowMax = left+75;
		} else if (direction == "s") {
			Tutorial.arrowMin = top;
			Tutorial.arrowMax = top+75;
		} else if (direction == "w") {
			Tutorial.arrowMin = left-75;
			Tutorial.arrowMax = left;
		} else if (direction == "n") {
			Tutorial.arrowMin = top-75;
			Tutorial.arrowMax = top;
		}
		
		Tutorial.arrowAnimateTimer = setTimeout("Tutorial.shiftArrow('"+arrow.id+"','"+direction+"',"+left+","+top+")",500);
	},
	
	killAnimateArrow: function() {
		clearTimeout(Tutorial.arrowAnimateTimer);
		Tutorial.arrowTotalBounces = 0;
	},
	
	shiftArrow: function(arrow,direction,left,top) {
		arrow = $(arrow);
		
		var divisor = 20;
		var newLeft = left;
		var newTop = top;
		
		if (Tutorial.arrowTotalBounces > Tutorial.arrowMaxBounces) {
			Tutorial.killAnimateArrow();
			return;
		}
		
		if (direction == "e") {
			if (Tutorial.arrowCurrentMotion == "out" && (left.toFixed() > (Tutorial.arrowMax-4))) { Tutorial.arrowCurrentMotion = "in"; }
			else if (Tutorial.arrowCurrentMotion == "in" && (left.toFixed() < (Tutorial.arrowMin+4))) { Tutorial.arrowCurrentMotion = "out"; Tutorial.arrowTotalBounces++; }
			
			if (Tutorial.arrowCurrentMotion == "out") newLeft += ((Tutorial.arrowMax-newLeft)/divisor);
			else newLeft -= ((newLeft-Tutorial.arrowMin)/divisor);
			
			arrow.style.left = newLeft+"px";
		} else if (direction == "s") {
			if (Tutorial.arrowCurrentMotion == "out" && (top.toFixed() > (Tutorial.arrowMax-4))) { Tutorial.arrowCurrentMotion = "in"; }
			else if (Tutorial.arrowCurrentMotion == "in" && (top.toFixed() < (Tutorial.arrowMin+4))) { Tutorial.arrowCurrentMotion = "out"; Tutorial.arrowTotalBounces++; }
			
			if (Tutorial.arrowCurrentMotion == "out") newTop += ((Tutorial.arrowMax-newTop)/divisor);
			else newTop -= ((newTop-Tutorial.arrowMin)/divisor);
			
			arrow.style.top = newTop+"px";
		} else if (direction == "w") {
			if (Tutorial.arrowCurrentMotion == "in" && (left.toFixed() < (Tutorial.arrowMin+4))) { Tutorial.arrowCurrentMotion = "out"; }
			else if (Tutorial.arrowCurrentMotion == "out" && (left.toFixed() > (Tutorial.arrowMax-4))) { Tutorial.arrowCurrentMotion = "in"; Tutorial.arrowTotalBounces++; }
			
			if (Tutorial.arrowCurrentMotion == "out") newLeft -= ((newLeft-Tutorial.arrowMax)/divisor);
			else newLeft += ((Tutorial.arrowMin-newLeft)/divisor);
			
			arrow.style.left = newLeft+"px";
		} else if (direction == "n") {
			if (Tutorial.arrowCurrentMotion == "in" && (top.toFixed() < (Tutorial.arrowMin+4))) { Tutorial.arrowCurrentMotion = "out"; }
			else if (Tutorial.arrowCurrentMotion == "out" && (top.toFixed() > (Tutorial.arrowMax-4))) { Tutorial.arrowCurrentMotion = "in";  Tutorial.arrowTotalBounces++; }
			
			if (Tutorial.arrowCurrentMotion == "out") newTop += ((Tutorial.arrowMax-newTop)/divisor);
			else newTop -= ((newTop-Tutorial.arrowMin)/divisor);
			
			arrow.style.top = newTop+"px";
		}
		
		clearTimeout(Tutorial.arrowAnimateTimer);
		Tutorial.arrowAnimateTimer = setTimeout("Tutorial.shiftArrow('"+arrow.id+"','"+direction+"',"+newLeft+","+newTop+")",10);
	},
	
	playerScript: false,
	playerSteps: false,
	forceActionTimer: false,
	nextPlayerBubbleTimer: false,
	lastPlayerBubble: false,
	currentTutorialStep: 0,
	observerList: Array(),
	completedObservers: Array(),
	user: false,
	
	clearEverything: function(user,keepBubbles) {
		Tutorial.clearSession(user);
		if (!keepBubbles) Tutorial.clearBubbles();
		
		if (Tutorial.currentTutorialStep == Tutorial.playerSteps) Tutorial.resetPlayer();
		else {
			clearTimeout(Tutorial.nextPlayerBubbleTimer);
			clearTimeout(Tutorial.forceActionTimer);
		}
		
		Tutorial.tutorialActive = false;
		Tutorial.inTutorialPlayer = false;
		
		Tutorial.hidePlayer();
		Tutorial.hideAllArrows();
	},
	
	registerPlayer: function(steps,script,user) {
		Tutorial.playerSteps = steps;
		Tutorial.playerScript = script;
		if (user) Tutorial.user = user;
	},
	
	resetPlayer: function() {
		clearTimeout(Tutorial.nextPlayerBubbleTimer);
		clearTimeout(Tutorial.forceActionTimer);
		Tutorial.lastPlayerBubble = false;
		Tutorial.currentTutorialStep = 0;
		Tutorial.hideAllArrows();
	},
	
	showPlayer: function() { if ($('tutorial_player')) $('tutorial_player').style.display = "block"; },
	hidePlayer: function() { if ($('tutorial_player')) $('tutorial_player').style.display = "none"; },

	showPlayerBubble: function(bubble,target,y,x,protect,hideall,anchor) {
		if (!target) var target = false;
		if (!y) var y = 5;
		if (!x) var x = 5;
		if (!protect) var protect = true;
		if (!hideall) var hideall = true;
		if (!anchor) var anchor = 's';
		
		if (Tutorial.inTutorialPlayer && $(bubble)) {
			if ($(bubble).innerHTML.indexOf("Close Bubble") < 0) $(bubble).innerHTML += "<div style='padding:1.5em 0 0 0; font-size:0.95em;'><a href='javascript:void(0);' onClick=Tutorial.inactivatePlayer('"+Tutorial.user+"');>Close Bubble</a>&nbsp;|&nbsp;<a href='javascript:void(0);' onClick=Tutorial.hideTutorial('"+Tutorial.user+"');>Exit Tutorial</a></div>";
			Page.showHelpBubble($(bubble),{'target':target, 'y':y, 'x':x, 'protect':protect, 'hideall':hideall, 'anchor':anchor, 'hideact':'mouseout'});
		}
	},
	
	activatePlayer: function(startingStep) {
		if ($('tutorial_player_play_container')) $('tutorial_player_play_container').style.display = "none";
		if ($('tutorial_player_controls_container')) $('tutorial_player_controls_container').style.display = "block";
		
		Tutorial.inTutorialPlayer = true;
		Tutorial.clearBubbles();
		
		var restarted = false;
		if (startingStep) Tutorial.currentTutorialStep = startingStep;
		else if (Tutorial.currentTutorialStep) {
			restarted = true;
			Tutorial.currentTutorialStep--;
		}
		
		Tutorial.processNextStep(false,restarted);
	},
	
	inactivatePlayer: function(user,keepBubbles) {
		if (!keepBubbles) var keepBubbles = false;
		
		if ($('tutorial_player_controls_container')) $('tutorial_player_controls_container').style.display = "none";
		if ($('tutorial_player_play_container')) $('tutorial_player_play_container').style.display = "block";
		
		Tutorial.clearEverything(user,keepBubbles);
		Tutorial.beginTutorial();
	},
	
	actionCompleted: function(obj) {
		if (!Tutorial.completedObservers.inArray(obj)) {
			Tutorial.processNextStep();
			Tutorial.completedObservers.push(obj);
		}
	},
	
	backScriptElement: function() {
		if (Tutorial.currentTutorialStep > 1) Tutorial.processNextStep(Tutorial.currentTutorialStep-1);
	},

	skipScriptElement: function() {
		if (Tutorial.currentTutorialStep < Tutorial.playerSteps) Tutorial.processNextStep(Tutorial.currentTutorialStep+1);
	},
	
	processNextStep: function(current_step,restarted) {
		if (!current_step) var current_step = Tutorial.currentTutorialStep+1;
		Tutorial.currentTutorialStep = current_step;
		
		Tutorial.hideAllArrows();
		
		if (Tutorial.lastPlayerBubble) {
			Tutorial.hideTutorialBubble(Tutorial.lastPlayerBubble);
			Tutorial.lastPlayerBubble = false;
		}
		
		var step = Tutorial.playerScript[Tutorial.currentTutorialStep];
		
		if (step.user && step.page) Tutorial.setSession(step.user,step.page,Tutorial.currentTutorialStep);
		if (step.bubble) {
			if (step.bubble.autoalign) {
				var scrollOffsets = document.viewport.getScrollOffsets();
				$(step.bubble.bubble).style.display = "block";
				
				if (step.bubble.autoalign == "center") {
					if (App.getBrowser() == "msie" || App.getBrowser() == "msie 6") {
						step.bubble.y = (scrollOffsets[1]+((document.viewport.getHeight()/2)-($(step.bubble.bubble).clientHeight/2)-100));
						step.bubble.x = ((document.body.offsetWidth/2)-($(step.bubble.bubble).clientWidth/2));
					} else {
						step.bubble.y = (scrollOffsets[1]+((document.viewport.getHeight()/2)-($(step.bubble.bubble).clientHeight/2)-100));
						step.bubble.x = ((window.innerWidth/2)-($(step.bubble.bubble).clientWidth/2));
						
						if (step.bubble.x == (window.innerWidth/2)) step.bubble.x -= 200;
					}
				}
				
				$(step.bubble.bubble).style.display = "none";
			} else {
				step.bubble.target = (step.bubble.target ? (step.bubble.delay && step.bubble.target.indexOf("'") < 0 ? "'"+step.bubble.target+"'" : step.bubble.target) : false);
				step.bubble.y = (step.bubble.y ? step.bubble.y : false);
				step.bubble.x = (step.bubble.x ? step.bubble.x : false);
				step.bubble.anchor = (step.bubble.anchor ? (step.bubble.delay && step.bubble.anchor.indexOf("'") < 0 ? "'"+step.bubble.anchor+"'" : step.bubble.anchor) : false);
			}
			
			step.bubble.protect = (step.bubble.protect ? step.bubble.protect : false);
			step.bubble.hideall = (step.bubble.hideall ? step.bubble.hideall : false);
			
			Tutorial.registerBubble(step.bubble.bubble);
			if (step.bubble.delay) Tutorial.nextPlayerBubbleTimer = setTimeout("Tutorial.showPlayerBubble('"+step.bubble.bubble+"',"+step.bubble.target+","+step.bubble.y+","+step.bubble.x+","+step.bubble.protect+","+step.bubble.hideall+","+step.bubble.anchor+")",step.bubble.delay);
			else Tutorial.showPlayerBubble(step.bubble.bubble,step.bubble.target,step.bubble.y,step.bubble.x,step.bubble.protect,step.bubble.hideall,step.bubble.anchor);
			
			Tutorial.lastPlayerBubble = step.bubble.bubble;
		}
		
		if (step.arrow) Tutorial.highlightObject(step.arrow.object,step.arrow.direction,step.arrow.bounces,step.arrow.offset_left,step.arrow.offset_top);
		
		if (step.await_action && Tutorial.currentTutorialStep < Tutorial.playerSteps) {
			if (!restarted) {
				if (step.await_action.object) {
					if (step.await_action.delay) setTimeout("Tutorial.setObserver('"+step.await_action.object+"','"+step.await_action.action+"')",(step.await_action.delay*1000));
					else Tutorial.setObserver(step.await_action.object,step.await_action.action);
				} else if (step.await_action.object_by_name) {
					for(var i = 0; i < document.getElementsByName(step.await_action.object_by_name).length; i++) {
						if (step.await_action.delay) setTimeout("Tutorial.setObserver('"+document.getElementsByName(step.await_action.object_by_name)[i].id+"','"+step.await_action.action+"')",(step.await_action.delay*1000));
						else Tutorial.setObserver(document.getElementsByName(step.await_action.object_by_name)[i].id,step.await_action.action);
					}
				}
			}
		} else {
			if (step.force_action && Tutorial.currentTutorialStep <= Tutorial.playerSteps) {
				if (!isArray(step.force_action)) var actions = Array(step.force_action);
				else var actions = step.force_action;
				
				for(var a = 0; a < actions.length; a++) {
					var action = actions[a];
					
					if (action.behavior) {
						if (action.wait) forceActionTimer = setTimeout("Tutorial.callBehavior('"+action.behavior+"','"+(action.uri ? action.uri : false)+"');",(action.wait*1000));
						else Tutorial.callBehavior(action.behavior,(action.uri ? action.uri : false));
					} else if (action.action) { 
						if (action.wait) forceActionTimer = setTimeout("Tutorial.callAction('"+action.object+"','"+action.action+"');",(action.wait*1000));
						else Tutorial.callAction(action.object,action.action);
					} else if (action.func) {
						if (action.wait) forceActionTimer = setTimeout("Tutorial.callFunc('"+action.func+"','"+action.params+"');",(action.wait*1000));
						else Tutorial.callFunc(action.func,action.params.toString());
					} else if (action.fill) {
						if (action.wait) forceActionTimer = setTimeout("Tutorial.callFill('"+action.fill+"',"+(action.set ? "'"+action.set+"'" : false)+","+(action.mark ? "'"+action.mark+"'" : false)+");",(action.wait*1000));
						else Tutorial.callFill(action.fill,(action.set ? action.set : false),(action.mark ? action.mark : false));
					}
				}
			}
			
			if (step.duration && Tutorial.currentTutorialStep < Tutorial.playerSteps) {
				var duration = parseInt(step.duration*1000);
				Tutorial.nextPlayerBubbleTimer = setTimeout("Tutorial.processNextStep()",duration);
			}
		}
		
		if (Tutorial.currentTutorialStep == Tutorial.playerSteps) {
			Tutorial.inactivatePlayer(Tutorial.user,true);
		}
	},
	
	setObserver: function(obj,act) {
		if ($(obj)) {
			if (!Tutorial.observerList.inArray(obj)) Tutorial.observerList.push(obj);
			
			$(obj).observe(act, function(event) {
				Tutorial.actionCompleted(obj);
			});
		}
	},
	
	callFunc: function(func,params) {
		params = params.split(",");
		
		var pass = "";
		for(var i = 0; i < params.length; i++) {
			if (isNumeric(params[i])) pass += params[i]+",";
			else pass += "'"+params[i]+"',";
		}
		pass = pass.substring(0,pass.length-1);
		
		try { eval(func+"("+pass+")"); }
		catch(err) { return false; }
	},
	
	callAction: function(obj,action) {
		try { eval("$('"+obj+"')."+action+"()"); }
		catch(err) {
			try { $(obj).fire(action); }
			catch(err) { alert("Tutorial error:\n\n"+err); }
		}
	},
	
	callFill: function(obj,set,mark) {
		if (set) {
			try { $(obj).value = set; }
			catch(err) { alert("Tutorial error:\n\n"+err); }
		} else if (mark) {
			try { eval("$('"+obj+"')."+mark+" = true;"); }
			catch(err) { alert("Tutorial error:\n\n"+err); }
		}
	},
	
	callBehavior: function(behavior,uri) {
		if (behavior == "redirect") window.location = uri;
		else window.reload();
	},
	
	setSession: function(user,page,step) {
		var params = { 'do':'set-session', 'user':user, 'page':page, 'step':step };
		App.request('/cp/Tutorial/', 'POST', params);
	},
	
	clearSession: function(user) {
		var params = { 'do':'clear-session', 'user':user };
		App.request('/cp/Tutorial/', 'POST', params);
	}
};

var Plans = 
{
	category_mapping: { 'Weight loss':'6',
						'Physical Activity':'7',
						'Nutrition':'8',
						'Mental Well-Being':'9',
						'Smoking Cessation':'10' },
	
	confirmPlan: function(record_id,user_ids,schedule,date) {
		var params = { 'do':'decide-plan-date', 'id':record_id, 'user_ids':user_ids, 'schedule':schedule, 'date':date };
		App.onSuccess = function() {}
		App.request('/cp/PlanOverview/', 'POST', params);
	},
	
	parseRecurring: function(text) {
		text = text.toLowerCase();
		var dNow = new Date();
		
		if ((text == "this week" || text == "next week") ||
			(text.indexOf("sometime") > -1 && (text.indexOf("this week") > -1 || text.indexOf("next week")))) return Array("0","1","2","3","4","5","6");
		else if ((text == "this month" || text == "next month") ||
				(text.indexOf("sometime") > -1 && (text.indexOf("this month") > -1 || text.indexOf("next month")))) return Array("0","1","2","3","4","5","6");
		else if (text.indexOf("every") > -1) {
			if (text.indexOf("except") < 0) {
				if (text.indexOf("sun") > -1) return Array("0");
				else if (text.indexOf("mon") > -1) return Array("1");
				else if (text.indexOf("tue") > -1) return Array("2");
				else if (text.indexOf("wed") > -1) return Array("3");
				else if (text.indexOf("thu") > -1) return Array("4");
				else if (text.indexOf("fri") > -1) return Array("5");
				else if (text.indexOf("sat") > -1) return Array("6");
				else if (text.indexOf(" day") > -1) return Array("0","1","2","3","4","5","6");
				else if (text.indexOf(" week") > -1) return Array(dNow.getDay().toString());
			} else if (text.indexOf("except") > -1 && text.indexOf(" day") > -1) {
				if (text.indexOf("sun") > -1) return Array("1","2","3","4","5","6");
				else if (text.indexOf("mon") > -1) return Array("0","2","3","4","5","6");
				else if (text.indexOf("tue") > -1) return Array("0","1","3","4","5","6");
				else if (text.indexOf("wed") > -1) return Array("0","1","2","4","5","6");
				else if (text.indexOf("thu") > -1) return Array("0","1","2","3","5","6");
				else if (text.indexOf("fri") > -1) return Array("0","1","2","3","4","6");
				else if (text.indexOf("sat") > -1) return Array("0","1","2","3","4","5");
			}
		}
		
		return false;
	},
	
	guessTentative: function(text) {
		text = text.toLowerCase();
		
		if (text.indexOf("sometime") > -1 ||
			text.indexOf("maybe") > -1 ||
			text.indexOf("perhaps") > -1) return true;
		
		return false;
	},
	
	guessEndDate: function(text) {
		text = text.toLowerCase();
		
		var guess = false;
		var dNow = new Date();
		
		if (text.indexOf("this week") > -1) dNow.setDate(dNow.getDate() + 7);
		else if (text.indexOf("next week") > -1) dNow.setDate(dNow.getDate() + 14);
		else if (text.indexOf("this month") > -1) dNow.setDate(daysInMonth(dNow.getMonth(),dNow.getYear()));
		else if (text.indexOf("next month") > -1) { dNow.setMonth(dNow.getMonth() + 1); dNow.setDate(daysInMonth(dNow.getMonth(),dNow.getYear())); }
		else return false;
		
		var dateString = (dNow.getMonth()+1)+"/"+dNow.getDate()+"/"+dNow.getFullYear();
		return dateString;
	},
	
	guessActivity: function(text) {
		text = text.toLowerCase();
		var guess = false;
		
		if (text.indexOf("gym") > -1) guess = "Go to the gym";
		else if (text.indexOf("run") > -1) guess = "Go running";
		else if (text.indexOf("walk") > -1) guess = "Go walking";
		else if (text.indexOf("yoga") > -1) guess = "Go to yoga";
		else if (text.indexOf("dinner") > -1) guess = "Make dinner at home";
		else if (text.indexOf("supper") > -1) guess = "Make dinner at home";
		else if (text.indexOf("lunch") > -1) guess = "Eat a healthy lunch";
		
		return guess;
	},
	
	guessCategory: function(text) {
		text = text.toLowerCase();
		var guess = false;
		
		if ((text.indexOf("gym") > -1 ||
			 text.indexOf("run") > -1 ||
			 text.indexOf("walk") > -1 ||
			 text.indexOf("basketball") > -1 ||
			 text.indexOf("yoga") > -1) && 
			Plans.category_mapping["Physical Activity"]) guess = Plans.category_mapping["Physical Activity"];
		else if ((text.indexOf("dinner") > -1 ||
				  text.indexOf("supper") > -1 ||
				  text.indexOf("lunch") > -1) && 
				 Plans.category_mapping["Nutrition"]) guess = Plans.category_mapping["Nutrition"];
		
		return guess;
	},
	
	findInvitees: function(search,target) {
		var params = { 'do':'find-invitees', 'search':search };
		App.request('/cp/PlanCreate/', 'POST', params, target);
	}
};

var Language = 
{
	textToDateString: function(text) {
		text = text.toLowerCase();
		var dateCheck = text.isDate();
		if (dateCheck) {
			objDate = new Date();  
			objDate.setTime(dateCheck);
			
			return text;
		}
				
		guess = "";
		
		var dNow = new Date();
		var showDate = false;
		
		if (text == "this week") guess = "This week";
		else if (text == "next week") guess = "Next week";
		else if (text.indexOf("sometime") > -1 && text.indexOf("this week") > -1) guess = "Sometime this week";
		else if (text.indexOf("sometime") > -1 && text.indexOf("next week") > -1) guess = "Sometime next week";
		else if (text == "this month") guess = "This month";
		else if (text == "next month") guess = "Next month";
		else if (text.indexOf("sometime") > -1 && text.indexOf("this month") > -1) guess = "Sometime this month";
		else if (text.indexOf("sometime") > -1 && text.indexOf("next month") > -1) guess = "Sometime next month";
		else if (text.indexOf("every") > -1) {
			var doy = false;
			var everyText = text;
			var exceptText = text;
			
			if (text.indexOf("except") > -1) {
				var splitText = text.split("except");
				everyText = splitText[0];
				exceptText = splitText[1];
			}
			
			if (everyText.indexOf("mon") > -1) { guess += "Every Mon"; doy = "1"; }
			else if (everyText.indexOf("tue") > -1) { guess += "Every Tue"; doy = "2"; }
			else if (everyText.indexOf("wed") > -1) { guess += "Every Wed"; doy = "3"; }
			else if (everyText.indexOf("thu") > -1) { guess += "Every Thu"; doy = "4"; }
			else if (everyText.indexOf("fri") > -1) { guess += "Every Fri"; doy = "5"; }
			else if (everyText.indexOf("sat") > -1) { guess += "Every Sat"; doy = "6"; }
			else if (everyText.indexOf("sun") > -1) { guess += "Every Sun"; doy = "0"; }
			else if (everyText.indexOf(" day") > -1) guess += "Every day";
			else if (everyText.indexOf(" week") > -1) guess += "Every week";
			
			if (text.indexOf("except") > -1 && text.indexOf(" day") > -1) {
				if (exceptText.indexOf("mon") > -1) guess += "except Mon";
				else if (exceptText.indexOf("tue") > -1) guess += "except Tue";
				else if (exceptText.indexOf("wed") > -1) guess += "except Wed";
				else if (exceptText.indexOf("thu") > -1) guess += "except Thu";
				else if (exceptText.indexOf("fri") > -1) guess += "except Fri";
				else if (exceptText.indexOf("sat") > -1) guess += "except Sat";
				else if (exceptText.indexOf("sun") > -1) guess += "except Sun";
			}
			
			if (doy) {
				guess += " starting";
				
				var increment = parseInt(doy) - dNow.getDay();
				var dTemp = new Date();
				dTemp.setDate(dTemp.getDate()+increment);
				
				guess += " "+dTemp.format("M j");
			}
		} else if (text.indexOf("next") > -1) {
			var doy = false;
			
			if (text.indexOf("mon") > -1) { guess += "Next Monday"; doy = 1; }
			else if (text.indexOf("tue") > -1) { guess += "Next Tuesday"; doy = 2; }
			else if (text.indexOf("wed") > -1) { guess += "Next Wednesday"; doy = 3; }
			else if (text.indexOf("thu") > -1) { guess += "Next Thursday"; doy = 4; }
			else if (text.indexOf("fri") > -1) { guess += "Next Friday"; doy = 5; }
			else if (text.indexOf("sat") > -1) { guess += "Next Saturday"; doy = 6; }
			else if (text.indexOf("sun") > -1) { guess += "Next Sunday"; doy = 0; }
			else if (text.indexOf(" day") > -1) guess += "Next day";
			else if (text.indexOf(" week") > -1) guess += "Next day";
		} else {
			if (text.indexOf("today") > -1 ||
				text.indexOf("this morning") > -1 ||
				text.indexOf("this afternoon") > -1) guess += "Today";
			else if (text.indexOf("tonight") > -1 ||
					 text.indexOf("this evening") > -1 ||
					 text.indexOf("tonight") > -1) guess += "Tonight";
			else if (text.indexOf("tomorrow") > -1 &&
					 text.indexOf("day after tomorrow") < 0) guess += "Tomorrow";
		}
		
		if (showDate) guess += " "
		
		if (text.indexOf("morning") > -1) guess += " at 8:00 AM";
		else if (text.indexOf("afternoon") > -1) guess += " at 1:00 PM";
		else if (text.indexOf("after work") > -1 ||
				 text.indexOf("following work") > -1 ||
				 text.indexOf("this evening") > -1 ||
				 text.indexOf("tonight") > -1) guess += " at 5:00 PM";
		else if (text.indexOf("today") > -1 ||
				 text.indexOf("during lunch") > -1 ||
				 text.indexOf("after lunch") > -1) guess += " at 12:00 PM";
		//else guess += " at "+dNow.getHours()+":"+dNow.getMinutes()+" "+(dNow.getHours() > 11 ? "PM" : "AM");
		
		if (guess != "") return guess;
		else return false;
	},
	
	textToDate: function(text) {
		text = text.toLowerCase();
		if (text.isDate()) return text;
		
		var dateString = "";
		
		var dNow = new Date();
		var dNext = new Date();
		
		if (text.indexOf("every") > -1) {
			var doy = false;
			var everyText = text;
			var exceptText = text;
			
			if (text.indexOf("except") > -1) {
				var splitText = text.split("except");
				everyText = splitText[0];
				exceptText = splitText[1];
			}
			
			if (everyText.indexOf("mon") > -1) doy = "1";
			else if (everyText.indexOf("tue") > -1) doy = "2";
			else if (everyText.indexOf("wed") > -1) doy = "3";
			else if (everyText.indexOf("thu") > -1) doy = "4";
			else if (everyText.indexOf("fri") > -1) doy = "5";
			else if (everyText.indexOf("sat") > -1) doy = "6";
			else if (everyText.indexOf("sun") > -1) doy = "0";
			
			if (doy) {
				var increment = parseInt(doy) - dNow.getDay();
				dNext.setDate(dNow.getDate() + increment);
			}
		} else if (text.indexOf("next") > -1) {
			var doy = false;
			
			if (text.indexOf("mon") > -1) doy = 1;
			else if (text.indexOf("tue") > -1) doy = 2;
			else if (text.indexOf("wed") > -1) doy = 3;
			else if (text.indexOf("thu") > -1) doy = 4;
			else if (text.indexOf("fri") > -1) doy = 5;
			else if (text.indexOf("sat") > -1) doy = 6;
			else if (text.indexOf("sun") > -1) doy = 0;
			else if (text.indexOf("week") > -1) dNext.setDate(dNow.getDate() + 7);
			else if (text.indexOf("month") > -1) dNext.setDate(dNow.getMonth() + 1);
			else if (text.indexOf("year") > -1) dNext.setDate(dNow.getYear() + 1);
			
			if (doy) {
				var increment = parseInt(doy) - dNow.getDay();
				dNext.setDate(dNow.getDate() + increment);
			}
		} else if (text.indexOf("tomorrow") > -1 &&
				   text.indexOf("day after tomorrow") < 0) { dNext.setDate(dNow.getDate() + 1); }
		else if (text.indexOf("day after tomorrow") > -1) dNext.setDate(dNow.getDate() + 2);
		
		var parts = text.toLowerCase().split(" ");
		for(var i = 0; i < parts.length; i++) {
			if (parts[i] == "at" && isNumeric(parts[i+1])) {
				if (parts[i+2] == "PM" && parts[i+1] < 12) dNext.setHours(parts[i+1]+12);
				else dNext.setHours(parts[i+1]);
			}
		}
		
		dNext.setMinutes(0);
		
		dateString = dNext.getFullYear()+"/"+(dNext.getMonth()+1)+"/"+dNext.getDate()+" "+dNext.getHours()+":"+(dNext.getMinutes().length == 1 ? dNext.getMinutes() : "0"+dNext.getMinutes());
		dateString += ":00";
		
		if (dateString != "") return dateString;
		else return false;
	}
};

var Mapping = 
{
	currentLatLong: false,
	sendCanvas: false,
	
	getMapAndMarkers: function(canvas,markers,center) {
		if (GBrowserIsCompatible()) {
			var map = new GMap2(document.getElementById(canvas));
			map.setCenter(new GLatLng(center.lat, center.long), 13);
			
        	for (var i = 0; i < markers.length; i++) {
        		var point = new GLatLng(markers[i].lat,
        								markers[i].long);
        		
        		map.addOverlay(new GMarker(point));
        	}
		}
	},
	
	parseLocation: function(response) {
		if (response) {
			var place = response.Placemark[0];
			Mapping.currentLatLong = { 'lat':place.Point.coordinates[1], 'long':place.Point.coordinates[0] };
		} else Mapping.currentLatLong = false;
		
		Mapping.getMapAndMarkers(Mapping.sendCanvas,Array(Mapping.currentLatLong),Mapping.currentLatLong);
	},
	
	getAddress: function(search) {
		var geocoder = new GClientGeocoder();
		geocoder.getLocations(search,Mapping.parseLocation);
	},
	
	buildMapByAddress: function(addr,canvas,textTarget) {
		Mapping.sendCanvas = canvas;
		Mapping.getAddress(addr);
		Mapping.grabAndSendAddress(addr,textTarget);
	},
	
	getLatLong: function(search) {
		App.onSuccess = function(latlong) { return latlong; };
		var params = { 'do':'get-latlong', 'search':search };
		App.request("/cp/Maps/", "POST", params);
	},
	
	grabAndSendAddress: function(search,target) {
		App.onSuccess = function(addr) { $(target).innerHTML = addr; };
		var params = { 'do':'get-address', 'search':search };
		App.request("/cp/Maps/", "POST", params);
	}
};

