/******************************************************************************/
/************************************************************ EXETEND DATES ***/
/******************************************************************************/
Date.prototype.render = function(dateTemplate)
{
	if(!dateTemplate) return this.toString();
	var	dateStr		= dateTemplate,
		monthNames 	= ["January", "February", "March", "April", "May", "June", "July", "August", "September", "October", "November", "December"],
		weekDays	= ["Sunday", "Monday", "Tuesday", "Wednesday","Thursday", "Friday", "Saturday"];
	dateStr = dateStr.replace(/wd/i,weekDays[this.getDay()]);
	dateStr = dateStr.replace(/dd/i,this.getDate().zeropad());
	dateStr = dateStr.replace(/mm/i,(this.getMonth()+1).zeropad());
	dateStr = dateStr.replace(/month/i,monthNames[this.getMonth()]);
	dateStr = dateStr.replace(/yyyy/i,this.getFullYear());
	if(/yy/i.test(dateStr))	dateStr = dateStr.replace(/yy/i,this.getYear().toString().substr(2,2));
	dateStr = dateStr.replace(/hh/i,this.getHours().zeropad());
	dateStr = dateStr.replace(/mi/i,this.getMinutes().zeropad());
	dateStr = dateStr.replace(/ss/i,this.getSeconds().zeropad());
	dateStr = dateStr.replace(/ms/i,this.getMilliseconds().zeropad());
	return dateStr;
}
Date.getDaysInMonth = function(m,y)
{
	var d = 31;	
	if (m == 2 && y % 4 == 0 && (y % 100 != 0 || y % 400 == 0)){d = 29;} 
	else if (m == 2){d = 28;} 
	else if (m == 4 || m == 6 || m == 9 || m == 11){d = 30;}
	return d;	
}
Date.prototype.getDaysInMonth = function(m,y)
{
	return Date.getDaysInMonth(this.getMonth()+1,this.getFullYear());
}

