function implementsInterface() {
	var prototypeObj=new Object();
	for (var i=0; i<arguments.length; i++) {
		for (var method in arguments[i]) {
			prototypeObj[method]=arguments[i][method];
		}	
	}
	return prototypeObj;
}

//////////////////////////
// Interface Observable //
//////////////////////////

Observable = {
	addListener : function(listenerObj) {
		if (typeof this.listeners == 'undefined') {
			this.listeners=new Array();
		}
		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);
			}
		}
	}
}


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

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


/////////////////////////////////////
// Class Animation.ContinuousVMove //
/////////////////////////////////////

Animation.ContinuousVMove=function(movingObject, relativeToObject, increment) {
	this.movingObject=movingObject;
	this.relativeToObject=relativeToObject;
	this.currentYPos=DHTMLApi.Position.getYPosInElement(movingObject,relativeToObject);
	this.interval=null;
	if (typeof increment != "undefined") {
		this.increment=increment;
	} else {
		this.increment=1;
	}
}

Animation.ContinuousVMove.prototype=implementsInterface(Observable);

Animation.ContinuousVMove.prototype.start=function (increment) {
	if (this.interval!==null) {
		window.clearInterval(this.interval);
		this.notifyListeners("onAnimationEnd",null);
	}
	var animationObject=this;
	if (typeof increment != "undefined") {
		this.increment=increment;
	}
	this.notifyListeners("onAnimationStart",null);
	this.interval=window.setInterval(function() {animationObject.animate()},Animation.FRAME_RATE);
}

Animation.ContinuousVMove.prototype.stop=function () {
	window.clearInterval(this.interval);
	this.notifyListeners("onAnimationEnd",null);
}

Animation.ContinuousVMove.prototype.animate=function () {
	this.currentYPos+=this.increment;
	DHTMLApi.Position.setYPos(this.movingObject, this.currentYPos, this.relativeToObject);
	this.notifyListeners("onAnimationStep",this.currentYPos);
}

Animation.ContinuousVMove.prototype.setYPosition=function (yPosition) {
	this.currentYPos=yPosition;
	DHTMLApi.Position.setYPos(this.movingObject, this.currentYPos, this.relativeToObject);
}

//////////////////////////////////
// Class Animation.SmoothResize //
//////////////////////////////////

Animation.SmoothResize=function(resizingObject) {
	this.resizingObject=resizingObject;
	this.currentWidth=DHTMLApi.Size.getElementWidth(this.resizingObject);
	this.currentHeight=DHTMLApi.Size.getElementHeight(this.resizingObject);
	this.proportionsRatio=1.0*this.currentWidth/this.currentHeight;
	this.maintainProportions=true;
	this.targetWidth=null;
	this.targetHeight=null;
	this.interval=null;
	this.currentAnimationStep=null;
}

Animation.SmoothResize.prototype=implementsInterface(Observable);

Animation.SmoothResize.prototype.setSize=function (targetWidth,targetHeight,maintainProportions) {
	if (this.interval!==null) {
		window.clearInterval(this.interval);
		this.notifyListeners("onAnimationEnd",null);
	}
	var animationObject=this;
	this.targetWidth=targetWidth;
	this.targetHeight=targetHeight;
	this.maintainProportions=maintainProportions;
	this.currentAnimationStep=0;
	this.notifyListeners("onAnimationStart",null);
	this.animate();
	this.interval=window.setInterval(function() {animationObject.animate()},Animation.FRAME_RATE);
}

