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];
	}
}

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);
			return (document.documentElement && document.documentElement.scrollWidth) ? document.documentElement.scrollWidth : (document.body.scrollWidth > document.body.offsetWidth) ? document.body.scrollWidth : document.body.offsetWidth;
		},
		
		getPageHeight: function () {
			var height=(document.documentElement && document.documentElement.scrollHeight) ? document.documentElement.scrollHeight : (document.body.scrollHeight > document.body.offsetHeight) ? document.body.scrollHeight : document.body.offsetHeight;
			return Math.max(height,DHTMLApi.Browser.getViewportHeight());
			
		}
	
	},
	
	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+')';
			} 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();
	}
};


function DOMEventHandle(element, type, handler) {
	this.element=element;
	this.type=type;
	this.handler=handler;
}

DOMEvent = {	

	// public
	
	addDomListener: function (element, type, handler) {
		var handlers, newHandler;
		newHandler=this.modifyHandlerExceptions(element, type, handler);
		if (newHandler!==false) handler=newHandler;
		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);
	},
	
	modifyHandlerExceptions : function (element, type, handler) {
		var newHandler;
		if ((type == "mouseout" || type == "mouseover") && element.nodeName == 'DIV') {
			newHandler=function (eventObject) {
				var relatedTarget= (eventObject.relatedTarget) ? eventObject.relatedTarget : eventObject.toElement;
				while (relatedTarget !==null && relatedTarget !== element && relatedTarget.nodeName != 'BODY') {
					relatedTarget= relatedTarget.parentNode;
				}
				if (relatedTarget !== element) {
					handler(eventObject);
				}
			}
			return newHandler;
		}
		
		//if (window.addEventListener)
        /** DOMMouseScroll is for mozilla. */
        //window.addEventListener('DOMMouseScroll', wheel, false);
/** IE/Opera. */
//window.onmousewheel = document.onmousewheel = wheel;
		return false;
	},
	
	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;
	}
};


JSON={
	serialize: function (JSONObject) {
		var elementArray=new Array();
		var resultString;			
		var objectTypeIsArray=false;
		if (JSONObject.constructor==Array) {
			objectTypeIsArray=true;
			for (var i=0; i<JSONObject.length; i++) {
				if (typeof JSONObject[i] == "object") {
					elementArray.push(JSON.serialize(JSONObject[i]));
				} else if (typeof JSONObject[i] == "string") {
					elementArray.push('"'+encodeURIComponent(JSONObject[i])+'"');
				} else {
					elementArray.push(JSONObject[i]);
				}
			}
		} else if (JSONObject.constructor==Object) {
			for (var property in JSONObject) {
				if (typeof JSONObject[property] == "object") {
					elementArray.push(property+':'+JSON.serialize(JSONObject[property]));
				} else if (typeof JSONObject[property] == "string") {
					elementArray.push(property+':'+'"'+encodeURIComponent(JSONObject[property])+'"');
				} else {
					elementArray.push(property+':'+JSONObject[property]);
				}
			}
		} else 	{
			return encodeURIComponent(JSONObject);
		}
		resultString=elementArray.join(",");
		if (objectTypeIsArray) {
			return "["+resultString+"]";
		} else {
			return "{"+resultString+"}";
		}
	},
	
	unserialize: function (JSONString) {
		var JSONObject;
		try {
			eval("JSONObject="+JSONString);
		} catch (e) {
			JSONObject=new Object();
		};
		return JSON.urlDecodeJSONObject(JSONObject);
	},
	
	urlDecodeJSONObject: function (JSONObject) {
		var decodedObject;
		if (JSONObject===null) {
			decodedObject=null;
		} else 	if (JSONObject.constructor==Array) {
			decodedObject=new Array();
			for (var i=0; i<JSONObject.length; i++) {
				if (typeof JSONObject[i] == "object") {
					decodedObject.push(JSON.urlDecodeJSONObject(JSONObject[i]));
				} else if (typeof JSONObject[i] == "string") {
					decodedObject.push(decodeURIComponent(JSONObject[i]));
				} else {
					decodedObject.push(JSONObject[i]);
				}
			}
		} else if (JSONObject.constructor==Object) {
			decodedObject=new Object();
			for (var property in JSONObject) {
				if (typeof JSONObject[property] == "object") {
					decodedObject[property]=JSON.urlDecodeJSONObject(JSONObject[property]);
				} else if (typeof JSONObject[property] == "string") {
					decodedObject[property]=decodeURIComponent(JSONObject[property]);
				} else {
					decodedObject[property]=JSONObject[property];
				}
			}
		} else 	{
			decodedObject=decodeURIComponent(JSONObject);
		}
		return decodedObject;
	}
};


Ajax={ 
	getXMLHttpRequest : function () {
	
		if ((typeof XMLHttpRequest) == "undefined") {
			XMLHttpRequest=function() {
				return new ActiveXObject(navigator.userAgent.indexOf("MSIE 5") >= 0 ? "Microsoft.XMLHTTP" : "Msxml2.XMLHTTP");
			}
		} 	
		return (new XMLHttpRequest());
	},
	
	isSuccess : function (xmlHttpRequestObj) {
		try {
			return (!xmlHttpRequestObj.status && location.protocol=="file:") || (xmlHttpRequestObj.status >=200 && xmlHttpRequestObj.status < 300) || xmlHttpRequestObj.status==304 || (navigator.userAgent.indexOf("Safari") >= 0 && typeof xmlHttpRequestObj.status == "undefined");
		} catch(e){};
		return false;		
	},
	
	/* dataType is string, values: xml, html, json */
	
	getResponseData : function (xmlHttpRequestObj,dataType) {
		var ct=xmlHttpRequestObj.getResponseHeader("content-type");
		var xmlData= !dataType && ct && ct.indexOf("xml")>=0;
		var data= (dataType == "xml" || xmlData)? xmlHttpRequestObj.responseXML: xmlHttpRequestObj.responseText;
		if (dataType=="json") {
			data=JSON.unserialize(data);
		}
		return data;
	}
}

