/////////////////////////////////
// Built in Date Class upgrade //
// * this code comes first     //
/////////////////////////////////

Date.isLeapYear=function(year) {
	return (((year % 4 == 0) && (year % 100 != 0)) || (year % 400 == 0)) ? true:false;
}

Date.prototype.isLeapYear=function() {
	var year=this.getFullYear();
	return (((year % 4 == 0) && (year % 100 != 0)) || (year % 400 == 0)) ? true:false;
}

Date.prototype.getNumOfDaysInMonth=function() {
	var numOfDaysInMonthArray=new Array(31,28,31,30,31,30,31,31,30,31,30,31);
	var currentMonth=this.getMonth();	
	if (currentMonth!=1 || (currentMonth==1 && !this.isLeapYear())) {
		return numOfDaysInMonthArray[currentMonth];
	} else {
		return 29;
	}
}


function implementsInterface(obj) {
	var prototypeObj={};
	for (var i=0; i<arguments.length; i++) {
		for (var method in arguments[i]) {
			prototypeObj[method]=arguments[i][method];
		}	
	}
	return prototypeObj;
}

function addObjectMethods(targetClass, methodObject) {
	for (var method in methodObject) {
		targetClass.prototype[method]=methodObject[method];
	}
}

//////////////////////////
// Interface Observable //
//////////////////////////

Observable = {
	addListener : function(listenerObj) {
		if (typeof this.listeners == 'undefined') {
			this.listeners=[];
		}
		for (var i=0; i<this.listeners.length; i++) {
			if (this.listeners[i]==listenerObj) return;
		}
		this.listeners[this.listeners.length]=listenerObj;
	},

	removeListener : function(listenerObj) {
		for (var i=0; i<this.listeners.length; i++) {
			if (this.listeners[i]==listenerObj) {
				this.listeners.splice(i,1);
				return;
			}
		}
	},
	
	notifyListeners : function (eventName,eventObj) {
		if (typeof this.listeners == 'undefined') return;
		for (var i=0; i< this.listeners.length; i++) {
			if (typeof this.listeners[i][eventName]!="undefined") {
				this.listeners[i][eventName](eventObj);
			}
		}
	}
};

function DOMEventHandle(element, type, handler) {
	this.element=element;
	this.type=type;
	this.handler=handler;
}

DOMEvent = {	

	// public
	
	addDomListener: function (element, type, handler) {
		var handlers;
		if (!handler.__id__) handler.__id__ = DOMEvent.currentId++;
		if (!element.events) element.events = {};
		handlers = element.events[type];
		if (!handlers) {
    		handlers = element.events[type] = {};
		    if (element["on" + type]) {
      			handlers[0] = element["on" + type];
    		}
  		}
		handlers[handler.__id__] = handler;
		element["on" + type] = DOMEvent.handleEvent;
		return new DOMEventHandle(element, type, handler);
	},
	
	removeListener: function (domEventHandleObj) {
		var element,type,handler;
		element=domEventHandleObj.element;
		type=domEventHandleObj.type;
		handler=domEventHandleObj.handler;
		if (element.events && element.events[type]) {
   			delete element.events[type][handler.__id__];
  		}
	},
	
	preventDefault: function (eventObj) {
		if (eventObj.preventDefault) {
			eventObj.preventDefault();
		} else {
			eventObj.returnValue=false;
		}
	},
	
	stopPropagation: function (eventObj) {
		if (eventObj.stopPropagation) {
			eventObj.stopPropagation();
		} else {
			eventObj.cancelBubble=true;
		}
	},
	
	// private
	
	currentId: 1,
	
	handleEvent: function (event) {
  		var handlers;
		event = event || window.event;
  		handlers = this.events[event.type];
  		for (var i in handlers) {
    		this.__handleEvent = handlers[i];
    		this.__handleEvent(event);
  		}
		this.__handleEvent=null;
	}
};

DHTMLApi = {
	
	CSS : {
		getStyle: function (element, name) {
			var styleObj;
			if (element.style[name]) return element.style[name];
			if (element.currentStyle) {	
				name=name.replace(/-([a-z])/g, function (matched) {
					return matched.toUpperCase().slice(1, matched.length);
				});
				return element.currentStyle[name];
			}
			if (document.defaultView && document.defaultView.getComputedStyle) {
				name=name.replace(/([A-Z])/g,"-$1");
				name=name.toLowerCase();
				styleObj=document.defaultView.getComputedStyle(element,"");
				return styleObj && styleObj.getPropertyValue(name);
			} else {
				return null;
			}
		},
		
		setProperties: function (element, properties) {
			var oldProperties={};
			for (var i in properties) {
				oldProperties[i]=element.style[i];
				element.style[i]=properties[i];
			}
			return oldProperties;
		},
		
		setClass:function (element,addClassesArray,removeClassesArray) {
			var currentClasses=new Array();
			var newClasses=new Array();
			var removedClasses=new Array();
			findWordsExp=new RegExp("\\w+", "g");
			var result;
			while ((result= findWordsExp.exec(element.className))!= null) currentClasses.push(result[0]); 
			for (var i=0; i<addClassesArray.length; i++) {
				var classExists=false;
				for (var j=0; j<currentClasses.length; j++) {
					if (currentClasses[j]==addClassesArray[i]) {
						classExists=true;
						break;
					}					
				}
				if (!classExists) newClasses.push(addClassesArray[i]);
			}
			currentClasses=currentClasses.concat(newClasses);
			if (removeClassesArray==null) return removedClasses;
			for (var i=0; i<removeClassesArray.length; i++) {
				for (var j=0; j<currentClasses.length; j++) {
					if (currentClasses[j]==removeClassesArray[i]) {
						removedClasses=removedClasses.concat(currentClasses.splice(j,1));
						break;
					}					
				}
			}
			element.className=currentClasses.join(" ");
			return removedClasses;
		}
	},
	
	Position : {
		getXPosOnPage: function (element) {
			return element.offsetParent?element.offsetLeft+DHTMLApi.Position.getXPosOnPage(element.offsetParent):element.offsetLeft;
		},
		
		getYPosOnPage: function (element) {
			return element.offsetParent?element.offsetTop+DHTMLApi.Position.getYPosOnPage(element.offsetParent):element.offsetTop;
		},
		
		getXPosInElement: function (element,container) {
			return DHTMLApi.Position.getXPosOnPage(element)-DHTMLApi.Position.getXPosOnPage(container);
		},
		
		getYPosInElement: function (element,container) {
			return DHTMLApi.Position.getYPosOnPage(element)-DHTMLApi.Position.getYPosOnPage(container);
		},
		
		setXPosOnPage: function (element,posX) {
			var propertiesArray={};
			if (element.parentNode!=document.body) {
				element=element.parentNode.removeChild(element);
				document.body.appendChild(element);
			}
			if (DHTMLApi.CSS.getStyle(element,"position")!="absolute") {
				propertiesArray={position: "absolute"};
			}
			propertiesArray.left=posX+"px";
			DHTMLApi.CSS.setProperties(element,propertiesArray);
		},
		
		setYPosOnPage: function (element,posY) {
			var propertiesArray={};
			if (element.parentNode!=document.body) {
				element=element.parentNode.removeChild(element);
				document.body.appendChild(element);
			}
			if (DHTMLApi.CSS.getStyle(element,"position")!="absolute") {
				propertiesArray={position: "absolute"};
			}
			propertiesArray.top=posY+"px";
			DHTMLApi.CSS.setProperties(element,propertiesArray);
		},
		
		setXPos: function (element, posX, relativeToElement) {
			if (relativeToElement==undefined) {
				element.style.left=posX+"px";
			} else {
				if(DHTMLApi.CSS.getStyle(element.parentNode,"position")=="static"){
					element.parentNode.style.position="relative";
				}
				element.style.position="absolute";
				element.style.left=(posX-DHTMLApi.Position.getXPosInElement(element.parentNode,relativeToElement))+"px";
			}
		},
		
		setYPos: function (element, posY, relativeToElement) {
			if (relativeToElement==undefined) {
				element.style.top=posY+"px";
			} else {
				if(DHTMLApi.CSS.getStyle(element.parentNode,"position")=="static"){
					element.parentNode.style.position="relative";
				}
				element.style.position="absolute";
				element.style.top=(posY-DHTMLApi.Position.getYPosInElement(element.parentNode,relativeToElement))+"px";
			}
		}
		
	},
	
	Size : { 
		
		getElementWidth : function (element) {
			var tempProperties, width;
			if (DHTMLApi.CSS.getStyle(element, "display" ) != "none") {
				return element.offsetWidth || parseInt(DHTMLApi.CSS.getStyle(element, "width"));
			}
			tempProperties=DHTMLApi.CSS.setProperties(element, {display: "block", visibility: "hidden", position: "absolute"});
			width=element.clientWidth || parseInt(DHTMLApi.CSS.getStyle(element, "width"));
			DHTMLApi.CSS.setProperties(element, {display: "", visibility: "", position: ""});
			DHTMLApi.CSS.setProperties(element,tempProperties);
			return width;		
		},
		
		getElementHeight : function (element) {
			var tempProperties, height;
			if (DHTMLApi.CSS.getStyle(element, "display" ) != "none") {
				return element.offsetHeight || parseInt(DHTMLApi.CSS.getStyle(element, "height"));
			}
			tempProperties=DHTMLApi.CSS.setProperties(element, {display: "block", visibility: "hidden", position: "absolute"});
			height=element.clientHeight || parseInt(DHTMLApi.CSS.getStyle(element, "height"));
			DHTMLApi.CSS.setProperties(element, {display: "", visibility: "", position: ""});
			DHTMLApi.CSS.setProperties(element,tempProperties);
			return height;
		},
		
		getPageWidth: function () {
			return Math.max(document.body.scrollWidth,document.body.offsetWidth);
		},
		
		getPageHeight: function () {
			var height=(typeof document.documentElement != "undefined" && typeof document.documentElement.offsetHeight != "undefined") ? document.documentElement.offsetHeight : 0;
			return Math.max(document.body.scrollHeight,document.body.offsetHeight,height);
		}
	
	},
	
	Visibility: {
		
		show: function (element) {
			element.style.display=element.__display__ || 'block';
		},
		
		hide: function (element) {
			var currentDisplay=DHTMLApi.CSS.getStyle(element,"display");
			if (currentDisplay != 'none') element.__display__=currentDisplay;
			element.style.display='none';
		},
		
		setOpacity: function (element,percent) {
			if (element.filters) {	
				element.style.filter='alpha(opacity='+percent+')';
				if (percent==100) {
					element.style.filter='none';
				}
			} else {
				element.style.opacity=percent/100;
			}
		}
		
	},
	
	Browser : {
		
		getViewportWidth: function () {
			return self.innerWidth || (document.documentElement && document.documentElement.clientWidth) || document.body.clientWidth;
		},
		
		getViewportHeight: function () {
			return self.innerHeight || (document.documentElement && document.documentElement.clientHeight) || document.body.clientHeight;
		},
		
		getScrollX: function () {
			return self.pageXOffset || (document.documentElement && document.documentElement.scrollLeft) || document.body.scrollLeft;
		},
		
		getScrollY: function () {
			return self.pageYOffset || (document.documentElement && document.documentElement.scrollTop) || document.body.scrollTop;
		}
		
	}
};