Animation.SmoothResize.prototype.animate=function () {
	var stepWidth=1.0*(this.targetWidth-this.currentWidth)/1.5;
	var stepHeight=1.0*(this.targetHeight-this.currentHeight)/1.5;
	if (((Math.abs(stepWidth)>0.3 || Math.abs(stepHeight)>0.3) && !this.maintainProportions) || (this.maintainProportions && Math.abs(stepWidth)>0.3)) {
		if (this.maintainProportions) {
			this.currentWidth+=stepWidth;
			this.currentHeight=this.currentWidth/this.proportionsRatio;
		} else {
			this.currentWidth+=stepWidth;
			this.currentHeight+=stepHeight;			
		}		
		DHTMLApi.CSS.setProperties(this.resizingObject, {width: Math.round(this.currentWidth)+"px", height:Math.round(this.currentHeight)+"px"});
		++this.currentAnimationStep;
		this.notifyListeners("onAnimationStep",this.currentAnimationStep);
		return this.currentAnimationStep;
	} else {
		if (this.maintainProportions) {
			this.currentWidth=this.targetWidth;
			this.currentHeight=Math.round(this.currentWidth/this.proportionsRatio);
		} else {
			this.currentWidth=this.targetWidth;
			this.currentHeight=this.targetHeight;			
		}			
		DHTMLApi.CSS.setProperties(this.resizingObject, {width: this.currentWidth+"px", height:this.currentHeight+"px"});
		this.notifyListeners("onAnimationStep",++this.currentAnimationStep);
		window.clearInterval(this.interval);
		this.notifyListeners("onAnimationEnd",null);
		this.currentAnimationStep=null;
		return false;
	}
}


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

function SlideShow(imagesUrlArray, containerElement, slideDurationInSec, numOfTransitionIterations, numOfTransitionMixIterations) {
	this.container=containerElement;
	this.imagesUrlArray=imagesUrlArray;
	this.numOfImagesPreloaded=1;
	this.preloadIsOn=false;
	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.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.preload=function() {
	var obj=this;
	if (this.numOfImagesPreloaded>=this.imagesUrlArray.length) return; 
	this.preloadIsOn=true;
	var img=new Image();
	img.onload=function () {
		obj.numOfImagesPreloaded++;
		if (obj.preloadIsOn) {
			obj.preload();
		}
	}
	img.src=this.imagesUrlArray[this.numOfImagesPreloaded];
}

SlideShow.prototype.stopPreload=function() {
	this.preloadIsOn=false;
}

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.preload();
	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.stopPreload();
	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);
}

///////////////////////////////////
// Class PhotoGalleryThumbScroll //
///////////////////////////////////

/* parameters:
GUIelements= {photoContainer: , thumbScroll: , thumbContainer: , nextPhotoSetButton: , previousPhotoSetButton: , nextPhotoButton: , previousPhotoButton:}
*/

function PhotoGalleryThumbScroll(GUIelements,imagesUrlArray,thumbsUrlArray,thumbHeight,numOfThumbsPerPage) {
	this.photoContainerDiv=GUIelements.photoContainer;
	this.thumbContainer=GUIelements.thumbContainer;
	this.scrollContainer=GUIelements.thumbScroll;
	this.numOfThumbsPerPage=numOfThumbsPerPage;
	this.thumbForwardButton=GUIelements.nextPhotoSetButton;
	this.thumbBackwardButton=GUIelements.previousPhotoSetButton;
	this.picForwardButton=GUIelements.nextPhotoButton;
	this.picBackwardButton=GUIelements.previousPhotoButton;
	this.thumbnailHeight=thumbHeight;
	this.thumbnailUrl=thumbsUrlArray;
	this.thumbnailPictureObjects= new Array();
	this.currentThumbSet=null;
	this.numOfThumbSets=null;
	this.currentPhoto=null;
	this.numberOfPhotos=imagesUrlArray.length;
	this.thumbScroller=new Animation.SmoothVMove(this.thumbContainer, this.scrollContainer);
	this.slideShow=new SlideShow(imagesUrlArray, this.photoContainerDiv, 5, 25, 20);
}