//////////////////////////
// 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);
			}
		}
	}
};


/////////////////////
// Class SlideShow //
/////////////////////

function SlideShow(imagesUrlArray, containerElement, slideDurationInSec, numOfTransitionIterations, numOfTransitionMixIterations) {
	this.container=containerElement;
	this.imagesUrlArray=imagesUrlArray;
	this.numOfImagesPreloaded=1;
	this.preloader=new ImagePreloader(this.imagesUrlArray.slice(1));
	this.currentSlide=1;
	this.slideDuration=Math.round(slideDurationInSec*1000);
	this.numOfTransitionIterations=numOfTransitionIterations;
	this.playInterval=null;
	this.foregroundSlide=document.createElement("IMG");
	this.backgroundSlide=document.createElement("IMG");
	this.fadeOutAnimation=null;
	this.fadeInAnimation=null;
	this.slideShowIsPlaying=false;
	this.numOfStartFadeInIteration=numOfTransitionIterations-numOfTransitionMixIterations;
	if (this.numOfStartFadeInIteration<1) {
		this.numOfStartFadeInIteration=1;
	}
	if (this.numOfStartFadeInIteration>=this.numOfTransitionIterations) {
		this.numOfStartFadeInIteration=this.numOfTransitionIterations-1;
	}
	this.preloader.addListener(this);
	this.init();
}

SlideShow.prototype.init=function() {
	var obj=this;
	DHTMLApi.CSS.setProperties(this.container, {position:"relative", overflow:"hidden"});
	this.container.appendChild(this.foregroundSlide);
	this.container.appendChild(this.backgroundSlide);
	DHTMLApi.CSS.setProperties(this.foregroundSlide, {position:"absolute", zIndex:2});
	DHTMLApi.CSS.setProperties(this.backgroundSlide, {position:"absolute", zIndex:1});
	DHTMLApi.Visibility.hide(this.foregroundSlide);
	DHTMLApi.Visibility.hide(this.backgroundSlide);
	this.displaySlide(this.foregroundSlide,this.currentSlide, 100);
}

SlideShow.prototype.displaySlide=function(slide, slideNum, opacity) {
	var obj=this;
	var img=new Image();
	img.onload=function () {
		DHTMLApi.Visibility.show(slide);
		slide.setAttribute("src",obj.imagesUrlArray[slideNum-1]);
		obj.setOpacity(slide,1);
		obj.centerSlide(slide,this.width,this.height);
		obj.setOpacity(slide,opacity);
	}
	img.src=this.imagesUrlArray[slideNum-1];
}

SlideShow.prototype.centerSlide=function (slide,slideWidth,slideHeight) {
	var posX,posY;
	posX=Math.round((DHTMLApi.Size.getElementWidth(this.container)-slideWidth)/2);
	posY=Math.round((DHTMLApi.Size.getElementHeight(this.container)-slideHeight)/2);
	DHTMLApi.CSS.setProperties(slide, {position:"absolute", left: posX+"px", top: posY+"px"});
}

SlideShow.prototype.setOpacity=function(slide,opacity) {
	DHTMLApi.Visibility.setOpacity(slide,opacity);
}

SlideShow.prototype.display=function(slideNum) {
	this.stop();
	this.currentSlide=slideNum;
	this.displaySlide(this.foregroundSlide, this.currentSlide,100);
}

SlideShow.prototype.displayNextSlide=function() {
	this.stop();
	this.currentSlide=this.getNextSlide();
	this.displaySlide(this.foregroundSlide, this.currentSlide,100);
}

SlideShow.prototype.displayPreviousSlide=function() {
	this.stop();
	this.currentSlide=this.getPreviousSlide();
	this.displaySlide(this.foregroundSlide, this.currentSlide,100);
}

SlideShow.prototype.getNextSlide=function() {
	if (this.currentSlide==this.imagesUrlArray.length) {
		return 1;
	} else {
		return this.currentSlide+1;
	}
}

SlideShow.prototype.getPreviousSlide=function() {
	if (this.currentSlide==1) {
		return this.imagesUrlArray.length;
	} else {
		return this.currentSlide-1;
	}
}

SlideShow.prototype.play=function () {
	var obj=this;
	if (this.slideShowIsPlaying) return;
	this.preloader.start();
	this.slideShowIsPlaying=true;
	this.playInterval=window.setInterval(function () {obj.playTransition();}, this.slideDuration);
}

SlideShow.prototype.playTransition=function() {
	var fadeOutListener, fadeInListener, fadeOutChannel, fadeInChannel;
	if (this.currentSlide>=this.numOfImagesPreloaded && this.numOfImagesPreloaded!=this.imagesUrlArray.length) return;
	var obj=this;
	this.fadeInAnimation=null;
	fadeOutListener=new Object();
	fadeOutListener.onAnimationEnd=function () {
		obj.fadeOutAnimation.removeListener(this);
	}
	fadeOutListener.onAnimationStart=function() {
	}
	
	fadeOutListener.onAnimationStep=function (eventObj) {
		if (eventObj==obj.numOfStartFadeInIteration) {
			obj.currentSlide=obj.getNextSlide();
			obj.displaySlide(obj.foregroundSlide, obj.currentSlide, 1);
			obj.fadeInAnimation=new Animation.Fade(obj.foregroundSlide, 1);
			obj.fadeInAnimation.setFade(100,obj.numOfTransitionIterations);
		}
	}
	
	this.displaySlide(this.backgroundSlide,this.currentSlide,100);
	this.fadeOutAnimation=new Animation.Fade(this.backgroundSlide, 100);
	this.fadeOutAnimation.addListener(fadeOutListener);
	this.fadeOutAnimation.setFade(0,this.numOfTransitionIterations);
}