MousePositionOnPage = {
	getX: function (mouseEvent) {
		return mouseEvent.pageX || mouseEvent.clientX+DHTMLApi.Browser.getScrollX();
	},
	getY: function (mouseEvent) {
		return mouseEvent.pageY || mouseEvent.clientY+DHTMLApi.Browser.getScrollY();
	}
};

Utopia={};
Utopia.Form={};

/////////////////////////////////
// class Utopia.Form.Validator //
/////////////////////////////////

/*
formFields = {required: [id1, id2, ...], email: [id1, id2, ...], numeric: [id1, id2, ...], confirm: [[id1, id1a,...],[id2, id2a,...],]}
errorMessages = {required: string, email: string, numeric: string, confirm: string}
cssStyles = {invalidEntryField : string}
ajaxValidator - Utopia.Form.AjaxValidator interface
*/

Utopia.Form.Validator = function (formElement,errorMsgContainerDiv,submitButtonElement,formFields,cssStyles,errorMessages,onSubmitSuccess,onSubmitUnsuccess,ajaxValidator) {
	this.formElement=formElement;
	this.errorMsgContainerDiv=errorMsgContainerDiv;
	this.cssStyles=cssStyles;
	if (typeof formFields.required !="undefined") {
		this.requiredFields=this.getElementsById(formFields.required);
	} else {
		this.requiredFields={};
	}
	if (typeof formFields.email !="undefined") {
		this.emailFields=this.getElementsById(formFields.email);
	} else {
		this.emailFields={};
	}
	if (typeof formFields.numeric !="undefined") {
		this.numericFields=this.getElementsById(formFields.numeric);
	} else {
		this.numericFields={};
	}
	this.onSubmitSuccess=(typeof onSubmitSuccess !="undefined") ? onSubmitSuccess : null;
	this.onSubmitUnsuccess=(typeof onSubmitUnsuccess !="undefined") ? onSubmitUnsuccess : null;
	this.ajaxValidator=(typeof ajaxValidator !="undefined") ? ajaxValidator : null;
	this.confirmFields=[];
	if (typeof formFields.confirm !="undefined") {
		for (var i=0; i<formFields.confirm.length; i++) {
			if (formFields.confirm[i].length>1) {
				this.confirmFields[i]=this.getElementsById(formFields.confirm[i]);
			}
		}
	}
	this.submitButtonElement=submitButtonElement;
	this.errorMessages=errorMessages;
	this.init();
}

Utopia.Form.Validator.prototype.init=function () {
	var obj=this;
	DOMEvent.addDomListener(this.submitButtonElement,"click",function (eventObj) {
		DOMEvent.preventDefault(eventObj);
		obj.submit();
	});
	
	DOMEvent.addDomListener(this.formElement,"submit", function (eventObj) {
		DOMEvent.preventDefault(eventObj);
		obj.submit();
	});
	
};

/* validatorFunction - returns false if ok, or error string 
   validatorFunctionParameters - object
*/

Utopia.Form.Validator.prototype.addCustomValidator=function (validatorFunction,validatorFunctionParameters) {
	this.customValidator=validatorFunction;
	this.customValidatorParameters=validatorFunctionParameters;
}

Utopia.Form.Validator.prototype.getElementsById=function (elementIdArray) {
	var elements={};
	for (var i=0; i<elementIdArray.length; i++) {
		elements[elementIdArray[i]]=document.getElementById(elementIdArray[i]);
	}
	return elements;
};

Utopia.Form.Validator.prototype.checkRequiredField=function(inputElement) {
	var radioButtonMenuItems,isRadioButtonMenuSelected;
	//alert(tinyMCE.getInstanceById('rta1').getContent());
	// input field
	if (typeof inputElement.value !="undefined") {
		return !((inputElement.value.search(/\w/)==-1) ? true : false);
	} else {
		radioButtonMenuItems=inputElement.getElementsByTagName("INPUT");
		if (radioButtonMenuItems.length!=0) {
			for (i=0; i<radioButtonMenuItems.length; i++) {
				if (radioButtonMenuItems[i].checked) return true;
			}
			return false;
		}
		
	}
	
	return false;
};

Utopia.Form.Validator.prototype.checkEmailField=function(inputElement) {
	return (inputElement.value!="" && inputElement.value.search(/^[A-Z0-9._%+-]+@[A-Z0-9.-]+\.[A-Z]{2,6}$/i)==-1) ? false : true;
};

Utopia.Form.Validator.prototype.checkNumericField=function(inputElement) {
	return (inputElement.value!="" && inputElement.value.search(/^[-+]?[0-9]*\.?[0-9]+$/)==-1) ? false : true;
};

Utopia.Form.Validator.prototype.checkConfirmField=function(inputElementObject) {
	var value;
	for (var id in inputElementObject) {
		value=inputElementObject[id].value;
		break;
	}
	for (var id in inputElementObject) {
		if (value!=inputElementObject[id].value) return false;
	}
	return true;
};

Utopia.Form.Validator.prototype.checkFields=function (inputFieldsObject,checkFunction) {
	var isOK=true;
	for (var id in inputFieldsObject) {
		if (checkFunction(inputFieldsObject[id])) {
			this.markFieldOK(inputFieldsObject[id]);
		} else {
			this.markFieldBad(inputFieldsObject[id]);
			isOK=false;
		}
	}
	return isOK;
};

Utopia.Form.Validator.prototype.markFieldOK=function (inputField) {
	DHTMLApi.CSS.setClass(inputField,[],new Array(this.cssStyles.invalidEntryField));
};

Utopia.Form.Validator.prototype.markFieldBad=function (inputField) {
	DHTMLApi.CSS.setClass(inputField,new Array(this.cssStyles.invalidEntryField),[]);
};

Utopia.Form.Validator.prototype.checkRequiredFields=function() {
	var okInput=this.checkFields(this.requiredFields,this.checkRequiredField);	
	if (!okInput) {
		this.displayErrorMessage(this.errorMessages.required);
		return false;
	} else {
		this.clearErrorMessage();
		return true;
	}
};

Utopia.Form.Validator.prototype.checkEmailFields=function() {
	var okInput=this.checkFields(this.emailFields,this.checkEmailField);	
	if (!okInput) {
		this.displayErrorMessage(this.errorMessages.email);
		return false;
	} else {
		this.clearErrorMessage();
		return true;
	}
};

Utopia.Form.Validator.prototype.checkNumericFields=function() {
	var okInput=this.checkFields(this.numericFields,this.checkNumericField);	
	if (!okInput) {
		this.displayErrorMessage(this.errorMessages.numeric);
		return false;
	} else {
		this.clearErrorMessage();
		return true;
	}
};

Utopia.Form.Validator.prototype.checkConfirmFields=function() {
	var okInput;
	for (var i=0; i<this.confirmFields.length; i++) {
		for (var id in this.confirmFields[i]) this.markFieldOK(this.confirmFields[i][id]);
	}
	this.clearErrorMessage();
	for (var i=0; i<this.confirmFields.length; i++) {
		okInput=this.checkConfirmField(this.confirmFields[i]);
		if (okInput===false) {
			for (var id in this.confirmFields[i]) this.markFieldBad(this.confirmFields[i][id]);
			this.displayErrorMessage(this.errorMessages.confirm);
			return false;
		} 
	}
};

Utopia.Form.Validator.prototype.displayErrorMessage=function(errorString) {
	DHTMLApi.Visibility.show(this.errorMsgContainerDiv);
	this.errorMsgContainerDiv.innerHTML=errorString;
};

Utopia.Form.Validator.prototype.clearErrorMessage=function () {
	this.errorMsgContainerDiv.innerHTML="";
};

Utopia.Form.Validator.prototype.check=function() {
	if (this.checkRequiredFields()===false) {
		return false;
	}
	if (this.checkConfirmFields()===false) {
		return false;
	}
	if (this.checkEmailFields()===false) {
		return false;
	}
	if (this.checkNumericFields()===false) {
		return false;
	}
	if (typeof this.customValidator!="undefined") {
		var customValidatorResult=this.customValidator(this.customValidatorParameters);
		if (customValidatorResult!==false) {
			this.displayErrorMessage(customValidatorResult);
			return false;
		}
	}
	return true;
};

Utopia.Form.Validator.prototype.submit=function() {
	var interval;
	var obj=this;
	DHTMLApi.CSS.setProperties(this.errorMsgContainerDiv, {display: "none"});
	if (this.check()) {
		if (this.ajaxValidator===null) {
			if (this.onSubmitSuccess!==null) {
				(this.onSubmitSuccess)();
			} 
			this.formElement.submit();
		} else {
			this.ajaxValidator.check();
			interval=window.setInterval(function () {
				if (obj.ajaxValidator.getResult()!==null) {
					window.clearInterval(interval);
					if (obj.ajaxValidator.getResult()===false) {
						if (obj.onSubmitSuccess!==null) {
							(obj.onSubmitSuccess)();
						} 
						obj.formElement.submit();
					} else {
						obj.displayErrorMessage(obj.ajaxValidator.getResult());
						if (obj.onSubmitUnsuccess!==null) {
							(obj.onSubmitUnsuccess)();
						}
					}
				}
			},100);
		}
	} else {
		if (this.onSubmitUnsuccess!==null) {
			(this.onSubmitUnsuccess)();
		}
	}
};