/******************************************************************************/
/*********************************************************** EXETEND ARRAYS ***/
/******************************************************************************/
Array.prototype.push = function()
{
    var n = this.length >>> 0;
    for (var i = 0; i < arguments.length; i++)
	{
		this[n] = arguments[i];
		n = n + 1 >>> 0;
    }
    this.length = n;
    return n;
}
/******************************************************************************/
/********************************************************** EXETEND NUMBERS ***/
/******************************************************************************/
Number.prototype.zeropad = function()
{
	var num = parseInt(this,10) || 0;
	return(num<10 ? '0' + num:num);
}
/******************************************************************************/
/********************************************************** EXETEND STRINGS ***/
/******************************************************************************/
String.prototype.trim = function()
{
	return this.replace(/^\s+|\s+$/,"");
}
String.prototype.chars = function(num,mult)
{	
	mult = mult || 1;
	return new Array(num*mult+1).join(this);
}
/******************************************************************************/
/**************************************************** EXETEND ELEMENTS (FF) ***/
/******************************************************************************/
if(typeof Element !== "undefined")
{
	Element.prototype.swapNode = function (swapWith)
	{
		var itemtmp = this.cloneNode(1),
			parent 	= this.parentNode;		
		swapWith = parent.replaceChild(itemtmp, swapWith);
		parent.replaceChild(swapWith, this);
		parent.replaceChild(this, itemtmp);
		itemtmp = null;
	}
	Element.prototype.contains = function(child)
	{
		while(child && child !== this)
			child = child.parentNode;
		return(child === this);
	}
	Element.prototype.__defineSetter__
	(
		"innerText", 
		function (sText)
		{
	   		this.innerHTML = sText.replace(/\&/g, "&amp;").replace(/</g, "&lt;").replace(/>/g, "&gt;");
		}
	);
	Element.prototype.__defineGetter__
	(
		"innerText", 
		function ()
		{
		   var r = this.ownerDocument.createRange();
		   r.selectNodeContents(this);
		   return r.toString();
		}
	);
	Event.prototype.__defineGetter__
	(
		"srcElement", 
		function ()
		{
		   var node = this.target;
		   while (node.nodeType != 1) node = node.parentNode;
		   return node;
		}
	);	
	Event.prototype.__defineSetter__
	(
		"cancelBubble", 
		function (b)
		{
		   if (b) this.stopPropagation();
		}
	);
	Event.prototype.__defineSetter__
	(
		"returnValue", 
		function (b)
		{
		   if (!b) this.preventDefault();
		}
	);
	Event.prototype.__defineGetter__
	(
		"fromElement",
		function ()
		{
		   var node;
		   if (this.type == "mouseover")
		      node = this.relatedTarget;
		   else if (this.type == "mouseout")
		      node = this.target;
		   else
		      return null;
		   while (node.nodeType != 1) node = node.parentNode;
		   return node;
		}
	);
	Event.prototype.__defineGetter__
	(
		"toElement",
		function ()
		{
		   var node;
		   if (this.type == "mouseout")
		      node = this.relatedTarget;
		   else if (this.type == "mouseover")
		      node = this.target;
		   else
		      return null;
		   while (node.nodeType != 1) node = node.parentNode;
		   return node;
		}
	);
}	
/******************************************************************************/
/********************************************************************** DOM ***/
/******************************************************************************/
var $D = new function()
{
	this.$ = function()
	{
		var elements = new Array();
		for (var i=0;i<arguments.length;i++)
		{	
			var element = arguments[i];			
			if(typeof element == "string") 
				element = document.getElementById(element);
			elements.push(element);
		}
		if(elements.length == 0)
			return null;
		else if (elements.length == 1)
			return elements[0];
		else
			return elements;
	}
	this.IsClass = function(objRef,className)
	{
		return ((new RegExp("\\b" + className.trim() + "\\b","gi")).test(objRef.className));
	}
	this.SetClass = function(objRef,className)
	{
		$D.ClearClass(objRef)
		objRef.className = className.trim();
	}
	this.AddClass = function(objRef,className)
	{
		$D.RemoveClass(objRef,className);
		objRef.className = (objRef.className + " " + className).trim();
	}
	this.RemoveClass = function(objRef,className)
	{
		objRef.className = objRef.className.replace(className,"").trim();
	}
	this.ClearClass = function(objRef)
	{
		objRef.className = "";
	}
	this.GetElementsByClassName = function(strClass, objContElm, strTag)
	{
		strTag = strTag || "*";
		objContElm = objContElm || document;
		var objColl = objContElm.getElementsByTagName(strTag);
		if (!objColl.length &&  strTag == "*" &&  objContElm.all) objColl = objContElm.all;
		var resultArray = [];
		var delim = strClass.indexOf('|') != -1  ? '|' : ' ';
		var arrClass = strClass.split(delim);
		for (var i = 0, j = objColl.length; i < j; i++)
		{
			var arrObjClass = objColl[i].className.split(' ');
			if (delim == ' ' && arrClass.length > arrObjClass.length) continue;
			var c = 0;
			comparisonLoop:
			for (var k = 0, l = arrObjClass.length; k < l; k++)
			{
		 		for (var m = 0, n = arrClass.length; m < n; m++)
				{
		    		if (arrClass[m] == arrObjClass[k]) c++;
				    	if (( delim == '|' && c == 1) || (delim == ' ' && c == arrClass.length))
						{
				    	  resultArray.push(objColl[i]);
				    	  break comparisonLoop;
		    			}
		  		}
			}
		}
		return resultArray;
	}
	this.GetElementsByTagNames = function(objRef, tagNames)
	{
		objRef = objRef || document;
		var resultArray = [];
		for (var i=1,len=tagNames.length;i<len;i++)
		{
			var tags = objRef.getElementsByTagName(tagNames[i]);
			for (var j=0;j<tags.length;j++)
			{
				resultArray.push(tags[j]);
			}
		}
		var testNode = resultArray[0];
		if(!testNode) return [];
		if (testNode.sourceIndex)
		{
			resultArray.sort(function (a,b)
							{
								return a.sourceIndex - b.sourceIndex;
							});
		}
		else if(testNode.compareDocumentPosition)
		{
			resultArray.sort(function (a,b)
							{
								return 3 - (a.compareDocumentPosition(b) & 6);
							});
		}
		return resultArray;
	}
	this.GetStyle = function(objRef, propName)
	{
		if(objRef.currentStyle)
			return objRef.currentStyle[propName.replace(/-([a-z])/gi,function(a,b){return b.toUpperCase()})];
		else if(window.getComputedStyle)
			return window.getComputedStyle(objRef,null).getPropertyValue(propName.replace(/[A-Z]/g,function(a){return "-" + a.toLowerCase()}));
	}
	this.GetChildLevel = function(parent, child)
	{
		var level = 0;
		while(child && child != parent)
		{
			level ++;
			child = child.parentNode;
		}
		return level;
	}
	this.IsSameChildLevel = function(parent, child1, child2)
	{
		var count1 = 0, count2 = 0;
		while(child1 && child2 && child1 != parent && child2 != parent)
		{
			child1 = child1.parentNode;
			child2 = child2.parentNode;
		}
		return(child1 == parent && child2 == parent);
	}
	this.IsInBoundry = function(point, boundry)
	{
		//IMPLAMENT
	}
	this.GetOffsetPosition = function(objRef)
	{
		var l = 0, t = 0;
		while(objRef)
		{
			l += objRef.offsetLeft;
			t += objRef.offsetTop;
			objRef = objRef.offsetParent;
		}
		return {left:l,top:t};
	}
	this.GetMousePosition = function(e)
	{
		var x = 0, y=0;
		if(e.pageX || e.pageY)
		{
			x = e.pageX;
			y = e.pageY;
		}
		else if(e.clientX || e.clientY)
		{
			x = e.clientX + document.body.scrollLeft + document.documentElement.scrollLeft;
			y = e.clientY + document.body.scrollTop + document.documentElement.scrollTop;
		}
		return {left:x,top:y};
	}
	this.GetOffsetMousePosition = function(e)
	{
		var x = 0, y=0, 
			objRef = e.srcElement;
		
		if(e.offsetX || e.offsetY)
		{
			x = e.offsetX;
			y = e.offsetY;
		}
		else if(e.pageX || e.pageY)
		{
			var pos = $D.getOffsetPosition(objRef);
			x = e.pageX - pos.left;
			y = e.pageY - pos.top;
		}
		return {left:x,top:y};
	}
	this.DocumentWrite = function(str)
	{
		document.write(str);
	}

	this.Select = {}

	this.Select.addOption = function(objRef, text, value)
	{
		objRef.options[objRef.options.length] = new Option(text, (value || text));
	}

}
var $ = $D.$;
/******************************************************************************/
/******************************************************************* EVENTS ***/
/******************************************************************************/
var $E  = new function()
{
	this.add = function(objRef,type,fn,useCapture)
	{
		objRef['e'+type+fn] = fn;

		if (objRef.attachEvent)
		{
			objRef[type+fn] = function() { objRef['e'+type+fn](window.event, objRef); }
			objRef.attachEvent('on'+type,objRef[type+fn]);
		}
		else
		{
			objRef[type+fn] = function(e) {objRef['e'+type+fn](e,this)};
			useCapture = useCapture || false;
			objRef.addEventListener(type,objRef[type+fn],useCapture);
		}
	}
	this.remove = function(objRef,type,fn)
	{
		if(objRef.detachEvent)
		{	
			objRef.detachEvent('on'+type,objRef[type+fn]);
			objRef[type+fn] = null;
		}
		else
		{
			objRef.removeEventListener(type,objRef[type+fn],false);
			objRef[type+fn] = null;
		}
	}
	this.onload = function(func)
	{
		var oldonload = window.onload;
		if(typeof window.onload != "function")
			$E.add(window, "load", func)
		else
			$E.add(window, "load", function(){oldonload();func();})
	}
	this.preventDefault = function(e)
	{
		if(e.preventDefault)
		{
			e.preventDefault();
		}
		else
		{
			e.returnValue = false;
 			e.cancelBubble = true;
		}		
	}
	this.cross = function(e)
	{
		if(e.keyCode) e.which = e.keyCode; 	else e.keyCode = e.which;
		if(!e.charCode) e.charCode = e.keyCode;
	}
	this.emulate = function()
	{
		//IMPLAMENT:
		//mouseenter and mouseleave  - http://blog.stchur.com/2007/03/15/mouseenter-and-mouseleave-events-for-firefox-and-other-non-ie-browsers/
		var events = ["mouseenter", "mouseleave"];
	}
}
/******************************************************************************/
/**************************************************************** UTILITIES ***/
/******************************************************************************/
var $U = new function()
{
	this.setSettings = function (from,to)
	{
		for(var s in from)
		{
			if(typeof from[s] != "object")
			{
				to[s] = from[s];
			}
			else
			{
				if(!to[s]) to[s] = {};
				setSettings(from[s], to[s])
			}
		}
	}
	this.Trace = new function()
	{
		var debugDiv		=  null,
			lineNum			= 1
			lineNumPadding	= 3;
		
		this.write = function(str)	
		{
			if(!debugDiv) debugDiv = buldWindow();			
			var objRef = document.createElement("SPAN");
				objRef.innerHTML = str;
			debugDiv.appendChild(objRef);
			debugDiv.scrollTop = debugDiv.scrollHeight;
		}
		this.writeLine = function(str)	
		{
			if(!debugDiv) debugDiv = buldWindow();
			var objRef = document.createElement("SPAN");
				objRef.innerHTML = str + '<br /><span style="background-color:#CFCFCF">' + '&nbsp;'.chars(lineNumPadding - (lineNum).toString().length) + (lineNum++) + ' </span>&nbsp;';
			debugDiv.appendChild(objRef);
			debugDiv.scrollTop = debugDiv.scrollHeight;
		}
		this.clear = function()
		{
			debugDiv.innerHTML = "";
		}		
		function buldWindow()
		{
			var	objRef 						= document.createElement("DIV");
				objRef.id 					= "$debugDiv";
				objRef.style.bottom			= "0px";
				objRef.style.right			= "0px";
				objRef.style.color			= "blue";
				objRef.style.width			= "300px";
				objRef.style.height			= "200px";
				objRef.style.border			= "2px solid red";
				objRef.style.overflow		= "auto";
				objRef.style.position		= "absolute";
				objRef.style.fontFamily		= "Fixedsys";
				objRef.style.whiteSpace		= "nowrap";
				objRef.style.backgroundColor= "#E0E0E0";
				objRef = document.body.appendChild(objRef);
			objRef.innerHTML = '<span style="background-color:#CFCFCF">' + "&nbsp;".chars(lineNumPadding - (lineNum).toString().length) + (lineNum++) + ' </span>&nbsp;';
			return objRef;
		}
	}	
}
window.trace = $U.Trace.writeLine;
/******************************************************************************/
/************************************************************* Ajax Handler ***/
/******************************************************************************/
function AjaxHandler(_href, _onResponse, settingsObject)
{
	// #region PUBLIC VARIABLES //

	this.OnResponse			= _onResponse;
	this.Href				= _href;
	this.ResponseText		= null;		
	this.Settings = 
		{
			Async				: true,
			Method				: "GET",
			ThrowOnServerError	: true
		};
		
	// #endregion PUBLIC VARIABLES //

	
	// #region PRIVATE VARIABLES //	
	
	var config	= this.Settings,
		href	= "",
		reqObj 	= null,
		objRef	= this;
			
	// #endregion PRIVATE VARIABLES //
	
 			
	(function init()
	{
		ctor();
	})()
	
	function ctor()
	{
		if(reqObj) return true;
		try{
			reqObj = new XMLHttpRequest();
		}
		catch(e)
		{
			try{
				reqObj = new ActiveXObject("Msxml2.XMLHTTP.4.0");
			}
			catch(e)
			{
				try{
					reqObj = new ActiveXObject("Msxml2.XMLHTTP");
				}
				catch(e)
				{
					try{
						reqObj = new ActiveXObject("microsoft.XMLHTTP");
					}
					catch(e)
					{
						reqObj = null;
					}
				}
			}
		}
		if(!reqObj)
		{
			throw new Error("$AJAX error: Unable to initialize XMLHttp object");
			return false;
		}
		else
		{
			$U.setSettings(settingsObject,config);
			return true;
		}
	}	

	this.execute = function(params)
	{	
		var queryString = "";
		
		if(params)
		{
			for(var p in params)
			{
				queryString += p + "=" + params[p] + "&";
			}
		}
		
		if(typeof objRef.OnResponse != "function")
		{
			throw new Error("$AJAX error: onResponse does not contain function, unable to return data!");
		}

		href = this.Href;
		
		if(config.Method != "POST")
		{
			
			if(href.indexOf("?") == -1)
				href += "?";
			else
				href += "&";
			
			href += queryString + "r=" + Math.random();
		}			
			
		reqObj.open(config.Method, href, config.Async)

		if(config.Method == "POST")
		{
			reqObj.setRequestHeader("Content-Type", "application/x-www-form-urlencoded");
		}
		reqObj.onreadystatechange = function() 
		{
			if(reqObj.readyState == 4)
			{		
				if(reqObj.status == 200)
				{	
					if(typeof objRef.OnResponse == "function")
					{
						objRef.ResponseText = reqObj.ResponseText;
						objRef.OnResponse(reqObj.ResponseText);
					}
				}
				else if(config.ThrowOnServerError) 
				{
					throw new Error("$AJAX error: " + reqObj.statusText + "\nStatus: " + reqObj.status + "\nError:\n" + reqObj.ResponseText);
				}
			}
		}
		if(config.Method == "POST")
			reqObj.send(queryString);
		else
			reqObj.send(null);
	}


}
/******************************************************************************/
/**************************************************************** EXTENDERS ***/
/******************************************************************************/
function DateFieldExtender(controlReference,settingsObject)
{
	// #region PUBLIC VARIABLES //
	
	this.Settings = 
		{
			DateFormat			: null,
			FieldHidden			: true,
			FieldReadonly		: true,
			ExtenderType		: "selects",
			YearOffset			: 5,
			YearEndOffset		: null,
			YearStartOffset		: null,
			ZeroPadding			: true,
			Default				:
				{
					Year		: null,
					Month		: null,
					Day			: null,
					Hour		: null,
					Minute		: null
				},
			DisplayTimeSelect	: true,
			DisplayDateSelect	: true,				
			DisplayFirstOptions	: false,
			FirstOptionText		:
				{
					Year		: "שנה",
					Month		: "חודש",
					Day			: "יום",
					Hour		: "שעה",
					Minute		: "דקה"
				}
		};	
	
	// #endregion PUBLIC VARIABLES //

	
	// #region PRIVATE VARIABLES //
	
	var fieldToExtend	= null,
		originalValue	= null,
		config			= this.Settings,
		container		= null,
		controls		= 
		{
			daySelect			: null,
			dayMonthDivider		: null,
			monthSelect			: null,
			monthDayDivider		: null,
			yearSelect			: null,		
			yearhourDivider		: null,
			hourSelect			: null,
			hourminuteDivider	: null,
			minuteSelect		: null
		};
		
	// #endregion PRIVATE VARIABLES //
 			
	(function init()
	{
		$E.onload(ctor);
	})();

	function ctor()
	{
		fieldToExtend = $(controlReference);
		
		if(!fieldToExtend) throw Error("Unable to extend control, invalid element refernce");
		
		originalValue = Date.parse(fieldToExtend.value) || null;
	
		$U.setSettings(settingsObject,config);
		var d = null;
		if(originalValue)
		{	
			d = new Date(originalValue);
		}
		else if(!config.DisplayFirstOptions)
		{
			d = new Date();
		}
	
		if(d)
		{
			if(config.Default.Year == null) config.Default.Year = d.getFullYear();
			if(config.Default.Month == null) config.Default.Month = d.getMonth()+1;
			if(config.Default.Day == null) config.Default.Day = d.getDate();
			if(config.Default.Hour == null) config.Default.Hour = d.getHours();
			if(config.Default.Minute == null) config.Default.Minute = d.getMinutes();		
		}
	
		if(!config.DateFormat)
		{
			config.DateFormat = "";
			if(config.DisplayDateSelect) config.DateFormat = "dd/mm/yyyy";
			if(config.DisplayTimeSelect)
			{
				if(config.DisplayDateSelect) config.DateFormat += " ";
				config.DateFormat += "hh:mi";
			}
		}
	
		if(config.FieldReadonly) fieldToExtend.readOnly = true;
		if(config.FieldHidden)	 fieldToExtend.style.display = "none";
		if(config.ExtenderType == "selects") selects_render();
	}
	
	function setFieldValue(newValue)
	{
		var d = Date.parse(newValue);

		if(d) fieldToExtend.value = new Date(d).render(config.DateFormat);
		else  fieldToExtend.value = "";
	}
	
	// #region SELECTS DISPLAY TYPE //
	
	function selects_render()
	{
		container = document.createElement("SPAN");
		container.dir = "ltr";
		container.style.direction = "ltr";
		
		if(config.DisplayDateSelect)
		{
			controls.daySelect		= container.appendChild(document.createElement("SELECT"));
			controls.dayMonthDivider= container.appendChild(document.createElement("SPAN"));
			controls.monthSelect	= container.appendChild(document.createElement("SELECT"));
			controls.monthDayDivider= container.appendChild(document.createElement("SPAN"));
			controls.yearSelect		= container.appendChild(document.createElement("SELECT"));
			
			controls.dayMonthDivider.innerHTML = "&nbsp;/&nbsp;";
			controls.monthDayDivider.innerHTML = "&nbsp;/&nbsp;";
			
			$E.add(controls.yearSelect,"change",selects_dateOnChange);
			$E.add(controls.monthSelect,"change",selects_dateOnChange);
			$E.add(controls.daySelect,"change",selects_dateOnChange);			
			
			var thisYear	= new Date().getFullYear(),
				startYear	= thisYear - (config.YearStartOffset != null ? config.YearStartOffset:config.YearOffset),
				endYear		= thisYear + (config.YearEndOffset != null ? config.YearEndOffset:config.YearOffset);

			if(config.DisplayFirstOptions)
			{
				$D.Select.addOption(controls.yearSelect,config.FirstOptionText.Year,"")
			}				
			for(var i = startYear; i <= endYear; i++)
			{
				$D.Select.addOption(controls.yearSelect,(config.ZeroPadding ? i.zeropad():i),i.zeropad())
				if(config.Default.Year == i)
					controls.yearSelect.options[controls.yearSelect.options.length-1].selected = true;
			}
			if(config.DisplayFirstOptions)
			{
				$D.Select.addOption(controls.monthSelect,config.FirstOptionText.Month,"")
			}				
			for(var i = 1; i <= 12; i++)
			{
				$D.Select.addOption(controls.monthSelect,(config.ZeroPadding ? i.zeropad():i),i.zeropad())
				if(config.Default.Month == i)	
					controls.monthSelect.options[controls.monthSelect.options.length-1].selected = true;
			}
			if(config.DisplayFirstOptions)
			{
				$D.Select.addOption(controls.daySelect,config.FirstOptionText.Day,"")
			}				
			for(var i = 1; i <= 31; i++)
			{
				$D.Select.addOption(controls.daySelect,(config.ZeroPadding ? i.zeropad():i),i.zeropad())
				if(config.Default.Day == i)	
					controls.daySelect.options[controls.daySelect.options.length-1].selected = true;
			}
		}
		if(config.DisplayTimeSelect)
		{
			if(config.DisplayDateSelect)
			{
				controls.yearhourDivider	= container.appendChild(document.createElement("SPAN"));
				controls.yearhourDivider.innerHTML		= "&nbsp;&nbsp;&nbsp;";
			}
			
			controls.hourSelect			= container.appendChild(document.createElement("SELECT"));
			controls.hourminuteDivider	= container.appendChild(document.createElement("SPAN"));
			controls.minuteSelect		= container.appendChild(document.createElement("SELECT"));
			
			controls.hourminuteDivider.innerHTML	= "&nbsp;:&nbsp;";

			$E.add(controls.hourSelect,"change",selects_timeOnChange);
			$E.add(controls.minuteSelect,"change",selects_timeOnChange);

			if(config.DisplayFirstOptions)
			{
				$D.Select.addOption(controls.hourSelect,config.FirstOptionText.Hour,"")
			}				
			for(var i = 0; i <= 23; i++)
			{
				$D.Select.addOption(controls.hourSelect,(config.ZeroPadding ? i.zeropad():i),i.zeropad())
				if(config.Default.Hour == i)	
					controls.hourSelect.options[controls.hourSelect.options.length-1].selected = true;
			}
			if(config.DisplayFirstOptions)
			{
				$D.Select.addOption(controls.minuteSelect,config.FirstOptionText.Minute,"")
			}				
			for(var i = 0; i <= 59; i++)
			{
				$D.Select.addOption(controls.minuteSelect,(config.ZeroPadding ? i.zeropad():i),i.zeropad())
				if(config.Default.Minute == i)	
					controls.minuteSelect.options[controls.minuteSelect.options.length-1].selected = true;
			}
		}		
		fieldToExtend.parentNode.insertBefore(container,fieldToExtend);
		setFieldValue(selects_getValue());
	}
	function selects_dateOnChange()
	{
		var y				= parseInt(controls.yearSelect.value,10),
			m				= parseInt(controls.monthSelect.value,10),
			d				= parseInt(controls.daySelect.value,10),
			optionsOffset	= config.DisplayFirstOptions ? 1:0,
			daysnum			= Date.getDaysInMonth(m,y);
		
		if(controls.daySelect.options.length - optionsOffset > daysnum)
		{
			controls.daySelect.options.length = daysnum + optionsOffset;
		}
		else if(controls.daySelect.options.length - optionsOffset  < daysnum)	
		{
			for(var i=parseInt(controls.daySelect.options[controls.daySelect.options.length -1].value,10) + 1; i <= daysnum; i++)
			{
				$D.Select.addOption(controls.daySelect,(config.ZeroPadding ? i.zeropad():i),i.zeropad());
			}
		}	
		setFieldValue(selects_getValue());
	}
	function selects_timeOnChange()
	{
		setFieldValue(selects_getValue());
	}
	function selects_getValue()
	{
		var value = "";
		
		if(config.DisplayDateSelect)
		{
			value = controls.yearSelect.value
					+ "/"
					+ controls.monthSelect.value
					+ "/"
					+ controls.daySelect.value;
		}
		if(config.DisplayTimeSelect)
		{
			value += " " + controls.hourSelect.value
					+ ":" 
					+ controls.minuteSelect.value;
		}
		return value;
	}
	// #endregion SELECTS DISPLAY TYPE //	
}	