SlideShow.prototype.stop=function() {
	this.preloader.stop();
	if (this.fadeOutAnimation!=null) this.fadeOutAnimation.stop();
	if (this.fadeInAnimation!=null) this.fadeInAnimation.stop();
	this.slideShowIsPlaying=false;
	DHTMLApi.Visibility.hide(this.backgroundSlide);
	this.displaySlide(this.foregroundSlide, this.currentSlide, 100);
	
	window.clearInterval(this.playInterval);
}

SlideShow.prototype.onImageLoad=function (eventObject) {
	this.numOfImagesPreloaded++;
}

//////////////////////////
// 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);
}

///////////////////////
// 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(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"});
	},
	
	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);
	},
	
	getPageHeight: function () {
		return DHTMLApi.Size.getPageHeight();
	},
	
	getPageWidth: function () {
		return DHTMLApi.Size.getPageWidth();
	}
	
}

////////////////////////////
// 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 //
////////////////////////

/*
imagesURLArray= [{img_url: string},]
cssClasses={navigationBox: string, previousButton: string, nextButton: string, closeButton: string, popUpBackground: string, zoomContainer: string}
navText={previous: string, next: string, close: string}
*/

function PopUpGallery(imagesURLArray, cssClasses, navText) {
	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 () {
	/*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['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+"px"});
		}
		if (i<(numOfRows-1)*this.thumbnailSettings.thumbs_per_row) {
			DHTMLApi.CSS.setProperties(imageElement,{marginBottom: this.thumbnailSettings.margin+"px"});
		}
		this.thumbContainer.appendChild(imageElement);
		num=i;
		(function() {
			var num=i;
			DOMEvent.addDomListener(imageElement, "click", function () {
				obj.open(num);
			}); 
		})();		
	}*/
	this.preloader=new GalleryPreloader(this.zoomPicturesArray);
}

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"});
	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;
}


/////////////////////
// class StoreData //
/////////////////////

function StoreData(adId,type,data) {
	this.id=adId;
	this.type=type;
	this.data=data;
}


StoreData.prototype.getMarkerHtml=function() {
	var str;
	str='<div class="baloon"><div class="baloon_title">'+this.data.title+'</div><div class="pic_holder"><img src="'+this.data.tn_uri+'"/></div><div class="baloon_text">'+this.getShopName()+this.getAddressHtml()+this.getPhone()+'<br>'+this.getEmail()+'</div></div>';
	return str;
};

StoreData.prototype.getAddressHtml=function () {
	var str;
	str="";
	if (this.data.street!="") str+=this.data.street+' '+this.data.house_nr+'<br>';
	str+=this.data.city_name;
	return str;
}

StoreData.prototype.getShopName=function () {
	if (this.data.shop_name=="") return "";
	return this.data.shop_name+'<br>'
}

StoreData.prototype.getPhone=function () {
	if (this.data.phone=="") return "";
	return '<br>tel: '+this.data.phone;
}

StoreData.prototype.getEmail=function () {
	if (this.data.email.length<25) {
		return '<a href="mailto:'+this.data.email+'">'+this.data.email+'</a>';
	} else {
		return '<a href="mailto:'+this.data.email+'">e-mail</a>';
	}
}

StoreData.prototype.getValue=function (databaseField) {
	return this.data[databaseField];
}
	
StoreData.prototype.getType=function () {
	return this.type;
}

//////////////////////
// class StoreCache //
//////////////////////

function StoreCache(markersInitArray,storeInitArray) {
	this.markersData={};
	this.adsData={};
	this.storeMarkers(markersInitArray);
	this.storeAds(storeInitArray);
}

StoreCache.prototype.storeAds=function (adsArray) {
	var adDataObject;
	for (var i=0; i<adsArray.length; i++) {
		this.addAd(adsArray[i]);
	}
};

StoreCache.prototype.storeMarkers=function (markersArray) {
	var markerType;
	for (var i=0; i<markersArray.length; i++) {
		markerType=markersArray[i].type;
		if (typeof this.markersData[markerType] == "undefined") this.markersData[markerType]=[];
		this.markersData[markerType].push(markersArray[i]);
	}
};

StoreCache.prototype.addAd=function (adData) {
	var adDataObject;
	adDataObject=new StoreData(adData["id"],adData["type"],adData["data"]);
	this.adsData[adData["id"]]=adDataObject;
};

StoreCache.prototype.getAdData=function (id) {
	if (typeof this.adsData[id]== "undefined") {
		return false;
	} else {
		return this.adsData[id];
	}
};

StoreCache.prototype.getMarkersData=function (type) {
	return this.markersData[type];
}

/////////////////////////////
// Class StoreLocationList //
/////////////////////////////

/* locationList= [{element: HTMLElement, pos: {lat: float, lng: float, zoom: int},] */

function StoreLocationList(map,locationList) {
	this.map=map;
	this.selectedElement=null;
	this.locationList=locationList;
	this.init();
}
						   