/////////////////////////////////////////
// interface Utopia.Form.AjaxValidator //
/////////////////////////////////////////

// this.error - null unchecked, false - no error, string - error 

Utopia.Form.AjaxValidator= {
	
	getResult: function () {
		return this.error;
	},
	check: function () {
		this.error=false;
	}	
}


//////////////////////////
// Class ImagePreloader //
//////////////////////////

/* broadcasts
	onImageLoad - event Object - img url string
	onAllImagesLoad + event Object - array of imgs url string
*/

function ImagePreloader(imgUrlArray) {
	this.imgUrlArray=imgUrlArray;
	this.imgPreloadingIndex=0;
	this.isPreloading=false;
	this.preloadInterval=null;
	this.imageIsPreloaded=false;
}

ImagePreloader.prototype=implementsInterface(Observable);

ImagePreloader.prototype.preload=function() {
	
	var obj=this;
	if (this.imgPreloadingIndex>=this.imgUrlArray.length) return; 
	this.preloadInterval=window.setInterval(function () {
		if (obj.imageIsPreloaded===false && obj.isPreloading==false) {
			obj.preloadImage(obj.imgPreloadingIndex);
			return;
		}
		if (obj.imgPreloadingIndex==(obj.imgUrlArray.length-1)) {
			window.clearInterval(obj.preloadInterval);
		} else {
			if (obj.imageIsPreloaded===true) {
				obj.imgPreloadingIndex++;
				obj.preloadImage(obj.imgPreloadingIndex);
			}
		}
													  
	}, 150);	
}

ImagePreloader.prototype.preloadImage=function (imageNum) {
	var obj=this;
	this.isPreloading=true;
	var img=new Image();
	this.imageIsPreloaded=false;
	img.onload=img.onerror=function () {
		obj.notifyListeners("onImageLoad",obj.imgUrlArray[obj.imgPreloadingIndex]);
		obj.imageIsPreloaded=true;
		if ((obj.imgUrlArray.length-1)==obj.imgPreloadingIndex) {
			obj.notifyListeners("onAllImagesLoad",obj.imgUrlArray);
		}
	}
	img.src=this.imgUrlArray[imageNum];
}

ImagePreloader.prototype.start=function () {
	this.preload();
}

ImagePreloader.prototype.stop=function () {
	this.isPreloading=false;
	this.imageIsPreloaded=false;
	if (this.preloadInterval!==null) {
		window.clearInterval(this.preloadInterval);
		this.preloadInterval=null;
	}
	return this.imgUrlArray.slice(this.imgPreloadingIndex+1);
}

///////////////////////////
// class SlidesPreloader //
///////////////////////////

/* 
data= [string filenames]
*/

// broadcasts onImageLoad(fileName)

function SlidesPreloader(data) {
	this.slidesCue=data;
	this.loadedSlides=[];
	this.preloader=null;
}

SlidesPreloader.prototype=implementsInterface(Observable);

SlidesPreloader.prototype.startPreload=function () {
	if (this.slidesCue.length==0) return;
	if (this.preloader != null && this.preloader.isPreloading) this.preloader.stop();
	this.preloader=new ImagePreloader(this.slidesCue);
	this.preloader.addListener(this);
	this.preloader.start();
}

SlidesPreloader.prototype.startPreloadSlide=function (imageFile) {
	var preloadsLeft;
	var slideCue=[];	
	if (this.isInArray(this.slidesCue,imageFile)===false) return;
	if (this.preloader !== null && this.preloader.isPreloading) this.preloader.stop();
	slideCue.push(imageFile);
	if (this.preloader !== null) {
		this.preloader.removeListener(this);
	}
	this.preloader=new ImagePreloader(slideCue);
	this.preloader.addListener(this);
	this.preloader.start();
}

SlidesPreloader.prototype.isLoaded=function (imageFile) {
	if (this.isInArray(this.loadedSlides,imageFile)) return true;
	return false;
}

SlidesPreloader.prototype.onImageLoad=function (imageFile) {
	this.firstSlidesCue=this.removeFromArray(this.slidesCue,imageFile);
	this.loadedSlides.push(imageFile);
	this.notifyListeners("onImageLoad",imageFile);
}

SlidesPreloader.prototype.removeFromArray=function (array,element) {
	var index=null;
	var newArray=[];
	for (var i=0; i<array.length; i++) {
		if (array[i]==element) {
			index=i;
			break;
		}
	}
	if (index!==null) {
		newArray=array.slice(0,index);
		newArray=newArray.concat(array.slice(index+1));
		return newArray;
	} else {
		return array;
	}
}

SlidesPreloader.prototype.isInArray=function (array,element) {
	for (var i=0; i<array.length; i++) {
		if (array[i]==element) return true;
	}
	return false;
}


///////////////////////
// Package Animation //
///////////////////////

Animation= new Object();

Animation.FRAME_RATE=50; // miliseconds

//////////////////////////
// Class Animation.Fade //
//////////////////////////

Animation.Fade=function (fadeObject, currentOpacityPercentage) {
	this.fadeObject=fadeObject;
	this.currentOpacityPercentage=currentOpacityPercentage;
	this.interval=null;
	this.targetOpacityPercentage=null;
	this.currentAnimationStep=null;
	this.numOfAnimationSteps=null;
	DHTMLApi.Visibility.setOpacity(this.fadeObject,Math.round(this.currentOpacityPercentage));
}

Animation.Fade.prototype=implementsInterface(Observable);

Animation.Fade.prototype.setFade=function (targetOpacityPercentage, numOfSteps) {
	this.stop();
	var animationObject=this;
	this.targetOpacityPercentage=targetOpacityPercentage;
	this.opacityStep=1.0*(targetOpacityPercentage-this.currentOpacityPercentage)/numOfSteps;
	this.numOfAnimationSteps=numOfSteps;
	this.currentAnimationStep=0;
	this.notifyListeners("onAnimationStart",null);
	this.animate();
	this.interval=window.setInterval(function() {animationObject.animate()},Animation.FRAME_RATE);
}

Animation.Fade.prototype.animate=function () {
	if (this.currentAnimationStep<this.numOfAnimationSteps) {
		this.currentOpacityPercentage+=this.opacityStep;
		DHTMLApi.Visibility.setOpacity(this.fadeObject,Math.round(this.currentOpacityPercentage));
		this.notifyListeners("onAnimationStep",this.currentAnimationStep);
		++this.currentAnimationStep;
		return this.numOfAnimationStep;
	} else {
		this.currentOpacityPercentage=this.targetOpacityPercentage;
		DHTMLApi.Visibility.setOpacity(this.fadeObject,Math.round(this.currentOpacityPercentage));
		this.notifyListeners("onAnimationStep",this.currentAnimationStep);
		window.clearInterval(this.interval);
		this.notifyListeners("onAnimationEnd",null);
		this.numOfAnimationStep=null;
		return false;
	}
}

Animation.Fade.prototype.stop=function() {
	if (this.interval!==null) {
		window.clearInterval(this.interval);
		this.notifyListeners("onAnimationEnd",null);
	}
}

/////////////////////////////////
// Class Animation.SmoothHMove //
/////////////////////////////////

Animation.SmoothHMove=function(movingObject, relativeToObject) {
	this.movingObject=movingObject;
	this.relativeToObject=relativeToObject;
	this.currentXPos=DHTMLApi.Position.getXPosInElement(movingObject,relativeToObject);
	this.targetXPos=null;
	this.interval=null;
	this.numOfAnimationStep=null;
}

Animation.SmoothHMove.prototype=implementsInterface(Observable);

Animation.SmoothHMove.prototype.setPosition=function (targetPosition) {
	if (this.interval!==null) {
		window.clearInterval(this.interval);
		this.notifyListeners("onAnimationEnd",null);
	}
	var animationObject=this;
	this.targetXPos=targetPosition;
	this.numOfAnimationStep=0;
	this.notifyListeners("onAnimationStart",null);
	this.animate();
	this.interval=window.setInterval(function() {animationObject.animate()},Animation.FRAME_RATE);
}

Animation.SmoothHMove.prototype.animate=function () {
	var stepDistance=(this.targetXPos-this.currentXPos)/3;
	if (Math.abs(stepDistance)>0.3) {
		this.currentXPos+=stepDistance;
		DHTMLApi.Position.setXPos(this.movingObject, this.currentXPos, this.relativeToObject);
		++this.numOfAnimationStep;
		this.notifyListeners("onAnimationStep",this.numOfAnimationSteps);
		return this.numOfAnimationStep;
	} else {
		this.currentXPos=this.targetXPos;
		DHTMLApi.Position.setXPos(this.movingObject, this.currentXPos, this.relativeToObject);
		this.notifyListeners("onAnimationStep",++this.numOfAnimationSteps);
		window.clearInterval(this.interval);
		this.notifyListeners("onAnimationEnd",null);
		this.numOfAnimationStep=null;
		return false;
	}
}

Animation.SmoothHMove.prototype.getAnimationStep=function () {
	return this.numOfAnimationStep;
}

Animation.SmoothHMove.prototype.stop=function() {
	if (this.interval!==null) {
		window.clearInterval(this.interval);
		this.notifyListeners("onAnimationEnd",null);
	}
}

/////////////////////////////////
// Class Animation.SmoothVMove //
/////////////////////////////////

Animation.SmoothVMove=function(movingObject, relativeToObject) {
	this.movingObject=movingObject;
	this.relativeToObject=relativeToObject;
	this.currentYPos=DHTMLApi.Position.getYPosInElement(movingObject,relativeToObject);
	this.targetYPos=null;
	this.interval=null;
	this.numOfAnimationStep=null;
}

Animation.SmoothVMove.prototype=implementsInterface(Observable);