PhotoGalleryThumbScroll.prototype.init= function () {
	var obj=this;
	this.initThumbs();
	
	DOMEvent.addDomListener(this.photoContainerDiv,"click", function (event) {
		if (obj.slideShow.slideShowIsPlaying) {
			obj.slideShow.stop();
			obj.currentPhoto=obj.slideShow.currentSlide;
			obj.setThumbSet(obj.getThumbSetNum(obj.currentPhoto));
		} else {
			obj.slideShow.play();
		}
	});
	
	DOMEvent.addDomListener(this.picForwardButton,"click", function (event) {
		obj.slideShow.displayNextSlide();
		obj.currentPhoto=obj.slideShow.currentSlide;
		obj.setThumbSet(obj.getThumbSetNum(obj.currentPhoto));
	});
	
	DOMEvent.addDomListener(this.picBackwardButton,"click", function (event) {
		obj.slideShow.displayPreviousSlide();
		obj.currentPhoto=obj.slideShow.currentSlide;
		obj.setThumbSet(obj.getThumbSetNum(obj.currentPhoto));
	});

	this.currentThumbSet=1;
	this.numOfThumbSets=Math.ceil(this.numberOfPhotos/this.numOfThumbsPerPage);
	this.currentPhoto=1;
}

PhotoGalleryThumbScroll.prototype.getThumbSetNum= function (photoNum) {
	return Math.ceil(photoNum/this.numOfThumbsPerPage); 
}

PhotoGalleryThumbScroll.prototype.getCurrentPhoto= function () {
	return this.currentPhoto; 
}

PhotoGalleryThumbScroll.prototype.calculateScrollPosition=function (targetThumbSet) {
	var numOfPhotosInLastSet;
	numOfPhotosInLastSet=this.numberOfPhotos % this.numOfThumbsPerPage;
	
	if (this.numOfThumbSets==targetThumbSet && this.numOfThumbSets>1 && numOfPhotosInLastSet!=0) {
		return -1*((targetThumbSet-2)*this.numOfThumbsPerPage+numOfPhotosInLastSet)*this.thumbnailHeight;
	}	else {
		return -1*(targetThumbSet-1)*this.thumbnailHeight*this.numOfThumbsPerPage;
	}
}

PhotoGalleryThumbScroll.prototype.setThumbSet=function (numOfThumbSet) {
	this.currentThumbSet=numOfThumbSet;
	this.thumbScroller.setPosition(this.calculateScrollPosition(numOfThumbSet));
}

PhotoGalleryThumbScroll.prototype.initThumbs= function () {
	var photoGalleryThumbScrollObj;
	photoGalleryThumbScrollObj=this;
	while (this.thumbContainer.hasChildNodes()) this.thumbContainer.removeChild(this.thumbContainer.firstChild);
	for (var i=0;i<this.numberOfPhotos;i++) {
		this.thumbnailPictureObjects[i]=document.createElement("IMG");
		this.thumbnailPictureObjects[i].num=i+1;
		this.thumbnailPictureObjects[i].setAttribute("src",this.thumbnailUrl[i]);
		this.thumbnailPictureObjects[i].style.cursor="pointer";
		this.thumbContainer.appendChild(this.thumbnailPictureObjects[i]);
		this.thumbnailPictureObjects[i].onclick=function () {
			photoGalleryThumbScrollObj.displayPhoto(this.num);
		}
	}
	this.thumbForwardButton.onclick= function () {
		if (photoGalleryThumbScrollObj.currentThumbSet!=photoGalleryThumbScrollObj.numOfThumbSets) {
			photoGalleryThumbScrollObj.setThumbSet(photoGalleryThumbScrollObj.currentThumbSet+1);
		} else {
			photoGalleryThumbScrollObj.setThumbSet(1);
		}
		
	}
	
	this.thumbBackwardButton.onclick= function () {
		if (photoGalleryThumbScrollObj.currentThumbSet>1) {
			photoGalleryThumbScrollObj.setThumbSet(photoGalleryThumbScrollObj.currentThumbSet-1);
		} else {
			photoGalleryThumbScrollObj.setThumbSet(photoGalleryThumbScrollObj.numOfThumbSets);
		}
	}
	
	this.thumbContainer.style.height=this.numberOfPhotos*this.thumbnailHeight+"px";
}