StoreLocationList.prototype.init=function () {
	var obj=this;
	for (var i=0; i< this.locationList.length; i++) {
		(function () {
			var j=i;
			DOMEvent.addDomListener(obj.locationList[j].element, "mouseover", function () {
				DHTMLApi.CSS.setClass(obj.locationList[j].element,["selected"],["not_selected"]);
			});
			
			DOMEvent.addDomListener(obj.locationList[j].element, "mouseout", function () {
				if (obj.selectedElement!=this) {
					DHTMLApi.CSS.setClass(obj.locationList[j].element,["not_selected"],["selected"]);
				}
			});
			DOMEvent.addDomListener(obj.locationList[j].element, "click", function () {
				if (obj.selectedElement !==null) {
					DHTMLApi.CSS.setClass(obj.selectedElement,["not_selected"],["selected"]);
				}
				obj.selectedElement=obj.locationList[j].element;
				obj.map.positionGMap(obj.locationList[j].pos);
			});
		})();
	}
}

////////////////////
// Class StoreMap //
////////////////////

function StoreMap(mapContainerElement, storeCache, markersType) {
	this.mapContainer=mapContainerElement;
	this.storeCache=storeCache;
	this.latDistance = null;
	this.lngDistance = null;
	this.currentlySelectedAdId=null;
	this.mapZoomControls=null;
	this.adMarkers={};
	this.gMap=null;
	this.infoBaloonOverlay=null;
	this.infoToolTip=null;
	this.createGMap(markersType);
}

StoreMap.prototype.createGMap=function(markersType) {
	if (GBrowserIsCompatible()) {
		this.gMap=new GMap2(this.mapContainer);		
		this.mapZoomControls=new MapZoomControls(this);
		this.gMap.addControl(this.mapZoomControls);
		this.gMap.addControl(new MapTypeControls(this.gMap, G_NORMAL_MAP));
		//this.positionGMap({lat: 45.092429, lng: 13.638153, zoom: 11});
		this.positionGMap(this.getAllAdsViewMapData(this.storeCache.getMarkersData(markersType)));
		this.initMapHandlers();
	}
}
	
StoreMap.prototype.positionGMap=function(mapData) {		
	this.mapPosition=new GLatLng(mapData.lat, mapData.lng);
	this.gMap.setCenter(this.mapPosition, mapData.zoom);
}

StoreMap.prototype.getAllAdsViewMapData=function (markersData) {
	var eastBound,westBound,northBound,southBound,targetZoomLevel;
	eastBound=markersData[0].lng;
	westBound=markersData[0].lng;
	northBound=markersData[0].lat;
	southBound=markersData[0].lat;
	for (var i=1; i<markersData.length; i++) {
		if (eastBound<markersData[i].lng) eastBound=markersData[i].lng;
		if (westBound>markersData[i].lng) westBound=markersData[i].lng;
		if (northBound<markersData[i].lat) northBound=markersData[i].lat;
		if (southBound>markersData[i].lat) southBound=markersData[i].lat;
	}
	if (markersData.length==1) {
		targetZoomLevel=13;
	} else {
		targetZoomLevel=this.gMap.getBoundsZoomLevel(new GLatLngBounds(new GLatLng(southBound,westBound),new GLatLng(northBound,eastBound)));
	}
	return {lat: (northBound+southBound)/2, lng: (eastBound+westBound)/2, zoom: targetZoomLevel};
}

StoreMap.prototype.initMapHandlers=function() {
	var obj=this;
	GEvent.addListener(this.gMap,"dblclick",function(latlng) {
		this.zoomIn();
	});
	/*
	GEvent.addListener(this.gMap,"dragend",function() {
		var tempId;
		if (obj.infoBaloonOverlay!==null) {
			if (!obj.isLatLngWithinView(obj.adMarkers[obj.currentlySelectedAdId].marker.getLatLng())) {
				obj.onAdUnselect();
			} else {
				tempId=obj.currentlySelectedAdId;
				obj.onAdUnselect();
				obj.displayAdBaloon(tempId);
			}
		}
	});
	
	GEvent.addListener(this.gMap,"zoomend", function() {
		obj.onAdUnselect();
	});
	*/
}
	
StoreMap.prototype.isLatLngWithinView=function (latLngObject) {
	var bounds=this.gMap.getBounds();
	return bounds.containsLatLng(latLngObject);
}

StoreMap.prototype.onAdUnselect=function() {
	if (typeof this.adMarkers[this.currentlySelectedAdId] != "undefined") {
		this.adMarkers[this.currentlySelectedAdId].displayUnselectedState();
	}
	this.hideInfoBaloon();
	this.currentlySelectedAdId=null;
}

StoreMap.prototype.displayMarkersOfType=function (type) {
	this.hideInfoBaloon();
	this.removeAllMarkers();
	if (typeof type=="string") {
		this.addMarkers(this.storeCache.getMarkersData(type));
	} else if (type.constructor == Array){
		for (var i=0; i<type.length; i++) {
			this.addMarkers(this.storeCache.getMarkersData(type[i]));
		}		
	}
}

StoreMap.prototype.addMarkers=function(markersData) {
	for (var i=0; i<markersData.length; i++) {
		if (typeof this.adMarkers[markersData[i].id]=="undefined") {
			this.adMarkers[markersData[i].id]=new StoreMarker(markersData[i].id,markersData[i].type,markersData[i].lat,markersData[i].lng,markersData[i].text,this);
			this.gMap.addOverlay(this.adMarkers[markersData[i].id].getGMarkerObject());
		}
	}
}
	
StoreMap.prototype.removeAllMarkers=function () {
	for (var markerId in this.adMarkers) this.gMap.removeOverlay(this.adMarkers[markerId].getGMarkerObject());
	this.adMarkers={};
}