Animation.SmoothVMove.prototype.setPosition=function (targetPosition) {
	if (this.interval!==null) {
		window.clearInterval(this.interval);
		this.notifyListeners("onAnimationEnd",null);
	}
	var animationObject=this;
	this.targetYPos=targetPosition;
	this.numOfAnimationStep=0;
	this.notifyListeners("onAnimationStart",null);
	this.animate();
	this.interval=window.setInterval(function() {animationObject.animate()},Animation.FRAME_RATE);
}

Animation.SmoothVMove.prototype.animate=function () {
	var stepDistance=(this.targetYPos-this.currentYPos)/3;
	if (Math.abs(stepDistance)>0.3) {
		this.currentYPos+=stepDistance;
		DHTMLApi.Position.setYPos(this.movingObject, this.currentYPos, this.relativeToObject);
		++this.numOfAnimationStep;
		this.notifyListeners("onAnimationStep",this.numOfAnimationSteps);
		return this.numOfAnimationStep;
	} else {
		this.currentYPos=this.targetYPos;
		DHTMLApi.Position.setYPos(this.movingObject, this.currentYPos, this.relativeToObject);
		this.notifyListeners("onAnimationStep",++this.numOfAnimationSteps);
		window.clearInterval(this.interval);
		this.notifyListeners("onAnimationEnd",null);
		this.numOfAnimationStep=null;
		return false;
	}
}

Animation.SmoothVMove.prototype.getAnimationStep=function () {
	return this.numOfAnimationStep;
}

Animation.SmoothVMove.prototype.stop=function() {
	if (this.interval!==null) {
		window.clearInterval(this.interval);
		this.notifyListeners("onAnimationEnd",null);
	}
}

///////////////////////////////////
// Class Animation.SmoothHResize //
///////////////////////////////////

Animation.SmoothHResize=function(resizeObject) {
	this.resizeObject=resizeObject;
	this.currentWidth=DHTMLApi.Size.getElementWidth(resizeObject);
	this.targetWidth=null;
	this.interval=null;
	this.numOfAnimationStep=null;
}

Animation.SmoothHResize.prototype=implementsInterface(Observable);

Animation.SmoothHResize.prototype.setSize=function (targetWidth) {
	if (this.interval!==null) {
		window.clearInterval(this.interval);
		this.notifyListeners("onAnimationEnd",null);
	}
	var animationObject=this;
	this.targetWidth=targetWidth;
	this.numOfAnimationStep=0;
	this.notifyListeners("onAnimationStart",null);
	this.animate();
	this.interval=window.setInterval(function() {animationObject.animate()},Animation.FRAME_RATE);
}

Animation.SmoothHResize.prototype.animate=function () {
	var stepWidth=(this.targetWidth-this.currentWidth)/3;
	if (Math.abs(stepWidth)>0.3) {
		this.currentWidth+=stepWidth;
		DHTMLApi.CSS.setProperties(this.resizeObject,{width: this.currentWidth+"px", overflow: "hidden"});
		++this.numOfAnimationStep;
		this.notifyListeners("onAnimationStep",this.numOfAnimationSteps);
		return this.numOfAnimationStep;
	} else {
		this.currentWidth=this.targetWidth;
		DHTMLApi.CSS.setProperties(this.resizeObject,{width: this.currentWidth+"px", overflow: "hidden"});
		this.notifyListeners("onAnimationStep",++this.numOfAnimationSteps);
		window.clearInterval(this.interval);
		this.notifyListeners("onAnimationEnd",null);
		this.numOfAnimationStep=null;
		return false;
	}
}

Animation.SmoothHResize.prototype.getAnimationStep=function () {
	return this.numOfAnimationStep;
}

Animation.SmoothHResize.prototype.stop=function() {
	if (this.interval!==null) {
		window.clearInterval(this.interval);
		this.notifyListeners("onAnimationEnd",null);
	}
}

///////////////////////////////////
// Class Animation.SmoothVResize //
///////////////////////////////////

Animation.SmoothVResize=function(resizeObject) {
	this.resizeObject=resizeObject;
	this.currentHeight=DHTMLApi.Size.getElementHeight(resizeObject);
	this.targetHeight=null;
	this.interval=null;
	this.numOfAnimationStep=null;
}

Animation.SmoothVResize.prototype=implementsInterface(Observable);

Animation.SmoothVResize.prototype.setSize=function (targetHeight) {
	if (this.interval!==null) {
		window.clearInterval(this.interval);
		this.notifyListeners("onAnimationEnd",null);
	}
	var animationObject=this;
	this.targetHeight=targetHeight;
	this.numOfAnimationStep=0;
	this.notifyListeners("onAnimationStart",null);
	this.animate();
	this.interval=window.setInterval(function() {animationObject.animate()},Animation.FRAME_RATE);
}

Animation.SmoothVResize.prototype.animate=function () {
	var stepHeight=(this.targetHeight-this.currentHeight)/3;
	if (Math.abs(stepHeight)>0.3) {
		this.currentHeight+=stepHeight;
		DHTMLApi.CSS.setProperties(this.resizeObject,{height: this.currentHeight+"px", overflow: "hidden"});
		++this.numOfAnimationStep;
		this.notifyListeners("onAnimationStep",this.numOfAnimationSteps);
		return this.numOfAnimationStep;
	} else {
		this.currentHeight=this.targetHeight;
		DHTMLApi.CSS.setProperties(this.resizeObject,{height: this.currentHeight+"px", overflow: "hidden"});
		this.notifyListeners("onAnimationStep",++this.numOfAnimationSteps);
		window.clearInterval(this.interval);
		this.notifyListeners("onAnimationEnd",null);
		this.numOfAnimationStep=null;
		return false;
	}
}

Animation.SmoothVResize.prototype.getAnimationStep=function () {
	return this.numOfAnimationStep;
}

Animation.SmoothVResize.prototype.stop=function() {
	if (this.interval!==null) {
		window.clearInterval(this.interval);
		this.notifyListeners("onAnimationEnd",null);
	}
}

/////////////////////////////
// Static Class PopUpLayer //
/////////////////////////////

PopUpLayer= {
	
	containerZIndex: 10000,
	
	init: function (popUpDivNode,backgroundCssClass,backgroundAlpha,closeButtonElement,onCloseCallback) {
		this.popUpDivNode=popUpDivNode;
		this.parentpopUpDivNode=popUpDivNode.parentNode;
		this.nextSiblingpopUpDivNode=popUpDivNode.nextSibling;
		this.popupContainerNode=null;
		this.backgroundNode=null;
		this.backgroundCssClass=backgroundCssClass;
		this.backgroundAlpha=backgroundAlpha;
		this.closeButtonElement=null;
		this.onCloseCallback=null;
		if (typeof closeButtonElement != "undefined") {
			this.closeButtonElement=closeButtonElement;
		}
		if (typeof onCloseCallback != "undefined") {
			this.onCloseCallback=onCloseCallback;
		}
		this.resizeHandler=null;
		this.closeHandler=null;
		this.closeButtonHandler=null;
		this.tempPopUpDivNodeStyles={position: DHTMLApi.CSS.getStyle(this.popUpDivNode, "position"), top: DHTMLApi.CSS.getStyle(this.popUpDivNode, "top"), left: DHTMLApi.CSS.getStyle(this.popUpDivNode, "left"), zIndex: DHTMLApi.CSS.getStyle(this.popUpDivNode, "z-index"), display: DHTMLApi.CSS.getStyle(this.popUpDivNode, "display")};
	},
	
	initHandlers: function () {
		var obj=this;
		this.resizeHandler=DOMEvent.addDomListener(window, "resize", function () {
			obj.centerOnPage();
		});
		this.closeHandler=DOMEvent.addDomListener(this.backgroundNode, "click", function () {
			obj.hide();
			if (obj.onCloseCallback!==null) (obj.onCloseCallback)();
		});
		if (this.closeButtonElement!==null) {
			this.closeButtonHandler=DOMEvent.addDomListener(this.closeButtonElement, "click", function () {
				obj.hide();
				if (obj.onCloseCallback!==null) (obj.onCloseCallback)();
			});
		}
	},
	
	removeHandlers: function () {
		DOMEvent.removeListener(this.resizeHandler);
		DOMEvent.removeListener(this.closeHandler);
		if (this.closeButtonHandler!==null) {
			DOMEvent.removeListener(this.closeButtonHandler);
		}
		this.resizeHandler=null;
		this.closeHandler=null;
		this.closeButtonHandler=null;
	},
	
	build: function () {
		var popUpNode;
		this.popupContainerNode=document.createElement("DIV");
		document.body.appendChild(this.popupContainerNode);
		DHTMLApi.CSS.setProperties(document.body,{overflow: "hidden"});
		DHTMLApi.CSS.setProperties(this.popupContainerNode,{position: "absolute", top: "0px", left: "0px", width: this.getPageWidth()+"px", height: this.getPageHeight()+"px", zIndex: this.containerZIndex, overflow:"hidden"});
		this.backgroundNode=document.createElement("DIV");
		this.popupContainerNode.appendChild(this.backgroundNode);
		DHTMLApi.CSS.setProperties(this.backgroundNode,{position: "absolute", top: "0px", left: "0px", zIndex: 1, cursor: "pointer", width: "100%", height: "100%"});
		DHTMLApi.CSS.setClass(this.backgroundNode,new Array(this.backgroundCssClass),new Array());
		
		popUpNode=this.parentpopUpDivNode.removeChild(this.popUpDivNode);
		this.popupContainerNode.appendChild(popUpNode);
		DHTMLApi.CSS.setProperties(popUpNode, {position: "absolute", zIndex: 2, display: "block"});
		DHTMLApi.Visibility.setOpacity(this.backgroundNode,this.backgroundAlpha);
		this.initHandlers();
	},
	
	restorePopUpNode: function() {
		if (this.nextSiblingpopUpDivNode!==null) {
			this.parentpopUpDivNode.insertBefore(this.popUpDivNode,this.nextSiblingpopUpDivNode);
		} else {
			this.parentpopUpDivNode.appendChild(this.popUpDivNode);
		}
		
		DHTMLApi.CSS.setProperties(this.popUpDivNode,this.tempPopUpDivNodeStyles);
	},
	
	centerOnPage: function (targetWidth,targetHeight) {
		var leftPos,topPos,elementWidth,elementHeight;
		elementWidth=(typeof targetWidth=="undefined") ? DHTMLApi.Size.getElementWidth(this.popUpDivNode) : targetWidth;
		elementHeight=(typeof targetHeight=="undefined") ? DHTMLApi.Size.getElementHeight(this.popUpDivNode) : targetHeight;
		leftPos=Math.round((DHTMLApi.Browser.getViewportWidth()-elementWidth)/2+DHTMLApi.Browser.getScrollX());
		topPos=Math.round((DHTMLApi.Browser.getViewportHeight()-elementHeight)/2+DHTMLApi.Browser.getScrollY());
		if (topPos+elementHeight>DHTMLApi.Size.getPageHeight()) {
			topPos=DHTMLApi.Size.getPageHeight()-elementHeight;
		}
		DHTMLApi.CSS.setProperties(this.popUpDivNode, {left: leftPos+"px", top: topPos+"px"});
		DHTMLApi.CSS.setProperties(this.popupContainerNode, {width: DHTMLApi.Browser.getViewportWidth()+"px", height: DHTMLApi.Size.getPageHeight()+"px"});
	},
	
	display: function (popUpDivNode,backgroundCssClass,backgroundAlpha,closeButtonElement,onCloseCallback) {
		this.init(popUpDivNode,backgroundCssClass,backgroundAlpha,closeButtonElement,onCloseCallback);
		this.build();
		this.centerOnPage();
	},
	
	hide: function () {
		this.removeHandlers();
		this.restorePopUpNode();
		document.body.removeChild(this.popupContainerNode);
		DHTMLApi.CSS.setProperties(document.body,{overflow: "auto"});
	},
	
	getPageHeight: function () {
		return DHTMLApi.Size.getPageHeight();
	},
	
	getPageWidth: function () {
		return DHTMLApi.Size.getPageWidth();
	}
	
}