PhotoGalleryThumbScroll.prototype.displayPhoto=function(photoNum) {
	this.slideShow.display(photoNum);
	this.currentPhoto=photoNum;
}

//////////////////////
// Class TabbedMenu //
//////////////////////

/* cssClasses = {rollover: , selected:} */

function TabbedMenu(cssClasses) {
	this.selectedTab= null;
	this.cssClasses= cssClasses;
	this.tabContent= new Object();
}

TabbedMenu.prototype.isSelected=function (tabId) {
	return (this.selectedTab==tabId) ? true:false;
}

TabbedMenu.prototype.initTab=function (tabId) {
	var tabElement;
	var obj=this;
	tabElement=document.getElementById(tabId);
	DOMEvent.addDomListener(tabElement, "mouseover", function () {
		if (!obj.isSelected(tabId)) {
			DHTMLApi.CSS.setClass(tabElement,new Array(obj.cssClasses.rollover),new Array());
		}
	});
	
	DOMEvent.addDomListener(tabElement, "mouseout", function () {
		if (!obj.isSelected(tabId)) {
			DHTMLApi.CSS.setClass(tabElement,new Array(),new Array(obj.cssClasses.rollover));
		}
	});
	
	DOMEvent.addDomListener(tabElement, "click", function () {
		if (!obj.isSelected(tabId)) {
			obj.select(tabId);
		}
	});
}

TabbedMenu.prototype.add=function (tabId,contentId) {
	this.tabContent[tabId]=document.getElementById(contentId);
	this.initTab(tabId);
}

TabbedMenu.prototype.select=function (tabId) {
	var tabElement;
	tabElement=document.getElementById(tabId);
	if (this.selectedTab!==null) {
		this.unselect(this.selectedTab);
	}
	this.selectedTab=tabId;
	DHTMLApi.CSS.setClass(tabElement,new Array(obj.cssClasses.selected),new Array(obj.cssClasses.rollover));
	DHTMLApi.Visibility.show(this.tabContent[tabId]);
}

TabbedMenu.prototype.unselect=function (selectedTabId) {
	DHTMLApi.CSS.setClass(tabElement,new Array(),new Array(obj.cssClasses.selected));
	DHTMLApi.Visibility.hide(this.tabContent[tabId]);
}


///////////////////////
// Class AutoVScroll //
///////////////////////

function AutoVScroll(maskElement,contentElement,increment) {
	this.mask=maskElement;
	this.content=contentElement;
	this.container=null;
	this.animation=null;
	this.contentHeight=null;
	if (DHTMLApi.Size.getElementHeight(this.mask)>DHTMLApi.Size.getElementHeight(this.content)) return;
	this.build();
	this.init(-1*increment);
}

AutoVScroll.prototype.build=function () {
	var duplicate, contentWidth;
	this.contentHeight=DHTMLApi.Size.getElementHeight(this.content);
	this.container=document.createElement("DIV");
	tempContent = this.mask.removeChild(this.content);
	this.container.appendChild(tempContent);
	duplicate=this.content.cloneNode(true);
	this.container.appendChild(duplicate);
this.mask.appendChild(this.container);
	contentWidth=DHTMLApi.Size.getElementWidth(this.content);
	DHTMLApi.CSS.setProperties(this.container, {width: contentWidth+"px", height: this.contentHeight+"px"});
	
}

AutoVScroll.prototype.init=function (increment) {
	var obj=this;
	this.animation=new Animation.ContinuousVMove(this.container, this.mask, increment);
	this.animation.addListener(this);
	this.animation.start();
	DOMEvent.addDomListener(this.mask, "mouseover", function () {
		obj.animation.stop();
	});
	DOMEvent.addDomListener(this.mask,"mouseout", function () {
		obj.animation.start();
	});
}