function ScrollerExtender(controlReference,settingsObject)
{ 
	// #region PUBLIC VARIABLES //

	this.Settings = 
		{
			Direction		: "up",
			MouseOverStop	: true, 
			MouseOverScroll	: false, 
			InitialDelay	: 10,
			Speed			: 10
		}
		
	// #endregion PUBLIC VARIABLES //
	
	// #region PRIVATE VARIABLES //

	var config				= this.Settings,
		member				= null,
		elementToExtend		= null,
		scrollContentFirst	= null,
		scrollContentSecond	= null,
		scrollContentSize	= 0,
		visibleScrollSize	= 0,	
		members =
		{
			down:
			{
				coefficient		: -1,
				scrollObject	: "scrollTop",
				scrollSizeObject: "scrollHeight",
				offsetSizeObject: "offsetHeight",
				hiddehOverflow	: "overflowX",
				scrollResetValue: 1000000
			},
			up:
			{
				coefficient		: 1,
				scrollObject	: "scrollTop",
				scrollSizeObject: "scrollHeight",
				offsetSizeObject: "offsetHeight",
				hiddehOverflow	: "overflowX",
				scrollResetValue: 0
			},
			right:
			{
				coefficient		: -1,
				scrollObject	: "scrollLeft",
				scrollSizeObject: "scrollWidth",
				offsetSizeObject: "offsetWidth",
				hiddehOverflow	: "overflowY",
				scrollResetValue: 1000000
			},
			left:
			{
				coefficient		: 1,
				scrollObject	: "scrollLeft",
				scrollSizeObject: "scrollWidth",
				offsetSizeObject: "offsetWidth",
				hiddehOverflow	: "overflowY",
				scrollResetValue: 0
			}
		};

	// #endregion PRIVATE VARIABLES //

	(function init()
	{
		$E.onload(ctor);
	})();
	
	function ctor()
	{
		elementToExtend = $(controlReference);
		
		if(!elementToExtend) throw Error("Unable to extend control, invalid element refernce");
				
		$U.setSettings(settingsObject,config);
		
		member = members[config.Direction];
		
		elementToExtend.style.width 	= (parseInt($D.GetStyle(elementToExtend, "width")) || elementToExtend.offsetWidth) + "px";
		elementToExtend.style.height 	= (parseInt($D.GetStyle(elementToExtend, "hidth")) || elementToExtend.offsetHeight) + "px";
		
		var scrollContentHTML = elementToExtend.innerHTML;
		
		elementToExtend.innerHTML = "";
		scrollContentFirst = elementToExtend.appendChild(document.body.appendChild(document.createElement("DIV")));
		scrollContentFirst.innerHTML =  scrollContentHTML;
		scrollContentSize = scrollContentFirst[member.offsetSizeObject];
		visibleScrollSize	= elementToExtend[member.offsetSizeObject];
		
		var	numScrollContentRepeations = Math.ceil(visibleScrollSize/scrollContentSize);	
		var content = [];
		for(var i=-1; i <= numScrollContentRepeations; i++)
		{
			content.push(scrollContentHTML);
		}
				
		scrollContentFirst.innerHTML =  content.join("");
		scrollContentFirst.style.height = elementToExtend.style.height;
		scrollContentFirst.style.overflow = "hidden";
	
		scrollContentSecond = elementToExtend.appendChild(scrollContentFirst.cloneNode(true));
		scrollContentSecond.style.display = "none";

		scrollContentFirst.otherScrollContent = scrollContentSecond;
		scrollContentSecond.otherScrollContent = scrollContentFirst;
	
		scrollContentFirst[member.scrollObject] = member.scrollResetValue;
		scrollContentSecond[member.scrollObject] = member.scrollResetValue;

		
		if(config.MouseOverStop)
		{
			$E.add(scrollContentFirst, "mousemove", stopScrollOn);
			$E.add(scrollContentFirst, "mouseout", doScrollOn);
			$E.add(scrollContentSecond, "mousemove", stopScrollOn);
			$E.add(scrollContentSecond, "mouseout", doScrollOn);
		}
		
		setTimeout(function(){doScroll(scrollContentFirst);},config.InitialDelay);
	}
	function doScroll(currentScrollContent)
	{	
		clearInterval(currentScrollContent.$timer);
		
		currentScrollContent.$timer = setInterval
		(
			function()
			{
  				currentScrollContent[member.scrollObject] = currentScrollContent[member.scrollObject] + member.coefficient;
  				if(
  					((config.Direction == "up" || config.Direction == "left") && currentScrollContent[member.scrollObject] > scrollContentSize)
  					||
  					((config.Direction == "down" || config.Direction == "right") &&  currentScrollContent[member.scrollSizeObject] - currentScrollContent[member.scrollObject] - visibleScrollSize > scrollContentSize)
  				)
  				{
  					clearInterval(currentScrollContent.$timer);
  					currentScrollContent[member.scrollObject] = member.scrollResetValue;
  					currentScrollContent.style.display = "none";
  					currentScrollContent.otherScrollContent.style.display = "block";
  					doScroll(currentScrollContent.otherScrollContent);
  				}
			}
			,150 / config.Speed
		);
	}	
	function doScrollOn(e,objRef)
	{
		doScroll(objRef);
		objRef.style.overflow = "hidden";
	}
	function stopScrollOn(e,objRef)
	{
		if(objRef.$timer) clearInterval(objRef.$timer);
		if(config.MouseOverScroll)
		{
			objRef.style.overflow = "auto";
			objRef.style[member.hiddenOverflow] = "hidden";
		}
	}
}
function TimeCounterExtender(controlReference,propertyName,settingsObject)
{
	// #region PUBLIC VARIABLES //
	this.Settings = 
		{
			DisplayTemplate : "hh:mi:ss"
		};	
	// #endregion PUBLIC VARIABLES //

	
	// #region PRIVATE VARIABLES //
	
	var elementToExtend	= null,
		originalValue	= null,
		date			= new Date(),
		config			= this.Settings;
		
	// #endregion PRIVATE VARIABLES //
	
 			
	(function init()
	{
		$E.onload(ctor);
	})();
	
	function ctor()
	{
		elementToExtend = $(controlReference);
		if(!elementToExtend) throw Error("Unable to extend control, invalid element refernce");
		if(typeof elementToExtend[propertyName] == "undefined") throw Error("Unable to extend control, invalid property name");
		
		$U.setSettings(settingsObject,config);
				
		originalValue = (elementToExtend[propertyName] || "").trim();
		
		if(/^(\d?\d):(\d?\d)(:(\d?\d))?$/gi.test(originalValue))
		{
			date.setHours(RegExp.$1);
			date.setMinutes(RegExp.$2);
			date.setSeconds(RegExp.$4 || 0);
		}	
		
		elementToExtend.$timer = setTimeout(function(){render();},1000);
		
		function render()
		{
			clearTimeout(elementToExtend.$timer);
			date.setSeconds(date.getSeconds()+1);
  			elementToExtend[propertyName] = date.render(config.DisplayTemplate);
  			setTimeout(function(){render();},1000)
		}
	}
}
function CheckboxStatusExtender(controlReference,settingsObject)
{
	// #region PUBLIC VARIABLES //
	this.Settings = 
		{
			HrefFormat			: "/Admin/Events/SetStatus.ashx?eventId={0}&isActive={1}",
			DisableOnRequest	: true,
			ParameterFormat		: "truefalse" //truefalse, yesno, onoff, numeric
		};	
	// #endregion PUBLIC VARIABLES //

	
	// #region PRIVATE VARIABLES //
	
	var elementToExtend		= null,
		config				= this.Settings,
		parameterFormater	= 
		{
			numeric		: {"true":1,"false":0},
			truefalse	: {"true":"true","false":"false"},
			yesno		: {"true":"yes","false":"no"},
			onoff		: {"true":"on","false":"off"}
		};
		
	// #endregion PRIVATE VARIABLES //
	
	(function ctor()
	{
		elementToExtend = $(controlReference);
		if(!elementToExtend) throw Error("Unable to extend control, invalid element refernce");
		if(elementToExtend.tagName.toLowerCase() != "input" || elementToExtend.type.toLowerCase() != "checkbox")  throw Error("Unable to extend control, element must be Input - Type Checkbox'");
		
		$U.setSettings(settingsObject,config);
		
		$E.add(elementToExtend, "click", setStatus);
	})();
	
	function setStatus(e,objRef)
	{
		elementToExtend.disabled = config.DisableOnRequest;
		
		var href = config.HrefFormat;	
		href = href.replace(/\{0\}/gi,elementToExtend.value);
		href = href.replace(/\{1\}/gi,parameterFormater[config.ParameterFormat][elementToExtend.checked.toString()]);

		var ajax = new AjaxHandler(href,setStatusCallback,{ThrowOnServerError:true});
		ajax.execute();
	}
	
	function setStatusCallback(response)
	{
		elementToExtend.disabled = false;
	}
}