Saponia={};

/*
elements={background_container: element, panel_container: element, more_button: element}
slides=[{background_image: string, link: string},]
css={control_button: string, selected_control_button: string}
*/

Saponia.MainCarousel=function (elements,slides,css) {
	this.elements=elements;
	this.slides=slides;
	this.css=css;
	this.backgroundImages=[];
	this.currentImageNum=0;
	this.currentBackgroundImage=null;
	this.controlButtons=[];
	this.fadeAnimation=null;
	this.controlPanelData={button_space: 10};
	this.numOfTransitionSteps=10;
	this.status=Saponia.MainCarousel.STATUS_IDLE;
	this.parseData();
	this.preloader=new SlidesPreloader(this.backgroundImages);
	this.preloader.startPreload();
	this.preloadingOnDemandFileName=null;
	this.moreButtonClickHandler=null;
	this.initialized=false;
	this.loopInterval=null;
	this.moreButton=null;
	this.build();
	this.init();
	this.slideClickHandler=null;
	this.displayBackground(this.backgroundImages[this.currentImageNum],100);
}

Saponia.MainCarousel.prototype=implementsInterface(Observable);

Saponia.MainCarousel.STATUS_IDLE=1;
Saponia.MainCarousel.STATUS_PRELOADING=2;
Saponia.MainCarousel.STATUS_FADE_OUT=3;
Saponia.MainCarousel.STATUS_FADE_IN=4;

Saponia.MainCarousel.prototype.parseData=function () {
	for (var i=0; i<this.slides.length; i++) {
		this.backgroundImages.push(this.slides[i].background_image);
	}
}

Saponia.MainCarousel.prototype.build=function () {
	if (this.backgroundImages.length>1) {
		for (var i=0; i<this.slides.length; i++) {
			var button=document.createElement("DIV");
			this.elements.panel_container.appendChild(button);
			DHTMLApi.CSS.setClass(button,[this.css.control_button],[]);
			if (i<(this.slides.length-1)) {
				DHTMLApi.CSS.setProperties(button,{styleFloat: "left", cssFloat: "left", marginRight: this.controlPanelData.button_space+"px"});
			} else {
				DHTMLApi.CSS.setProperties(button,{styleFloat: "left", cssFloat: "left"});
			}
			this.controlButtons.push(button);
		}
		var panelWidth=(this.slides.length*DHTMLApi.Size.getElementWidth(this.controlButtons[0])+(this.slides.length-1)*this.controlPanelData.button_space);
		DHTMLApi.CSS.setProperties(this.elements.panel_container,{width: panelWidth+"px"});
		this.setSelectedButton(this.currentImageNum);
	}
}

Saponia.MainCarousel.prototype.setSelectedButton=function (slideNum) {
	for (var i=0; i<this.controlButtons.length; i++) {
		if (i==slideNum) {
			DHTMLApi.CSS.setClass(this.controlButtons[i],[this.css.selected_control_button],[this.css.control_button]);
		} else {
			DHTMLApi.CSS.setClass(this.controlButtons[i],[this.css.control_button],[this.css.selected_control_button]);
		}
	}
}

Saponia.MainCarousel.prototype.init=function () {
	var obj=this;
	for (var i=0; i<this.controlButtons.length; i++) {
		(function () {
			var j=i;
			DOMEvent.addDomListener(obj.controlButtons[j],"click",function () {
				obj.stopLoop();
				if (j!=obj.currentImageNum) {
					obj.currentImageNum=j;
					obj.setSelectedButton(j);
					obj.showTransition(j);
				}
			});
		})();
	}
	
	
	DOMEvent.addDomListener(window,"resize",function () {
		if (obj.currentBackgroundImage!==null) {
			DHTMLApi.CSS.setProperties(obj.currentBackgroundImage, {position:"absolute", left: Math.round((DHTMLApi.Size.getElementWidth(obj.elements.background_container)-obj.currentBackgroundImage.width)/2)+"px", top: "0px"});
		}
	
	});
}

Saponia.MainCarousel.prototype.getBackgroundIndex=function (fileName) {
	for (var i=0; i<this.backgroundImages.length; i++) {
		if (this.backgroundImages[i].image==fileName) return i;
	}
	return false;
}

Saponia.MainCarousel.prototype.displayBackground=function(file,opacity) {
	var obj=this;
	var img=new Image();
	if (this.slideClickHandler!==null) {
		DOMEvent.removeListener(this.slideClickHandler);
	}
	img.onload=function () {
		obj.elements.background_container.innerHTML="";
		obj.currentBackgroundImage=document.createElement("IMG");
		DHTMLApi.Visibility.show(obj.currentBackgroundImage);
		obj.currentBackgroundImage.setAttribute("src",file);
		obj.elements.background_container.appendChild(obj.currentBackgroundImage);
		DHTMLApi.Visibility.setOpacity(obj.currentBackgroundImage,opacity);
		DHTMLApi.CSS.setProperties(obj.currentBackgroundImage, {position:"absolute", left: Math.round((DHTMLApi.Size.getElementWidth(obj.elements.background_container)-this.width)/2)+"px", top: "0px"});
		obj.initialized=true;
		if (obj.moreButtonClickHandler!==null) {
			DOMEvent.removeListener(obj.moreButtonClickHandler);
		}
		if (typeof obj.slides[obj.currentImageNum].link!="undefined" && obj.slides[obj.currentImageNum].link!='') {
			DHTMLApi.CSS.setProperties(obj.elements.more_button, {display: "block"});
			obj.moreButtonClickHandler=DOMEvent.addDomListener(obj.elements.more_button,"click",function () {
				window.location.href=obj.slides[obj.currentImageNum].link;
			});
		} else {
			DHTMLApi.CSS.setProperties(obj.elements.more_button, {display: "none"});
		}
	}
	img.src=file;
}

Saponia.MainCarousel.prototype.showTransition=function (imageNum) {
	var obj=this;
	var fadeOutListenerObj={};
	var fadeInListenerObject={};
	if (this.fadeAnimation!==null) this.fadeAnimation.stop();
	this.notifyListeners("onFadeOutStart",this.currentImageNum);
	function __local__fadeIn() {
		obj.currentBackgroundImage=null;
			obj.displayBackground(obj.backgroundImages[obj.currentImageNum],1);
			var generateImgInt=setInterval(function () {									 
				if (obj.currentBackgroundImage!==null && obj.status!=Saponia.MainCarousel.STATUS_FADE_IN) {
					obj.setAnimation(new Animation.Fade(obj.currentBackgroundImage, 1));
					obj.fadeAnimation.addListener(fadeInListenerObject);
					obj.fadeAnimation.setFade(100,obj.numOfTransitionSteps);
					obj.status=Saponia.MainCarousel.STATUS_FADE_IN;
					clearInterval(generateImgInt);
				}
			},50);
	}
	fadeOutListenerObj.onAnimationEnd=function () {
		if (obj.preloader.isLoaded(obj.backgroundImages[obj.currentImageNum])) {
			__local__fadeIn();
			obj.fadeAnimation.removeListener(fadeOutListenerObj);
		} else {
			obj.status=Saponia.MainCarousel.STATUS_PRELOADING;
			obj.preloadingOnDemandFileName=obj.backgroundImages[obj.currentImageNum];
			obj.preloader.startPreloadSlide(obj.currentImageNum,0);
			var onLoadFileObject={};
			onLoadFileObject.onImageLoad=function (fileName) {
				if (fileName==obj.preloadingOnDemandFileName) {
					__local__fadeIn();
					obj.preloadingOnDemandFileName=null;
					obj.preloader.removeListener(onLoadFileObject);
				} else {
					obj.preloader.startPreloadSlide(obj.currentImageNum,0);
				}
			};
			obj.preloader.addListener(onLoadFileObject);
		}
	}
	
	fadeInListenerObject.onAnimationEnd=function () {
		obj.status=Saponia.MainCarousel.STATUS_IDLE;
		obj.notifyListeners("onFadeInStop",imageNum);
	}
	
	fadeInListenerObject.onAnimationStart=function () {
		obj.setSelectedButton(obj.currentImageNum);
	}
			
	if (this.initialized) {
		if (this.status==Saponia.MainCarousel.STATUS_IDLE || this.status==Saponia.MainCarousel.STATUS_FADE_IN) {
			if (this.status==Saponia.MainCarousel.STATUS_IDLE) {
				this.setAnimation(new Animation.Fade(this.currentBackgroundImage, 100)); 
				this.fadeAnimation.setFade(0, this.numOfTransitionSteps);
			} else {
				var currentStep=this.fadeAnimation.currentAnimationStep;
				var currentOpacity=this.fadeAnimation.currentOpacityPercentage;
				this.setAnimation(new Animation.Fade(this.currentBackgroundImage, currentOpacity)); 
				this.fadeAnimation.setFade(0,this.numOfTransitionSteps-currentStep);
			}
			this.fadeAnimation.addListener(fadeOutListenerObj);
			this.status=Saponia.MainCarousel.STATUS_FADE_OUT;
			if (!this.preloader.isLoaded(this.backgroundImages[imageNum])) {
				this.preloader.startPreloadSlide(this.backgroundImages[imageNum]);
				this.preloadingOnDemandFileName=this.backgroundImages[imageNum];
			}
		}	
		if (this.status==Saponia.MainCarousel.STATUS_FADE_OUT || this.status==Saponia.MainCarousel.STATUS_PRELOADING) {
			if (!this.preloader.isLoaded(this.backgroundImages[imageNum])) {
				this.preloadingOnDemandFileName=this.backgroundImages[imageNum];
			}
		}
	}
	this.currentImageNum=imageNum;
}