AutoVScroll.prototype.onAnimationStep=function (currentYPostion) {
	if (Math.abs(currentYPostion)>=this.contentHeight) {
		this.animation.setYPosition(this.contentHeight-Math.abs(currentYPostion));
	}
}


///////////////////////////
// Class BreadcrumbsMenu //
///////////////////////////

function BreadCrumbsMenu(rootLabel, dividerElement, containerElement) {
	this.containerElement=containerElement;
	this.dividerElement=dividerElement;
	this.undoHandlers=new Array();
	this.crumbClickHandlers=new Array();
	this.crumbs=new Array();
	this.numOfMenuLevels=1;
	this.init(rootLabel);
}

BreadCrumbsMenu.prototype.init=function(rootLabel) {
	var rootCrumb;
	var obj=this;
	rootCrumb=document.createElement("SPAN");
	rootCrumb.appendChild(document.createTextNode(rootLabel));
	this.crumbs[0]=rootCrumb;
	this.crumbClickHandlers[0]=DOMEvent.addDomListener(this.crumbs[0], "click", function () {
		obj.undo(1);
	});
	this.undoHandlers[0]=null;
	this.containerElement.appendChild(rootCrumb);
}

BreadCrumbsMenu.prototype.undo=function (menuLevel) {
	for (var i=this.numOfMenuLevels-1; i>=menuLevel; i--) {
		(this.undoHandlers[i])();
		DOMEvent.removeListener(this.crumbClickHandlers[i]);
		this.undoHandlers.splice(i,1);
		this.crumbClickHandlers.splice(i,1);
	}
	this.numOfMenuLevels=menuLevel;
	this.removeCrumbs(menuLevel);
}

BreadCrumbsMenu.prototype.removeCrumbs=function (lastMenuLevel) {
	var numOfNodesAfterRemove=null;
	for (var i=0; i<this.containerElement.childNodes.length; i++) {
		if (this.containerElement.childNodes[i]==this.crumbs[lastMenuLevel-1]) {
			numOfNodesAfterRemove=i+1;
			break;
		} 			
	}	
	while (this.containerElement.childNodes.length>numOfNodesAfterRemove) this.containerElement.removeChild(this.containerElement.lastChild);
}

BreadCrumbsMenu.prototype.addCrumb=function(label, undoHandler) {
	var numOfMenuLevels;
	var obj=this;
	var crumb=document.createElement("SPAN");
	this.numOfMenuLevels++;
	crumb.appendChild(document.createTextNode(label));
	this.crumbs.push(crumb);
	this.containerElement.appendChild(this.dividerElement.cloneNode(true));
	this.containerElement.appendChild(crumb);
	this.undoHandlers.push(undoHandler);
	numOfMenuLevels=this.numOfMenuLevels;
	this.crumbClickHandlers[this.numOfMenuLevels-1]=DOMEvent.addDomListener(this.crumbs[this.numOfMenuLevels-1], "click", function () {
		obj.undo(numOfMenuLevels);
	});
}


function AtlanticMenu (menuContainerId, defaultContent) {
	this.menuContainerId=menuContainerId;
	this.defaultContent=defaultContent;
	this.selectedMenuId=null;
	this.menuItems=new Object();
	this.contextualMenus=new Object();
}

AtlanticMenu.prototype.add=function (menuItemId,contextualMenuId) {
	this.menuItems[menuItemId]=document.getElementById(menuItemId);
	this.contextualMenus[menuItemId]=document.getElementById(contextualMenuId);
}