StoreMap.prototype.showAdMarkerToolTip=function(adId) {
	if (this.infoToolTip!==null) this.hideToolTip();
	this.infoToolTip=this.adMarkers[adId].getMarkerToolTip();
	this.gMap.addOverlay(this.infoToolTip);
}
		
StoreMap.prototype.hideToolTip=function() {
	if (this.infoToolTip===null) return;
	this.gMap.removeOverlay(this.infoToolTip);
	this.infoToolTip=null;
}
	
StoreMap.prototype.hideInfoBaloon=function() {
	if (this.infoBaloonOverlay!==null) {
		this.gMap.removeOverlay(this.infoBaloonOverlay);
		this.infoBaloonOverlay=null;
	}
}

StoreMap.prototype.displayAdBaloon=function (id) {
	this.infoBaloonOverlay=new StoreMapBaloon(id, this.adMarkers[id].type, this.adMarkers[id].marker,this.storeCache.getAdData(id).getMarkerHtml(),{width: 260, height: 120, horizontalPadding: 5, verticalPadding: 5, baloonAnchorImage: "gfx/baloon_anchor.png", reversedBaloonAnchorImage: "gfx/baloon_anchor_rev.png", closeImage: "gfx/close_btn.gif", closeImagePaddingFromEdge: 5, baloonAnchorImageWidth: 11, baloonAnchorImageHeight: 11, baloonAnchorDistanceFromEdge: 20},this);
	this.currentlySelectedAdId=id;
	this.gMap.addOverlay(this.infoBaloonOverlay);
};


///////////////////////////
// Class MapZoomControls //
///////////////////////////

function MapZoomControls(adMap) {
	this.adMap=adMap;
	this.zoomOutButton=null;
}

MapZoomControls.prototype=new GControl(true);

MapZoomControls.prototype.initialize=function(map) {
	var controlsContainer, zoomInButton;
	var obj=this;
	controlsContainer=document.createElement("DIV");
	DHTMLApi.CSS.setClass(controlsContainer,["mapzoomcontrolscontainer"],[]);
	zoomInButton=document.createElement("DIV");
	zoomInButton.appendChild(document.createTextNode("+"));
	DHTMLApi.CSS.setClass(zoomInButton,["mapzoombutton"],[]);
	this.zoomOutButton=document.createElement("DIV");
	this.zoomOutButton.appendChild(document.createTextNode("-"));
	DHTMLApi.CSS.setClass(this.zoomOutButton,["mapzoombutton"],[]);
	controlsContainer.appendChild(zoomInButton);
	controlsContainer.appendChild(this.zoomOutButton);
	map.getContainer().appendChild(controlsContainer);
	
	DOMEvent.addDomListener(zoomInButton, "mouseover", function () {
		DHTMLApi.CSS.setClass(zoomInButton,["mapbuttonrollover"],[]);
	});
	
	DOMEvent.addDomListener(zoomInButton, "mouseout", function () {
		DHTMLApi.CSS.setClass(zoomInButton,[],["mapbuttonrollover"]);
	});
	
	DOMEvent.addDomListener(zoomInButton, "click", function () {
		map.zoomIn();
	});
	
	DOMEvent.addDomListener(this.zoomOutButton, "mouseover", function () {
		DHTMLApi.CSS.setClass(obj.zoomOutButton,["mapbuttonrollover"],[]);
	});
	
	DOMEvent.addDomListener(this.zoomOutButton, "mouseout", function () {
		DHTMLApi.CSS.setClass(obj.zoomOutButton,[],["mapbuttonrollover"]);
	});
	
	DOMEvent.addDomListener(this.zoomOutButton, "click", function () {
		map.zoomOut();
	});
	
	return controlsContainer;
};

MapZoomControls.prototype.getDefaultPosition=function() {
	return new GControlPosition(G_ANCHOR_TOP_LEFT, new GSize(5,5));
};

///////////////////////////
// Class MapTypeControls //
///////////////////////////

/* parameters: initType - int (index in type list or google map type)
*/

function MapTypeControls(gMap,initType) {
	this.selectedType=G_NORMAL_MAP;
	this.typeList=[G_NORMAL_MAP,G_HYBRID_MAP,G_SATELLITE_MAP];
	if (typeof initType=="number") {
		this.selectedType=initType;
	} else {
		for (var i=0; i<this.typeList.length; i++) {
			if (this.typeList[i]==initType) {
				this.selectedType=i;
				break;
			}
		}
	}
	this.buttons=[];
	gMap.setMapType(this.typeList[this.selectedType]);
}

MapTypeControls.prototype=new GControl(true);