Saponia.MainCarousel.prototype.setAnimation=function (animationObject) {
	if (this.fadeAnimation!==null) this.fadeAnimation.stop();
	this.fadeAnimation=animationObject;
}

Saponia.MainCarousel.prototype.startLoop=function () {
	var obj=this;
	if (this.loopInterval===null && obj.backgroundImages.length>1) {
		this.loopInterval=window.setInterval(function () {
			if (obj.currentImageNum<(obj.backgroundImages.length-1)) {
				obj.currentImageNum++;
			} else {
				obj.currentImageNum=0;
			}
			obj.showTransition(obj.currentImageNum);
		},10000);
	}
}

Saponia.MainCarousel.prototype.stopLoop=function () {
	if (this.loopInterval!==null) {
		window.clearInterval(this.loopInterval);
		this.loopInterval=null;
	}
}


///////////////////////////////////
// class Saponia.ProductSelector //
///////////////////////////////////

/* elements= {content: element, prevButton: element, nextButton: element}
	parameters= {numOfItems: int, numOfItemsPerScreen: int, screenWidth: int} */

Saponia.ProductSelector=function (elements, parameters) {
	this.contentElement=elements.content;
	this.prevButton=elements.prevButton;
	this.nextButton=elements.nextButton;
	this.numOfItems=parameters.numOfItems;
	this.parameters=parameters;
	this.currentScreen=0;
	this.numOfScreens=Math.ceil(this.parameters.numOfItems/this.parameters.numOfItemsPerScreen);
	this.buttons=[];
	this.animation=new Animation.SmoothHMove(this.contentElement, this.contentElement.parentNode);
	this.setPrevNextButtonsDisplay();
	this.build();
	this.init();
}

Saponia.ProductSelector.prototype=implementsInterface(Observable);

Saponia.ProductSelector.prototype.build=function () {
	DHTMLApi.CSS.setProperties(this.contentElement, {width: this.parameters.screenWidth*this.numOfScreens+"px"});
}

Saponia.ProductSelector.prototype.init=function () {
	var obj=this;
	
	DOMEvent.addDomListener(this.nextButton,"click",function () {
		if (obj.currentScreen<(obj.numOfScreens-1)) {
			obj.setPosition(++obj.currentScreen);
		}
	});
	DOMEvent.addDomListener(this.prevButton,"click",function () {
		if (obj.currentScreen!=0) {
			obj.setPosition(--obj.currentScreen);
		}
	});
}

Saponia.ProductSelector.prototype.setPosition=function (screenNum) {
	this.animation.setPosition(-1*screenNum*this.parameters.screenWidth);
	this.setPrevNextButtonsDisplay();
}

Saponia.ProductSelector.prototype.setPrevNextButtonsDisplay=function () {
	if (this.currentScreen==0) {
		DHTMLApi.Visibility.hide(this.prevButton);
	} else {
		DHTMLApi.Visibility.show(this.prevButton);
	}
	if (this.currentScreen==(this.numOfScreens-1)) {
		DHTMLApi.Visibility.hide(this.nextButton);
	} else {
		DHTMLApi.Visibility.show(this.nextButton);
	}
}


////////////////////////////
// class GalleryPreloader //
////////////////////////////

/* 
data= [string,string]
*/

// broadcasts onImageLoad(fileName)

function GalleryPreloader(data) {
	this.preloadData=data;
	this.imageCue=data;
	this.preloader=null;
}

GalleryPreloader.prototype=implementsInterface(Observable);

GalleryPreloader.prototype.startPreloadAll=function () {
	if (this.imageCue.length==0) return;
	if (this.preloader != null && this.preloader.isPreloading) this.preloader.stop();
	this.preloader=new ImagePreloader(this.imageCue);
	this.preloader.addListener(this);
	this.preloader.start();
}

GalleryPreloader.prototype.startPreloadPicture=function (imageIndex) {
	var preloadsLeft;
	var imageCue=[];
	if (this.isInArray(this.imageCue,this.preloadData[imageIndex])===false) return;
	if (this.preloader != null && this.preloader.isPreloading) this.preloader.stop();	
	imageCue.push(this.preloadData[imageIndex]);
	if (this.preloader != null) this.preloader.removeListener(this);
	this.preloader=new ImagePreloader(imageCue);
	this.preloader.addListener(this);
	this.preloader.start();
}

GalleryPreloader.prototype.isLoaded=function (imageFile) {
	if (this.isInArray(this.imageCue,imageFile)) return false;
	return true;
}

GalleryPreloader.prototype.onImageLoad=function (imageFile) {
	this.imageCue=this.removeFromArray(this.imageCue,imageFile);
	this.notifyListeners("onImageLoad",imageFile);
}

GalleryPreloader.prototype.removeFromArray=function (array,element) {
	var index=null;
	var newArray=[];
	for (var i=0; i<array.length; i++) {
		if (array[i]==element) {
			index=i;
			break;
		}
	}
	if (index!==null) {
		newArray=array.slice(0,index);
		newArray=newArray.concat(array.slice(index+1));
		return newArray;
	} else {
		return array;
	}
}

GalleryPreloader.prototype.isInArray=function (array,element) {
	for (var i=0; i<array.length; i++) {
		if (array[i]==element) return true;
	}
	return false;
}


////////////////////////
// Class PopUpGallery //
////////////////////////

/*
thumbContainer= element or null - gallery without thumbanils
imagesURLArray= [{thmb_url: string, img_url: string},]
cssClasses={navigationBox: string, previousButton: string, nextButton: string, closeButton: string, popUpBackground: string, zoomContainer: string}
navText={previous: string, next: string, close: string}
thumbnailSettings={thumbs_per_row: int, margin: int}
*/

function PopUpGallery(thumbContainer, imagesURLArray, cssClasses, navText, thumbnailSettings) {
	this.zoomContainer=null;
	this.pictureContainer=null;
	this.thumbContainer=thumbContainer;
	this.thumbnailSettings=thumbnailSettings;
	this.imagesURLArray=imagesURLArray;
	this.cssClasses=cssClasses;
	this.navText=navText;
	this.currentPicture=0;
	this.previousButtonHandler-null;
	this.nextButtonHandler-null;
	this.closeButtonHandler=null;
	this.previousButton=null;
	this.nextButton=null;
	this.closeButton=null;
	this.preloader=null;
	this.status=PopUpGallery.STATUS_IDLE;
	this.preloadingOnDemandFileName=null;
	this.initialized=false;
	this.pictureIsReady=false;
	this.numOfTransitionSteps=5;
	this.statusBox=null;
	this.pictureElement=null;
	this.navigationContainer=null;
	this.zoomPicturesArray=[];
	this.pictureContainerHResizeAnimation=null;
	this.pictureContainerVResizeAnimation=null;
	this.fadeAnimation=null;
	this.pictureXPosInViewport=null;
	this.pictureYPosInViewport=null;
	this.init();
}

PopUpGallery.STATUS_IDLE=1;
PopUpGallery.STATUS_PRELOADING=2;
PopUpGallery.STATUS_FADE_OUT=3;
PopUpGallery.STATUS_FADE_IN=4;

PopUpGallery.prototype.init=function () {
	if (this.thumbContainer!==null) this.initThumbs();
	this.preloader=new GalleryPreloader(this.zoomPicturesArray);
}

PopUpGallery.prototype.initThumbs=function () {
	var imageElement,num,numOfRows;
	var obj=this;
	this.thumbContainer.innerHTML="";
	numOfRows=Math.ceil(this.imagesURLArray.length/this.thumbnailSettings.thumbs_per_row);
	for (var i=0; i<this.imagesURLArray.length; i++) {
		this.zoomPicturesArray.push(this.imagesURLArray[i]['img_url']);
		imageElement=document.createElement("IMG");
		imageElement.setAttribute("src",this.imagesURLArray[i].thmb_url);
		if ((i+1)%this.thumbnailSettings.thumbs_per_row!=0) {
			DHTMLApi.CSS.setProperties(imageElement,{marginRight: this.thumbnailSettings.margin_horizontal+"px"});
		}
		if (i<(numOfRows-1)*this.thumbnailSettings.thumbs_per_row) {
			DHTMLApi.CSS.setProperties(imageElement,{marginBottom: this.thumbnailSettings.margin_vertical+"px"});
		}
		this.thumbContainer.appendChild(imageElement);
		num=i;
		(function() {
			var num=i;
			DOMEvent.addDomListener(imageElement, "click", function () {
				obj.open(num);
			}); 
		})();		
	}
}

PopUpGallery.prototype.open=function (pictureNum) {
	this.displayZoom();
	this.displayFirstPicture(pictureNum);
	this.currentPicture=pictureNum;
}