AtlanticMenu.prototype.init=function () {
	var obj=this;
	for (var menuItemId in this.menuItems) {
		(function () {
			var id=menuItemId;
			DOMEvent.addDomListener(obj.menuItems[id], "mouseover", function () {
				if (obj.selectedMenuId!==null) {
					DHTMLApi.Visibility.hide(obj.contextualMenus[obj.selectedMenuId]);
				}
				DHTMLApi.Visibility.hide(obj.defaultContent);
				DHTMLApi.Visibility.show(obj.contextualMenus[id]);
				obj.selectedMenuId=id;
			});
		})();
	}
	
	HotSpot.init();
	HotSpot.add(this.menuContainerId,null,function () {
		if (obj.selectedMenuId!==null) {	
			DHTMLApi.Visibility.hide(obj.contextualMenus[obj.selectedMenuId]);
			DHTMLApi.Visibility.show(obj.defaultContent);
			obj.selectedMenuId=null;
		}
	});
	
	/*DOMEvent.addDomListener(this.menuContainer, "mouseout", function () {
		if (obj.selectedMenuId!==null) {	
			DHTMLApi.Visibility.hide(obj.contextualMenus[obj.selectedMenuId]);
			DHTMLApi.Visibility.show(obj.defaultContent);
			obj.selectedMenuId=null;
		}
	});*/	
}

//////////////////////////
// Static Class HotSpot //
//////////////////////////

HotSpot= new Object();

HotSpot.init=function () {
	var obj=this;
	this.hotSpots=new Object();
	DOMEvent.addDomListener(document.body, "mousemove", function (mouseEvent) {
		HotSpot.check(mouseEvent);
	});
	DOMEvent.addDomListener(window, "resize", function () {
		/*var interval;
		interval=window.setInterval(function () {obj.update();window.clearInterval(interval);}, 50);*/
		obj.update();
	});
}

HotSpot.update=function () {
	for (var hotSpotId in this.hotSpots) {
		this.hotSpots[hotSpotId].bounds=this.getBounds(this.hotSpots[hotSpotId].element);
	}
}

HotSpot.add=function (elementId,onMouseOverHandler,onMouseOutHandler) {
	var hotSpotObject=new Object();
	var element=document.getElementById(elementId);
	hotSpotObject.element=element;
	hotSpotObject.bounds=HotSpot.getBounds(element);
	hotSpotObject.onMouseOverHandler=onMouseOverHandler;
	hotSpotObject.onMouseOutHandler=onMouseOutHandler;
	hotSpotObject.mouseIsInHotSpot=null;
	this.hotSpots[elementId]=hotSpotObject;
}

HotSpot.remove=function (elementId) {
	delete this.hotSpots[elementId];
}

// private

HotSpot.getBounds=function (element) {
	return {left: DHTMLApi.Position.getXPosOnPage(element), top: DHTMLApi.Position.getYPosOnPage(element), right: DHTMLApi.Position.getXPosOnPage(element)+DHTMLApi.Size.getElementWidth(element), bottom: DHTMLApi.Position.getYPosOnPage(element)+DHTMLApi.Size.getElementHeight(element)};
}

HotSpot.check=function (mouseEvent) {
	var hotSpot;
	for (var hotSpotId in this.hotSpots) {
		hotSpot=this.hotSpots[hotSpotId];
		if (hotSpot.bounds.left < MousePositionOnPage.getX(mouseEvent) && hotSpot.bounds.right > MousePositionOnPage.getX(mouseEvent) && hotSpot.bounds.top < MousePositionOnPage.getY(mouseEvent) && hotSpot.bounds.bottom > MousePositionOnPage.getY(mouseEvent)) {
			if (hotSpot.mouseIsInHotSpot===false || hotSpot.mouseIsInHotSpot===null) {
				if (hotSpot.onMouseOverHandler!==null) {
					hotSpot.onMouseOverHandler();
				}
				hotSpot.mouseIsInHotSpot=true;
			}
		} else {
			if (hotSpot.mouseIsInHotSpot===true || hotSpot.mouseIsInHotSpot===null) {
				if (hotSpot.onMouseOutHandler!==null) {
					hotSpot.onMouseOutHandler();
				}
				hotSpot.mouseIsInHotSpot=false;
			}
		}
	}
}