MapTypeControls.prototype.initialize=function(map) {
	var controlsContainer, mapButton, hybridButton, sateliteButton;
	var obj=this;
	controlsContainer=document.createElement("DIV");
	DHTMLApi.CSS.setClass(controlsContainer,["maptypecontrolscontainer"],[]);
	this.buttons[0]=document.createElement("DIV");
	this.buttons[0].appendChild(document.createTextNode("map"));
	DHTMLApi.CSS.setClass(this.buttons[0],["maptypebutton"],[]);
	this.buttons[1]=document.createElement("DIV");
	this.buttons[1].appendChild(document.createTextNode("hybrid"));
	DHTMLApi.CSS.setClass(this.buttons[1],["maptypebutton"],[]);
	this.buttons[2]=document.createElement("DIV");
	this.buttons[2].appendChild(document.createTextNode("satellite"));
	DHTMLApi.CSS.setClass(this.buttons[2],["maptypebutton"],[]);
	controlsContainer.appendChild(this.buttons[2]);
	controlsContainer.appendChild(this.buttons[1]);
	controlsContainer.appendChild(this.buttons[0]);
	map.getContainer().appendChild(controlsContainer);
	
	if (this.selectedType!==null) {
		DHTMLApi.CSS.setClass(this.buttons[this.selectedType],["mapbuttonrollover"],[]);
	}
	
	for (var i=0; i<this.buttons.length;i++) {
		(function () {
			var j=i;

			DOMEvent.addDomListener(obj.buttons[j], "mouseover", function () {
				DHTMLApi.CSS.setClass(obj.buttons[j],["mapbuttonrollover"],[]);
			});
	
			DOMEvent.addDomListener(obj.buttons[j], "mouseout", function () {
				if (obj.selectedType!=j) {
					DHTMLApi.CSS.setClass(obj.buttons[j],[],["mapbuttonrollover"]);
				}
			});
	
			DOMEvent.addDomListener(obj.buttons[j], "click", function () {
				if (obj.selectedType!=j) {
					map.setMapType(obj.typeList[j]);
					DHTMLApi.CSS.setClass(obj.buttons[obj.selectedType],[],["mapbuttonrollover"]);
					obj.selectedType=j;
				}
			});
		}
		)();
	}
	
	return controlsContainer;
};

MapTypeControls.prototype.getDefaultPosition=function() {
	return new GControlPosition(G_ANCHOR_TOP_RIGHT, new GSize(5,5));
};

///////////////////////
// Class StoreMarker //
///////////////////////

function StoreMarker(id,type,lat,lng,rolloverText,adMapObject) {
	this.id=id;
	this.type=type;	
	this.adMapObject=adMapObject;
	this.rolloverText=rolloverText;
	this.mouseOverHandler=null;
	this.mouseOutHandler=null;
	this.clickHandler=null;
	this.marker=new GMarker(new GLatLng(lat,lng));;
	this.initHandlers();
}

StoreMarker.prototype.initHandlers=function() {
	var obj=this;	
	this.mouseOverHandler=GEvent.addListener(this.marker,'mouseover', function() {
		obj.displayRollOverState(obj.id);
	});
	this.mouseOutHandler=GEvent.addListener(this.marker,'mouseout', function() {
		obj.displayRollOutState(obj.id);
	});
	
	/*this.clickHandler=GEvent.addListener(this.marker,'click', function() {
		obj.displaySelectedState();
	});
	*/
};

StoreMarker.prototype.removeHandlers=function() {
	GEvent.removeListener(this.mouseOverHandler);
	GEvent.removeListener(this.mouseOutHandler);
	GEvent.removeListener(this.clickHandler);
	this.mouseOverHandler=this.mouseOutHandler=this.clickHandler=null;
};

StoreMarker.prototype.displaySelectedState=function() {
	var obj=this;
	this.adMapObject.onAdUnselect();
	//this.marker.setImage(MapIconImages[this.type].rollover);
	this.adMapObject.displayAdBaloon(obj.id);
	this.adMapObject.hideToolTip();
};

StoreMarker.prototype.displayUnselectedState=function() {
	if (this.clickHandler!==null) {
		GEvent.removeListener(this.clickHandler);
		this.clickHandler=null;
	}
	this.initHandlers();
	this.marker.setImage(MapIconImages[this.type].normal);
};

StoreMarker.prototype.displayRollOverState=function() {
	//this.marker.setImage(MapIconImages[this.type].rollover);
	this.adMapObject.showAdMarkerToolTip(this.id);
};

StoreMarker.prototype.displayRollOutState=function() {
	//this.marker.setImage(MapIconImages[this.type].normal);
	this.adMapObject.hideToolTip();
};

StoreMarker.prototype.getGMarkerObject=function() {	
	return this.marker;
};

StoreMarker.prototype.getMarkerToolTip=function () {
	return new AdToolTip(this.marker,this.rolloverText,Math.round(this.adMapObject.gMap.getSize().width/2.5),"tooltip");
}


/////////////////////
// Class AdToolTip //
/////////////////////

function AdToolTip(marker,html,maxWidth,cssStyle) {
	this.marker=marker;
	this.html=html;
	this.maxWidth=maxWidth;
	this.cssStyle=cssStyle;
	this.containerElement=null;
	this.gMap=null;
	this.mapContainer=null;
}

AdToolTip.prototype= new GOverlay();

AdToolTip.prototype.initialize=function(map) {
	this.gMap=map;
	this.mapContainer=this.gMap.getContainer();
	this.containerElement=document.createElement("div");
	this.gMap.getPane(G_MAP_FLOAT_PANE).appendChild(this.containerElement);
	DHTMLApi.Visibility.hide(this.containerElement);
};

AdToolTip.prototype.remove=function() {
	this.containerElement.parentNode.removeChild(this.containerElement);
};

AdToolTip.prototype.copy=function() {
	return new AdToolTip(this.marker,this.html,this.maxWidth,this.cssStyle);
};

AdToolTip.prototype.redraw=function(force) {
	var toolTipPosition, toolTipWidth, toolTipHeight;
	if (!force) return;
	DHTMLApi.Visibility.setOpacity(this.containerElement,1);
	DHTMLApi.Visibility.show(this.containerElement);
	this.containerElement.innerHTML=this.html;
	DHTMLApi.CSS.setClass(this.containerElement,[this.cssStyle],[]);
	if (DHTMLApi.Size.getElementWidth(this.containerElement) > this.maxWidth) {
		DHTMLApi.CSS.setProperties(this.containerElement,{whiteSpace:"normal", width: this.maxWidth+"px"});
	} 
	toolTipWidth=DHTMLApi.Size.getElementWidth(this.containerElement);
	toolTipHeight=DHTMLApi.Size.getElementHeight(this.containerElement);
	toolTipPosition=this.getTooltipPosition(3,3,toolTipWidth, toolTipHeight);
	DHTMLApi.Position.setXPos(this.containerElement, toolTipPosition.x, this.mapContainer);
	DHTMLApi.Position.setYPos(this.containerElement, toolTipPosition.y, this.mapContainer);
	DHTMLApi.Visibility.setOpacity(this.containerElement,100);
};