PopUpGallery.prototype.displayZoom=function () {
	var obj=this;
	this.buildZoom();
	this.setZoomContainerSize(800,600);
	PopUpLayer.display(this.zoomContainer,this.cssClasses.popUpBackground,80,null,function () {obj.clear();});
	PopUpLayer.centerOnPage();
	//if (this.imagesURLArray.length>1) {
		this.initNavigation();
	//}
}

PopUpGallery.prototype.clear=function () {
	if (this.imagesURLArray.length>1) {
		DOMEvent.removeListener(this.previousButtonHandler);
		DOMEvent.removeListener(this.nextButtonHandler);
	}
	DOMEvent.removeListener(this.closeButtonHandler);
	this.pictureContainerHResizeAnimation.stop();
	this.pictureContainerVResizeAnimation.stop();
	this.fadeAnimation.stop();
	document.body.removeChild(this.zoomContainer);
}

PopUpGallery.prototype.buildZoom=function () {
	var navigationContainer;
	var obj=this;
	this.zoomContainer=document.createElement("DIV");
	this.pictureContainer=document.createElement("DIV");
	
	this.zoomContainer.appendChild(this.pictureContainer);
	document.body.appendChild(this.zoomContainer);
	
	
	this.navigationContainer=document.createElement("DIV");
	if (this.imagesURLArray.length>1) {
		this.previousButton=document.createElement("SPAN");
		this.previousButton.appendChild(document.createTextNode(this.navText.previous));
		this.nextButton=document.createElement("SPAN");
		this.nextButton.appendChild(document.createTextNode(this.navText.next));
		this.statusBox=document.createElement("SPAN");
	}
	this.closeButton=document.createElement("SPAN");
	this.closeButton.appendChild(document.createTextNode(this.navText.close));
	if (this.imagesURLArray.length>1) {
		this.navigationContainer.appendChild(this.previousButton);
		this.navigationContainer.appendChild(document.createElement("SPAN").appendChild(document.createTextNode(" | ")));
	}
	this.navigationContainer.appendChild(this.closeButton);
	if (this.imagesURLArray.length>1) {
		this.navigationContainer.appendChild(document.createElement("SPAN").appendChild(document.createTextNode(" | ")));
		this.navigationContainer.appendChild(this.nextButton);
		this.navigationContainer.appendChild(this.statusBox);
	}
	this.zoomContainer.appendChild(this.navigationContainer);
	DHTMLApi.CSS.setClass(this.navigationContainer,[this.cssClasses.navigationBox],[]);
	if (this.imagesURLArray.length>1) {
		DHTMLApi.CSS.setClass(this.previousButton,[this.cssClasses.previousButton],[]);
		DHTMLApi.CSS.setClass(this.nextButton,[this.cssClasses.nextButton],[]);
	}
	DHTMLApi.Visibility.hide(this.navigationContainer);
	DHTMLApi.CSS.setClass(this.closeButton,[this.cssClasses.closeButton],[]);
	DHTMLApi.CSS.setClass(this.zoomContainer,[this.cssClasses.zoomContainer],[]);
	this.pictureContainerHResizeAnimation=new Animation.SmoothHResize(this.pictureContainer);
	this.pictureContainerVResizeAnimation=new Animation.SmoothVResize(this.pictureContainer);
	this.pictureContainerHResizeAnimation.addListener({onAnimationStep: function () {obj.centerHPicture();}});
	this.pictureContainerVResizeAnimation.addListener({onAnimationStep: function () {obj.centerVPicture();}});
}

PopUpGallery.prototype.setZoomContainerSize=function (pictureWidth,pictureHeight) {
	DHTMLApi.CSS.setProperties(this.zoomContainer, {width: pictureWidth+"px",height: (pictureHeight+24)+"px"});
	DHTMLApi.CSS.setProperties(this.pictureContainer, {width: pictureWidth+"px", height: pictureHeight+"px", position: "absolute", top: "0px", left: "0px"});
}

PopUpGallery.prototype.setZoomContainerSizeAnimate=function (pictureWidth,pictureHeight) {
	//if (this.imagesURLArray.length>1) {
		this.pictureContainerHResizeAnimation.setSize(pictureWidth);
		this.pictureContainerVResizeAnimation.setSize(pictureHeight);
	/*} else {
		DHTMLApi.CSS.setProperties(this.zoomContainer, {width: pictureWidth+"px",height: pictureHeight+"px"});
		DHTMLApi.CSS.setProperties(this.pictureContainer, {width: pictureWidth+"px", height: pictureHeight+"px", position: "absolute", top: "0px", left: "0px"});
	}*/
}

PopUpGallery.prototype.initNavigation=function () {
	var obj=this;
	if (this.imagesURLArray.length>1) {
		this.previousButtonHandler=DOMEvent.addDomListener(this.previousButton, "click", function () {
			var targetPicture;
			if (obj.currentPicture==0) {
				targetPicture=obj.imagesURLArray.length-1;
			} else {
				targetPicture=obj.currentPicture-1;
			}
			//obj.displayPicture(obj.currentPicture);
			obj.onPictureChange(targetPicture);
		}); 
	
		this.nextButtonHandler=DOMEvent.addDomListener(this.nextButton, "click", function () {
			var targetPicture;
			if (obj.currentPicture==(obj.imagesURLArray.length-1)) {
				targetPicture=0;
			} else {
				targetPicture=obj.currentPicture+1;
			}
			//obj.displayPicture(obj.currentPicture);
			obj.onPictureChange(targetPicture);
		});
	}
		
	this.closeButtonHandler=DOMEvent.addDomListener(this.closeButton, "click", function () {
		PopUpLayer.hide();
		obj.clear();
	});
}

PopUpGallery.prototype.displayPicture=function(pictureNum,opacity) {
	var pictureElement,navigationPositionInViewport;
	var obj=this;
	this.pictureContainer.innerHTML="";
	this.pictureElement=document.createElement("IMG");
	this.pictureIsReady=false;
	this.pictureElement.onload=function () {
		obj.pictureContainer.appendChild(obj.pictureElement);
		obj.pictureXPosInViewport=Math.round((DHTMLApi.Browser.getViewportWidth()-this.width)/2+DHTMLApi.Browser.getScrollX());
		obj.pictureYPosInViewport=Math.round((DHTMLApi.Browser.getViewportHeight()-this.height)/2+DHTMLApi.Browser.getScrollY());
		if (obj.pictureYPosInViewport+this.height>DHTMLApi.Size.getPageHeight()) {
			obj.pictureYPosInViewport=DHTMLApi.Size.getPageHeight()-this.height;
		}
		DHTMLApi.Visibility.setOpacity(obj.pictureElement,opacity)
		obj.setZoomContainerSizeAnimate(this.width,this.height);
		obj.pictureIsReady=true;
	}
	this.pictureElement.setAttribute("src",this.imagesURLArray[pictureNum].img_url);
	navigationPositionInViewport=Math.round((DHTMLApi.Browser.getViewportWidth()-DHTMLApi.Size.getElementWidth(this.navigationContainer))/2+DHTMLApi.Browser.getScrollX());
	DHTMLApi.CSS.setProperties(this.navigationContainer,{position: "absolute", left: (navigationPositionInViewport-DHTMLApi.Position.getXPosOnPage(this.zoomContainer))+"px"});
	if (this.imagesURLArray.length>1) {
		this.displayStatusInfo(pictureNum);
	}
}

PopUpGallery.prototype.displayFirstPicture=function (pictureNum) {
	var obj=this;
	var fadeInListenerObject={};
	this.displayPicture(pictureNum,1);
	var generateImgInt=setInterval(function () {
		if (obj.pictureIsReady) {
		//if (obj.pictureElement!==null) {
			obj.fadeAnimation=new Animation.Fade(obj.pictureElement, 1);
			obj.fadeAnimation.setFade(100,obj.numOfTransitionSteps);
			obj.fadeAnimation.addListener(fadeInListenerObject);
			obj.status=PopUpGallery.STATUS_FADE_IN;
			obj.initialized=true;
			clearInterval(generateImgInt);
			DHTMLApi.Visibility.show(obj.navigationContainer);
		}
	},70);
	
	fadeInListenerObject.onAnimationEnd=function () {
		obj.status=PopUpGallery.STATUS_IDLE;
	}
}

PopUpGallery.prototype.centerHPicture=function () {
	var leftContainerPos,leftPicPos,navigationPositionInViewport;
	leftContainerPos=Math.round((DHTMLApi.Browser.getViewportWidth()-DHTMLApi.Size.getElementWidth(this.pictureContainer))/2+DHTMLApi.Browser.getScrollX());
	leftPicPos=this.pictureXPosInViewport-leftContainerPos;
	DHTMLApi.CSS.setProperties(this.zoomContainer,{width: DHTMLApi.Size.getElementWidth(this.pictureContainer)+"px", left: leftContainerPos+"px"});
	DHTMLApi.CSS.setProperties(this.pictureElement,{position: "absolute", left: leftPicPos+"px"});
	navigationPositionInViewport=Math.round((DHTMLApi.Browser.getViewportWidth()-DHTMLApi.Size.getElementWidth(this.navigationContainer))/2+DHTMLApi.Browser.getScrollX());
	DHTMLApi.CSS.setProperties(this.navigationContainer,{position: "absolute", left: navigationPositionInViewport-leftContainerPos+"px"});
}

PopUpGallery.prototype.centerVPicture=function () {
	var topContainerPos,topPicPos;
	topContainerPos=Math.round((DHTMLApi.Browser.getViewportHeight()-DHTMLApi.Size.getElementHeight(this.pictureContainer))/2+DHTMLApi.Browser.getScrollY());
	topPicPos=this.pictureYPosInViewport-topContainerPos;
	DHTMLApi.CSS.setProperties(this.zoomContainer,{height: (DHTMLApi.Size.getElementHeight(this.pictureContainer)+24)+"px", top: (topContainerPos-24)+"px"});
	DHTMLApi.CSS.setProperties(this.pictureElement,{position: "absolute", top: topPicPos+"px"});
}

PopUpGallery.prototype.displayStatusInfo=function (pictureNum) {
	this.statusBox.innerHTML=(pictureNum+1)+"/"+this.imagesURLArray.length;
}

PopUpGallery.prototype.onPictureChange=function (pictureNum) {
	var obj=this;
	var fadeOutListenerObj={};
	var fadeInListenerObject={};
	function __local__fadeIn() {
		obj.pictureElement=null
			obj.displayPicture(obj.currentPicture,1);
			var generateImgInt=setInterval(function () {
				if (obj.pictureIsReady) {
				//if (obj.pictureElement!==null) {
					obj.fadeAnimation=new Animation.Fade(obj.pictureElement, 1);
					obj.fadeAnimation.setFade(100,obj.numOfTransitionSteps);
					obj.fadeAnimation.addListener(fadeInListenerObject);
					obj.status=PopUpGallery.STATUS_FADE_IN;
					clearInterval(generateImgInt);
				}
			},70);
	}
	fadeOutListenerObj.onAnimationEnd=function () {
		if (obj.preloader.isLoaded(obj.zoomPicturesArray[obj.currentPicture])) {
			__local__fadeIn();
		} else {
			obj.status=PopUpGallery.STATUS_PRELOADING;
			obj.preloadingOnDemandFileName=obj.zoomPicturesArray[obj.currentPicture];
			obj.preloader.startPreloadPicture(obj.currentPicture,0);
			var onLoadFileObject={};
			onLoadFileObject.onImageLoad=function (fileName) {
				if (fileName==obj.preloadingOnDemandFileName) {
					__local__fadeIn();
					obj.preloadingOnDemandFileName=null;
					obj.preloader.removeListener(onLoadFileObject);
				} else {
					obj.preloader.startPreloadPicture(obj.currentPicture,0);
				}
			};
			obj.preloader.addListener(onLoadFileObject);
		}
	}
	fadeInListenerObject.onAnimationEnd=function () {
		obj.status=PopUpGallery.STATUS_IDLE;
	}
	
	if (this.initialized) {
		if (this.status==PopUpGallery.STATUS_IDLE || this.status==PopUpGallery.STATUS_FADE_IN) {
			if (this.status==PopUpGallery.STATUS_IDLE) {
				this.fadeAnimation=new Animation.Fade(this.pictureElement, 100);
				this.fadeAnimation.setFade(0, this.numOfTransitionSteps);
			} else {
				var currentStep=this.fadeAnimation.currentAnimationStep;
				var currentOpacity=this.fadeAnimation.currentOpacityPercentage;
				this.fadeAnimation.stop();
				this.fadeAnimation=new Animation.Fade(this.pictureElement, currentOpacity);
				this.fadeAnimation.setFade(0,this.numOfTransitionSteps-currentStep);
			}
			this.fadeAnimation.addListener(fadeOutListenerObj);
			this.status=PopUpGallery.STATUS_FADE_OUT;
			if (!this.preloader.isLoaded(this.zoomPicturesArray[pictureNum])) {
				this.preloader.startPreloadPicture(pictureNum,0);
				this.preloadingOnDemandFileName=this.zoomPicturesArray[pictureNum];
			}
		}	
		if (this.status==PopUpGallery.STATUS_FADE_OUT || this.status==PopUpGallery.STATUS_PRELOADING) {
			if (!this.preloader.isLoaded(this.zoomPicturesArray[pictureNum])) {
				this.preloadingOnDemandFileName=this.zoomPicturesArray[pictureNum];
			}
		}
	}
	this.currentPicture=pictureNum;
}


////////////////////////////////
// Interface DropDownSelector //
////////////////////////////////

DropDownSelector = {
	setSelected : function (selectionElement, selectedValue) {
			for (var i=0; i<selectionElement.length; i++) {
				if (selectionElement.options[i].value==selectedValue) {
					try {
						selectionElement.options[i].selected=true;
					}					
					catch (e) {}
				} else {
					try {
						selectionElement.options[i].selected=false;
					}					
					catch (e) {}
				}
			}
	},
	
	getSelectedValue : function (selectionElement) {
		var selectedIndex;
		selectedIndex=selectionElement.selectedIndex;
		if (selectedIndex == -1) return false;
		return selectionElement.options[selectedIndex].value;
	},
	
	getSelectedLabelName : function (selectionElement) {
		var selectedIndex;
		selectedIndex=selectionElement.selectedIndex;
		if (selectedIndex == -1) return false;
		return selectionElement.options[selectedIndex].label;
	},
	
	addOption : function (selectionElement, optionLabel, optionValue) {
		var newOptionElement;
		newOptionElement=document.createElement("option");
		newOptionElement.appendChild(document.createTextNode(optionLabel));
		newOptionElement.value=optionValue;
		newOptionElement.label=optionLabel;
		selectionElement.appendChild(newOptionElement);
	},
	
	clearOptions : function (selectionElement) {
		while(selectionElement.hasChildNodes()) {
			selectionElement.removeChild(selectionElement.firstChild);
		}
	},
	
	disable : function (selectionElement) {
		selectionElement.disabled=true;
	},
	
	enable : function (selectionElement) {
		selectionElement.disabled=false;
	}
};

Utopia.Calendar={};

///////////////////////////////////////////////////
// interface Utopia.Calendar.DateTimeInputCommon //
///////////////////////////////////////////////////

Utopia.Calendar.DateTimeInputCommon= {
	buildDaySelector: function (daySelectorElement,numOfdays) {
		DropDownSelector.clearOptions(daySelectorElement);
		DropDownSelector.addOption(daySelectorElement, "-", "");
		for (var i=1; i<=numOfdays; i++) {
			DropDownSelector.addOption(daySelectorElement, i, i);
		}
	},
	
	buildMonthSelector: function (monthSelectorElement) {
		DropDownSelector.addOption(monthSelectorElement, "-", "");
		for (var i=1; i<=12; i++) {
			DropDownSelector.addOption(monthSelectorElement, i, i);
		}
	},
	
	buildYearSelector: function (yearSelectorElement,startYear,endYear) {
		DropDownSelector.addOption(yearSelectorElement, "-", "");
		for (var i=endYear; i>=startYear; i--) {
			DropDownSelector.addOption(yearSelectorElement, i, i);
		}
	},
	
	setSelectedDay: function (daySelectorElement,selectedInfoObject,dayNum,maxNumOfDays) {
		var selectedDay;
		selectedDay=(parseInt(dayNum)>maxNumOfDays) ? "" : dayNum;
		DropDownSelector.setSelected(daySelectorElement, selectedDay);
		selectedInfoObject.day=selectedDay;
	},
	
	setSelectedMonth: function (monthSelectorElement,selectedInfoObject,monthNum) {
		DropDownSelector.setSelected(monthSelectorElement, monthNum);
		selectedInfoObject.month=monthNum;
	},
	
	setSelectedYear: function (yearSelectorElement,selectedInfoObject,year) {
		DropDownSelector.setSelected(yearSelectorElement, year);
		selectedInfoObject.year=year;
	},
	
	getNumOfDays: function (year,month) {
		var date;
		if (year=="" || month=="") return 31;
		date=new Date(year,(month-1));
		return date.getNumOfDaysInMonth();
	}
}

//////////////////////////////////////////////
// class Utopia.Calendar.BirthDayInputField //
//////////////////////////////////////////////

/* inputElements={daySelector: element, monthSelector: element, yearSelector: element}

selectedDate={year: int, month: int (1-12), day: int} 
*/

Utopia.Calendar.BirthDayInputField=function (inputElements,startYear,endYear,selectedDate) {
	this.inputElements=inputElements;
	this.selectedDate=(typeof selectedDate=="undefined") ? {year: "", month: "", day: ""} : selectedDate;
	this.currentMaxNumOfDays=(typeof selectedDate=="undefined") ? 31 : this.getNumOfDays(this.selectedDate.year,this.selectedDate.month);
	this.startYear=startYear;
	this.endYear=endYear;
	this.init();
	this.initHandlers();
}

Utopia.Calendar.BirthDayInputField.prototype=implementsInterface(Utopia.Calendar.DateTimeInputCommon);

Utopia.Calendar.BirthDayInputField.prototype.init=function () {
	this.buildDaySelector(this.inputElements.daySelector,this.currentMaxNumOfDays);
	this.buildMonthSelector(this.inputElements.monthSelector);
	this.buildYearSelector(this.inputElements.yearSelector,this.startYear,this.endYear);
	if (this.selectedDate.year!="") this.setSelectedYear(this.inputElements.yearSelector,this.selectedDate,this.selectedDate.year);
	if (this.selectedDate.month!="") this.setSelectedMonth(this.inputElements.monthSelector,this.selectedDate,this.selectedDate.month);
	if (this.selectedDate.day!="") this.setSelectedDay(this.inputElements.daySelector,this.selectedDate,this.selectedDate.day,this.currentMaxNumOfDays);
}

Utopia.Calendar.BirthDayInputField.prototype.initHandlers=function () {
	var obj=this;
	DOMEvent.addDomListener(this.inputElements.yearSelector,"change",function () {
		obj.selectedDate.year=DropDownSelector.getSelectedValue(obj.inputElements.yearSelector);
		obj.currentMaxNumOfDays=obj.getNumOfDays(obj.selectedDate.year,obj.selectedDate.month);
		obj.buildDaySelector(obj.inputElements.daySelector,obj.currentMaxNumOfDays);
		obj.setSelectedDay(obj.inputElements.daySelector,obj.selectedDate,obj.selectedDate.day,obj.currentMaxNumOfDays);	
	});	
	DOMEvent.addDomListener(this.inputElements.monthSelector,"change",function () {
		obj.selectedDate.month=DropDownSelector.getSelectedValue(obj.inputElements.monthSelector);
		obj.currentMaxNumOfDays=obj.getNumOfDays(obj.selectedDate.year,obj.selectedDate.month);
		obj.buildDaySelector(obj.inputElements.daySelector,obj.currentMaxNumOfDays);
		obj.setSelectedDay(obj.inputElements.daySelector,obj.selectedDate,obj.selectedDate.day,obj.currentMaxNumOfDays);		
	});
	DOMEvent.addDomListener(this.inputElements.daySelector,"change",function () {
		obj.selectedDate.day=DropDownSelector.getSelectedValue(obj.inputElements.daySelector);
	});
}