AdToolTip.prototype.getTooltipPosition=function(paddingHorizontal,paddingVertical,toolTipWidth,toolTipHeight) {
	var markerAnchorLocation, markerSize, mapSize, xPos, yPos;	
	markerAnchorLocation=this.gMap.fromLatLngToContainerPixel(this.marker.getLatLng()); // GPoint
	mapSize=this.gMap.getSize(); // GSize
	markerSize=this.marker.getIcon().iconSize; // GSize
	if (markerAnchorLocation.x < Math.round(mapSize.width/2)) {
		xPos=markerAnchorLocation.x + Math.round(markerSize.width/2) + paddingHorizontal;
	} else {
		xPos=markerAnchorLocation.x - Math.round(markerSize.width/2) - toolTipWidth - paddingHorizontal;
	}
	if (markerAnchorLocation.y < markerSize.height) {
		yPos=markerAnchorLocation.y + paddingVertical;
	} else if (markerAnchorLocation.y >= mapSize.height) {
		yPos=markerAnchorLocation.y - markerSize.height - paddingVertical - toolTipHeight;
	} else {
		yPos=markerAnchorLocation.y - markerSize.height;
	}
	return new GPoint(xPos, yPos);
};

//////////////////////////
// class StoreMapBaloon //
//////////////////////////

/*
adBaloonData= {
width: baloon width, 
height: baloon height, 
horizontalPadding: horizontal baloon content padding, 
verticalPadding: veritcal baloon content padding, 
baloonAnchorImage: baloon root image file name, 
reversedBaloonAnchorImage: reversed baloon root image file name,
closeImage: close baloon image file name,
closeImagePaddingFromEdge: padding form edge of baloon window, 
baloonAnchorImageWidth: img width, 
baloonAnchorImageHeight: img height
baloonAnchorDistanceFromEdge: distance of baloon anchor from left and right edges of baloon
}
*/

function StoreMapBaloon(adId,adType,marker,html,adBaloonData,mapObject) {
	this.id=adId;
	this.adType=adType;
	this.marker=marker;
	this.html=html;
	this.adBaloonData=adBaloonData;
	this.mapObject=mapObject;
	this.containerElement=null;
	this.baloonElement=null;
	this.baloonContentElement=null;
	this.baloonAnchorImageElement=null;
	this.closeBaloonButtonImageElement=null;
	this.closeBaloonHandler=null;
	this.gMap=null;
	this.mapContainer=null;
}

StoreMapBaloon.prototype= new GOverlay()

StoreMapBaloon.prototype.addCloseBaloonHandler=function () {
	var obj=this;
	this.closeBaloonHandler=DOMEvent.addDomListener(this.closeBaloonButtonImageElement, "click", function () {obj.mapObject.onAdUnselect();});
};

StoreMapBaloon.prototype.removeHandlers=function () {
	DOMEvent.removeListener(this.closeBaloonHandler);
	this.closeBaloonHandler=null;
};

StoreMapBaloon.prototype.remove=function() {
	this.removeHandlers();
	this.containerElement.parentNode.removeChild(this.containerElement);
};

StoreMapBaloon.prototype.copy=function() {
	return new StoreMapBaloon(this.id,this.type,this.marker,this.html,this.adBaloonData,this.mapObject);
};

StoreMapBaloon.prototype.redraw=function(force) {
	var baloonPosition;
	if (!force) return;
	DHTMLApi.Visibility.setOpacity(this.containerElement,1);
	DHTMLApi.Visibility.show(this.containerElement);
	this.baloonContentElement.innerHTML=this.html;
	baloonPosition=this.getBaloonPosition(3);
	this.arrangeBaloonElements(baloonPosition.pos.x,baloonPosition.pos.y,baloonPosition.reversePosition, baloonPosition.anchorOrientationLeft);
	DHTMLApi.Position.setXPos(this.containerElement, baloonPosition.pos.x, this.mapContainer);
	DHTMLApi.Position.setYPos(this.containerElement, baloonPosition.pos.y, this.mapContainer);
	DHTMLApi.Visibility.setOpacity(this.containerElement,100);
}

StoreMapBaloon.prototype.initialize=function(map) {
	this.gMap=map;
	this.mapContainer=this.gMap.getContainer();
	this.createBaloonElements();
	this.gMap.getPane(G_MAP_FLOAT_PANE).appendChild(this.containerElement);
	DHTMLApi.Visibility.hide(this.containerElement);
	this.addCloseBaloonHandler();
}

StoreMapBaloon.prototype.getBaloonPosition=function(paddingVertical) {
	var markerAnchorLocation, markerSize, markerVerticalAnchor, mapSize, xPos, yPos, reversePos, anchorOrientationLeft;	
	markerAnchorLocation=this.gMap.fromLatLngToContainerPixel(this.marker.getLatLng()); // GPoint
	mapSize=this.gMap.getSize(); // GSize
	markerSize=this.marker.getIcon().iconSize; // GSize
	markerVerticalAnchor=this.marker.getIcon().iconAnchor.y;
	
	if (markerAnchorLocation.x < this.adBaloonData.baloonAnchorDistanceFromEdge) {
		xPos=0;
	} else if (markerAnchorLocation.x > mapSize.width-this.adBaloonData.baloonAnchorDistanceFromEdge) {
		xPos=mapSize.width - this.adBaloonData.width;
	} else if (markerAnchorLocation.x < Math.round((mapSize.width - this.adBaloonData.width)/2) + this.adBaloonData.baloonAnchorDistanceFromEdge) {
		xPos=markerAnchorLocation.x - this.adBaloonData.baloonAnchorDistanceFromEdge;
	} else if (markerAnchorLocation.x > Math.round((mapSize.width + this.adBaloonData.width)/2) - this.adBaloonData.baloonAnchorDistanceFromEdge) {
		xPos=markerAnchorLocation.x - this.adBaloonData.width + this.adBaloonData.baloonAnchorDistanceFromEdge;
	} else {
		xPos=Math.round((mapSize.width - this.adBaloonData.width)/2);
	}
	
	if (markerAnchorLocation.y > Math.round(mapSize.height/2)+20) {
		yPos=markerAnchorLocation.y - paddingVertical - markerVerticalAnchor - this.adBaloonData.height - this.adBaloonData.baloonAnchorImageHeight;
		reversePos=false;
	} else {
		yPos=markerAnchorLocation.y + markerSize.height - markerVerticalAnchor + paddingVertical;
		reversePos=true;
	}
	return {pos: new GPoint(xPos, yPos), reversePosition: reversePos};
}

StoreMapBaloon.prototype.setBaloonAnchorXPosition=function (posX) {
	var markerAnchorLocation, mapWidth, leftPos;
	
	markerAnchorLocation=this.gMap.fromLatLngToContainerPixel(this.marker.getLatLng()); // GPoint
	mapWidth=this.gMap.getSize().width;
	leftPos=markerAnchorLocation.x-posX-Math.round(this.adBaloonData.baloonAnchorImageWidth/2);
	if (leftPos < 0) leftPos=0;
	if (leftPos > this.adBaloonData.width-this.adBaloonData.baloonAnchorImageWidth) leftPos=this.adBaloonData.width-this.adBaloonData.baloonAnchorImageWidth;
	DHTMLApi.CSS.setProperties(this.baloonAnchorImageElement,{left: leftPos + "px"});
}

StoreMapBaloon.prototype.getAdId=function () {
	return this.id;
}
	
StoreMapBaloon.prototype.getAdType=function () {
	return this.adType;
}
	
StoreMapBaloon.prototype.createBaloonElements=function() {
	this.containerElement=document.createElement("div");
	this.baloonElement=document.createElement("div");
	this.containerElement.appendChild(this.baloonElement);
	this.baloonContentElement=document.createElement("div");
	this.baloonElement.appendChild(this.baloonContentElement);
	this.baloonAnchorImageElement=document.createElement("img");
	this.containerElement.appendChild(this.baloonAnchorImageElement);
	this.closeBaloonButtonImageElement=document.createElement("img");
	this.baloonElement.appendChild(this.closeBaloonButtonImageElement);
}
	
StoreMapBaloon.prototype.arrangeBaloonElements=function(posX,posY,reversePosition, anchorOrientationLeft) {
	DHTMLApi.CSS.setProperties(this.containerElement,{width: this.adBaloonData.width+"px", height: (this.adBaloonData.height+this.adBaloonData.baloonAnchorImageHeight)+"px", position:"absolute"});
	DHTMLApi.CSS.setProperties(this.baloonContentElement,{width: (this.adBaloonData.width-2*(this.adBaloonData.horizontalPadding+1))+"px", height: (this.adBaloonData.height-2*(this.adBaloonData.verticalPadding+1))+"px", position: "absolute", top: this.adBaloonData.verticalPadding+"px", left: this.adBaloonData.horizontalPadding+"px"});
	this.closeBaloonButtonImageElement.setAttribute("src",this.adBaloonData.closeImage);
	DHTMLApi.CSS.setProperties(this.closeBaloonButtonImageElement, {position: "absolute", top: this.adBaloonData.closeImagePaddingFromEdge +"px", right: this.adBaloonData.closeImagePaddingFromEdge +"px", cursor: "pointer"});
	if (reversePosition) {
		DHTMLApi.CSS.setProperties(this.baloonElement,{width: (this.adBaloonData.width-2)+"px", height: (this.adBaloonData.height-2)+"px", position: "absolute", left: "0px", top: (this.adBaloonData.baloonAnchorImageHeight-1)+"px",backgroundColor: "#FFFFFF", border: "1px solid #000000", zIndex:1});
		this.baloonAnchorImageElement.setAttribute("src",this.adBaloonData.reversedBaloonAnchorImage);
		DHTMLApi.CSS.setProperties(this.baloonAnchorImageElement,{position: "absolute", top: "0px", zIndex:2});
	} else {
		DHTMLApi.CSS.setProperties(this.baloonElement,{width: (this.adBaloonData.width-2)+"px", height: (this.adBaloonData.height-2)+"px", position: "absolute", left: "0px", top: "1px", backgroundColor: "#FFFFFF", border: "1px solid #000000", zIndex:1});
		this.baloonAnchorImageElement.setAttribute("src",this.adBaloonData.baloonAnchorImage);
		DHTMLApi.CSS.setProperties(this.baloonAnchorImageElement,{position: "absolute", bottom:"0px", zIndex:2});
	}
	DHTMLApi.CSS.setProperties(this.baloonAnchorImageElement, {width: this.adBaloonData.baloonAnchorImageWidth+"px", height: this.adBaloonData.baloonAnchorImageHeight+"px"});
	this.setBaloonAnchorXPosition(posX);
}
