/*
** Photo Slider 1.0 08/08/07
**  Author: Jesse Janzer
**   jjanzer@lanthera.net http://jjanzer.subculture.org
**  Tutorial Site: http://opiefoto.com/articles/slider
**
** You may use this library for any purpose.
**
** If you find it useful feel free to give me credit and link to
**  the original tutorial site http://opiefoto.com/articles/slider
*/

var FOTO = { };
var SKEL = { };
SKEL.EFFECTS = { };


FOTO.Slider = {
	newSrc: null,
	prevThumb: null,
	prevContent: '',
	discrShown: 0,
	hidenOpac: 0.5,  //opacity value for "hiding" unactive  thumbs
	videoFile: '',	
	doAlert: 0,
	playerMarginB: 0,
	player: null,
	curentButton: '', //current top button,  chosen in  menu
	curentContent: '#photocontainer', // curent content ID for hide/show 
	//curentContent: '#video', // curent content ID for hide/show 
	bucket : { }, //a hash containing our thumbnails & images
	imageCache : { }, //cache of the images so the preloaded images aren't overwritten in some browsers
	descr: {}, // if a bucket has a description
	loadingURL : '../../images/loading.gif',
	baseURL : 'images/',
	thumbURL : 't_{ID}.jpg',
	mainURL : '{ID}.jpg',
	containerID : 'photocontainer',
	curKey :'',
    mouseX: 0,
	mouseY: 0,
	cH: 0,//content height
	iH: 0,//max image height
	iH0: 0,
	iW: 0,//max image width;
	cW: 0,//content widht
	firstThumb: 0,
	contentBorder: 0,
	margins: 10,
	margTop: 5,
	margBot: 10,
	curH: 0,
	curW: 0,
	navW: 720,
	barW: 0,
	barMaxX: 0,
	barMinX: 0,
	windowWidth: 0,
	windowHeight: 0,
	marginLeft: 0,
	discrAndThumbH: 145,
	thumbH: 85,
	imgBorder: 2,
	thumbBar: null,
	duration: 4000, //how long do we look at each image?
	sliderMainWrap: null,
	sliderMainImg: null,
	scrollL : 0,
	slideInterval: null,
	sliderNav: null,
	slideShowBtn: null,
	curNSlot: 0,
	isPreloading: {},

	data : { }, //contains things like current offset, paused, etc keyed off of the slider id	


	getContentHeight: function() {
		var h1 = $('#wrapper').height();
		var h2 = $('#top').height();
		var h3 = $('#footer').height();
		var windowHeight = window.innerHeight ? window.innerHeight : document.documentElement.clientHeight ? document.documentElement.clientHeight : document.body.clientHeight;
		var windowWidth  = window.innerWidth  ? window.innerWidth  : document.documentElement.clientWidth  ? document.documentElement.clientWidth  : document.body.clientWidth ;
		var myWidth = 0, myHeight = 0;
		if( typeof( window.innerWidth ) == 'number' ) {
			//Non-IE
			myWidth = window.innerWidth;
			myHeight = window.innerHeight;
		} else if( document.documentElement && ( document.documentElement.clientWidth || document.documentElement.clientHeight ) ) {
			//IE 6+ in 'standards compliant mode'
			myWidth = document.documentElement.clientWidth;
			myHeight = document.documentElement.clientHeight;
		} else if( document.body && ( document.body.clientWidth || document.body.clientHeight ) ) {
			//IE 4 compatible
			myWidth = document.body.clientWidth;
			myHeight = document.body.clientHeight;
		}		
		var curTotH = $('#site-container-wrapper').height();
		var curTotW = $('#site-container-wrapper').width();
		var curTotWinside = $('#site-container').width();
		this.cH = myHeight - curTotH - this.margTop - this.margBot;			
		this.iH = this.cH - this.discrAndThumbH;
		this.cW = curTotWinside;
		this.iW = this.cW - 2* this.imgBorder;
		this.marginLeft =  (myWidth - curTotW)/2;		
		//$('#site-container-wrapper').css('margin-left',this.marginLeft+'px');
		var marginLin = (curTotW-curTotWinside)/2;
		//$('#site-container').css('margin-left',marginLin+'px');
		this.windowWidth = myWidth;
		this.windowHeight = myHeight;
	},
	
	//returns the URL for our thumbnails and large images
	getUrlFromId: function(key,id,isThumb){

		//do we have this url in our bucket?
		if(this.bucket[key] != null && this.bucket[key][id] != null){
			if(isThumb && this.bucket[key][id]['thumb'] != null){
				return this.baseURL+this.bucket[key][id]['thumb'];
			} else if (!isThumb && this.bucket[key][id]['main'] != null){
			return this.baseURL+this.bucket[key][id]['main'];
			}
		}

		//we don't have it stored, so generate it
		if(isThumb)
			return this.thumbURL.replace('{ID}',id);
		return this.mainURL.replace('{ID}',id);
	},

	//returns the caption for the image
	getCaptionFromId: function(key,id){
		if(this.bucket[key] != null && this.bucket[key][id] != null){
			return this.bucket[key][id]['caption'];
		}
	},

	//ids is just an array
	importBucketFromIds: function(key,ids){
		this.bucket[key] = new Object(); //replace any existing entries with this new set		
		for(i in ids){
			//ids[i]  --> j
			this.bucket[key][i] = new Object(); //there isn't any reason to pre-store the urls for this
			this.bucket[key][i]['thumb'] = this.thumbURL.replace('{ID}',ids[i]);
			this.bucket[key][i]['main'] = this.mainURL.replace('{ID}',ids[i]);
			this.bucket[key][i]['caption'] = '';			
		}
	},

	buildThumbBar: function(key,bar){
		if(this.bucket[key] == null){
			return false;
		}

		var slot = 0;

		for(i in this.bucket[key]){
			var div = $(document.createElement('div'));
			div.attr('imageid',i);
			div.attr('slot',slot++);
			//div.attr('selected',0);
			div.addClass('photoslider_thumb');

			var img = document.createElement('img');
			img.src = this.getUrlFromId(key,i,true);

			//attach the image to the div
			div.append(img);

			//attach the div to our thumbnail bar
			$(bar).append(div);
			
			if (i==0) {
				this.firstThumb = div;
			}

			//calc the width (needed for later)
			/*this.data[key]['thumbWidth'] =
				parseInt(div.css('width'))
				+parseInt(div.css('border-left-width'))
				+parseInt(div.css('border-right-width'))
				+parseInt(div.css('margin-left'))
				+parseInt(div.css('margin-right'))
				+parseInt(div.css('padding-left'))
				+parseInt(div.css('padding-right'));*/
		}

		//we need to add a clear since we have floating divs
		var clear = document.createElement('div');
		$(clear).addClass('photoslider_clear');

		//finally we need to force the width of the bar so that the divs don't wrap to the next line
		// we give it 1 extra slot just for buffer
		this.barW = ((slot)*this.data[key]['thumbWidth']);
		//var barW = ((slot+1)*this.data[key]['thumbWidth']);
		$(bar).css('width',this.barW+'px')
		//$(bar).css('height',((slot+1)*this.data[key]['thumbWidth'])+'px')
		$(bar).append(clear);
		if (this.barW<this.navW) {
			var marginLin = (this.navW-this.barW)/2;
			$(bar).css('margin-left',marginLin+'px');
		} else {
			this.barMaxX = 0;
			this.barMinX = this.navW-this.barW;
		}
		this.curNSlot = slot;
	},

	//loads in the slideshow, replaces the existing one if set
	reload: function(key){
		if (this.curKey == key) {
			return;
		}
		this.curKey = key;
		if(this.data[key] == null){
			this.data[key] = new Object();
		}

		this.data[key]['thumbWidth'] = 62;
		this.data[key]['paused'] = true;
		this.data[key]['currentSlot'] = 0;// current slot in thumbnails bar
		this.data[key]['currentId'] = null;// current iD of an image in  "key"

		
		//this.getContentHeight();
		//var sliderDiv = $('#'+key);
		var sliderDiv = $('#'+this.containerID);
		sliderDiv.addClass('photoslider');
		$(sliderDiv).css('height',this.cH+'px');
		$(sliderDiv).css('width',this.cW+'px');
		
		//var sliderMain = $('#'+key+' .photoslider_main').get(0);
		var sliderMain = $('#'+this.containerID+' .photoslider_main').get(0);		
		if(sliderMain != null){
			$(sliderMain).remove();
		}

		sliderMain = $(document.createElement('div'));
		sliderMain.addClass('photoslider_main');

		this.sliderMainWrap = document.createElement('div');
		//$(this.sliderMainWrap).addClass('photoslider_mainWrap');
		$(this.sliderMainWrap).css('display','none');
		this.sliderMainImg = document.createElement('img');
		$(this.sliderMainWrap).append(this.sliderMainImg);
		//sliderMain.append(sliderMainImg);		
		sliderMain.append(this.sliderMainWrap);		
		var id0 = '0';
		var firstPhotoCaption = this.getCaptionFromId(key,id0);
		//alert('first caption is   '+firstPhotoCaption);
		if (firstPhotoCaption=='') {
			this.iH = this.cH - this.thumbH - 2* this.imgBorder;
		} else {
			this.iH = this.cH - this.discrAndThumbH  - 2* this.imgBorder;;
		}		
		$(sliderMain).css('height',this.iH+'px');
		$(sliderMain).css('width',this.iW+'px');
		

		sliderDiv.append(sliderMain);

		var sliderCaption = $('#'+this.containerID+' .photoslider_caption').get(0);
		if(sliderCaption != null){
			$(sliderCaption).remove();
		}				
		
		if (firstPhotoCaption !='') {
			//alert('create Caption div');
			sliderCaption = $(document.createElement('div'));
			sliderCaption.addClass('photoslider_caption');
			$(sliderCaption).css('width',this.cW+'px');		
			if (FOTO.Slider.discrShown == 0 ) {
				$(sliderCaption).css("cursor","pointer");				
			} else {
				$(sliderCaption).css("cursor","text");						
			}
			sliderDiv.append(sliderCaption);
		} else {
			$(sliderMain).css('margin-bottom',13+'px');// 2*border  + widht/margin Buttons
			$(sliderMain).css('padding-bottom',0+'px');			
		}
		
		
		//build our play/stop button
		var sliderPlayStop = $('#'+this.containerID+' .photoslider_playStop').get(0);
		if(sliderPlayStop != null){
			$(sliderPlayStop).remove();
		}
		sliderPlayStop = $(document.createElement('div'));
		$(sliderPlayStop).css("href","");
		$(sliderPlayStop).css("onclick","");
		sliderPlayStop.addClass('photoslider_playStop');		
		$(sliderPlayStop).hover(function(){
			this.style.backgroundColor = "#ED1B34";
		}, function() {
			this.style.backgroundColor = "black";
		});

		
		
		//bind our click events to the buttons
		$(sliderPlayStop).html("начать слайдшоу");
		$(sliderPlayStop).click(function(){
			if(FOTO.Slider.data[key]['paused']){			
				$(sliderPlayStop).html("остановить слайдшоу");
				FOTO.Slider.play(key);
			} else {
				$(sliderPlayStop).html("начать слайдшоу");
				FOTO.Slider.stop(key);
			}
		});				
		sliderDiv.append(sliderPlayStop);		
		this.slideShowBtn = sliderPlayStop;
		
		
		
		/* build devider element */
		var divider = $('#'+this.containerID+' .site-divider').get(0);
		if(divider != null){
			$(divider).remove();
		}
		divider = $(document.createElement('div'));
		divider.addClass('site-divider');
		sliderDiv.append(divider);		

		//var sliderNav = $('#'+key+' .photoslider_nav').get(0);
		var sliderNav = $('#'+this.containerID+' .photoslider_nav').get(0);		 
		if(sliderNav != null){
			//remove it
			$(sliderNav).remove();
		}

		sliderNav = $(document.createElement('div'));
		sliderNav.addClass('photoslider_nav');				
		//$(sliderNav).css('height',this.cH+'px');

		sliderDiv.append(sliderNav);
		this.sliderNav = sliderNav;
		//thumbBar = $(document.createElement('div'));
		var thumbBar = $(document.createElement('div'));
		thumbBar.addClass('photoslider_thumbBar');

		//build the bar
		this.buildThumbBar(key,thumbBar);

		//now we need to attach our events
		$(thumbBar).children('.photoslider_thumb').each(function(){
			//what happens when we click on a thumbnail?
			$(this).click(function(ev){
				FOTO.Slider.thumbClick(ev);
			});
			/*
			$(this).mouseover(function(){
				$(this).stop().animate(
					{opacity: 1}, 
					{duration:300})
			});			
		    $(this).mouseout(function(){
				if ( $(this).attr('imageid') !=FOTO.Slider.data[FOTO.Slider.curKey]['currentId'] ) {
					$(this).stop().animate(
						{opacity: FOTO.Slider.hidenOpac}, 
						{duration:300});
				};
			});
                           */			
		});

		//attach our thumb nail bar to our parent
		sliderNav.append(thumbBar);		
		this.thumbBar = thumbBar;
		
		if (this.barW>this.navW) {
		//alert('barW = '+this.barW+'; navW='+this.navW);
		$(sliderNav).css({overflow: 'hidden'});
		$(sliderNav)
			.mouseout(function() {				
				$('#top').html('nav event out');
				$().unbind( "mousemove" );				
				clearInterval(FOTO.Slider.slideInterval);
			})
		    .mouseover(function(){			
				$().mousemove(function(e){
					FOTO.Slider.mouseX = e.pageX;	
				});
				FOTO.Slider.slideInterval = setInterval(function(){
					//FOTO.Slider.mouseX = e.pageX;	
					//FOTO.Slider.mouseY = e.pageY;
					//$('#top').html(e.pageX +', '+ e.pageY);
					//$('#top').html('nav event: '+FOTO.Slider.mouseX +', '+ FOTO.Slider.mouseY);					
					// from FLASH:
					//var left = (e.pageX - $(sliderNav).offset().left) * (FOTO.Slider.barW-FOTO.Slider.navW) / FOTO.Slider.navW;
					//$('#top').html('left = '+left+'; offset='+$(sliderNav).offset().left);		
					//$(FOTO.Slider.thumbBar).animate({left: -left}, { queue:false, duration:500});					
					//$(FOTO.Slider.thumbBar).scrollLeft(left);					
					//var x = this.startX + Math.round( this.distX * Math.sin(this.per*elapsed) );
					//this.hold_mc._x = this.hold_mc._x-(_root._xmouse-Stage.width/2)/20;
					var relX = (FOTO.Slider.mouseX - $(FOTO.Slider.sliderNav).offset().left);
					FOTO.Slider.scrollL += (relX-0.5*FOTO.Slider.navW)/50;
                    if ( FOTO.Slider.scrollL < 0                )	FOTO.Slider.scrollL = 0;
					//if ( FOTO.Slider.scrollL > FOTO.Slider.navW )	FOTO.Slider.scrollL = FOTO.Slider.navW;
					if ( FOTO.Slider.scrollL > FOTO.Slider.barW - FOTO.Slider.navW )	FOTO.Slider.scrollL = FOTO.Slider.barW - FOTO.Slider.navW;
					//$(sliderNav).scrollLeft(left);
					$(FOTO.Slider.sliderNav).scrollLeft(FOTO.Slider.scrollL);
				}
				,10);
			});
		};
		
		$(this.sliderMainImg)
			.mouseover(function() {
				$().mousemove(function(e){
					FOTO.Slider.mouseX = e.pageX;
					FOTO.Slider.mouseY = e.pageY;
					//$('#top').html(e.pageX +', '+ e.pageY);
					$('#top').html('image event: '+FOTO.Slider.mouseX +', '+ FOTO.Slider.mouseY);
				}); 
			})
			.mouseout(function() {
				$('#top').html('image event out');				
				$().unbind( "mousemove" );
				/*$().mousemove(null);				
				$().onmousemove = null;
				$().mousemove(function() {null});
				*/
			});				

		this.firstThumb.click();
	},

	thumbClick: function(ev){
		//find our main parent
		var thumb = null;


		if(ev.currentTarget){
			thumb = $(ev.currentTarget);
		} else if(ev.srcElement){
			//work around for IE's lack of currentTarget
			if( $(ev.srcElement).attr('src') == null){
				//they clicked on the div
				thumb = $(ev.srcElement);
			} else {
				//they clicked on the img
				thumb = $(ev.srcElement).parent();
			}
		}	else if (ev.target) {
			thumb = $(ev.target);
		}

		var id = thumb.attr('imageid');
		var bar = thumb.parent();
		var nav = bar.parent();
		var parent = nav.parent();
		//var key = parent.attr('id');
		var key =  this.curKey;
		var slot = thumb.attr('slot');
		if(id == null){
			id = 0;
		}
		if(slot == null){
			slot = 0;
		}

		//window.alert('id '+id+' bar '+bar+' nav '+nav+' parent '+parent+' key '+key+' slot '+slot);

		if(id == this.data[key]['currentId']){
			return false; //don't do anything since this is our current image
		}				

		//this.resetTimer(key);
		this.pauseTimer(key);		
		
		
		if(this.data[key]['currentId'] != null){
			//alert( 'fadeOut curThumb');
			//$('.photoslider_thumb[@imageid='+this.data[key]['currentId']+']').stop().animate(
			$(this.prevThumb).stop().animate(
					{opacity: FOTO.Slider.hidenOpac}, 
					{duration:300});
		}
		this.prevThumb = thumb;
		
		

		this.data[key]['currentId'] = id;
		this.data[key]['currentSlot'] = slot;
		//now we have everything we need, let's load in the main image
		//this.setMainImage(key,id);


		//animate our div down
		
		//$('.photoslider_thumb[@imageid='+this.data[key]['currentId']+']').stop();
		$(thumb).stop().animate(
					{opacity: 1.0}, //parameter
					300, //duration		
					"linear",
					function() {
						//alert('animation of current Thumb is done');
						var key = FOTO.Slider.curKey;
						var id = FOTO.Slider.data[key]['currentId'];
						FOTO.Slider.setMainImage(key,id);
					}
		);												
	},

	mainImgOnLoadGif: function() {
		this.onload = null;
		//alert('onLoad of animationGif...');
		$(this).height(22).width(126);			
		$(this).parent().fadeIn("fast", function() {
				//alert('loadingURL faded in, preload next image...');
				//preload the image and on return set our image			
				var key = FOTO.Slider.curKey;
				var id = FOTO.Slider.data[key]['currentId'];
				FOTO.Slider.preload(FOTO.Slider.getUrlFromId(key,id,false),FOTO.Slider.displayMainImage,{key: key, id: id, cID: FOTO.Slider.containerID});
		});		
	},
	
	//preloads the image for the main viewing area
	setMainImage: function(key,id){
		var main = $('#'+this.containerID+' .photoslider_main');
		//var mainImg = $('#'+this.containerID+' .photoslider_main img').get(0);
		var mainImgWrap=FOTO.Slider.sliderMainWrap;

		//set the mainImg to the spinner
		$(mainImgWrap).fadeOut("fast", function() {
			//alert('mainImg fadeedOut, put loadingURL...');
			//check if image was not loaded already:
			var key = FOTO.Slider.curKey;
			var id = FOTO.Slider.data[key]['currentId'];
			var url = FOTO.Slider.getUrlFromId(key,id,false);
			$(this).css('padding-top',0+'px');
			if (FOTO.Slider.imageCache[url] == null ) {		
				//alert('showing loading...');				
				FOTO.Slider.sliderMainImg.onload = FOTO.Slider.mainImgOnLoadGif;
				FOTO.Slider.sliderMainImg.src = FOTO.Slider.loadingURL;
			} else {
				FOTO.Slider.sliderMainImg.onload = null;
				//alert('loading image which was loaded before...');
				FOTO.Slider.preload(FOTO.Slider.getUrlFromId(key,id,false),FOTO.Slider.displayMainImage,{key: key, id: id, cID: FOTO.Slider.containerID});
			};
		});
		//this.preload(this.getUrlFromId(key,id,false),FOTO.Slider.displayMainImage,{key: key, id: id, cID: this.containerID});
	},
	
	resizeMainImage: function() {
		var mainImg = FOTO.Slider.sliderMainImg; //$('#'+this.containerID+' .photoslider_main img').get(0);
		var curW = FOTO.Slider.curW;//$(mainImg).width();
		var curH = FOTO.Slider.curH;//$(mainImg).height();		
		var ratio = 0;			
		var marg = 0;
		if ( curW/curH < this.iW/this.iH) {
			ratio = this.iH/curH;
			//$(mainImg).parent().css('padding-top',0+'px');
		} else {			
			ratio = this.iW/curW;
			marg = (this.iH-ratio*curH)/2;
			//alert('padding-top is '+marg);
			$(mainImg).parent().css('padding-top',marg+'px');
		}
		var newWidth = ratio*curW;
		var newHeight= ratio*curH;
		$(mainImg).height(newHeight).width(newWidth);		
	},

	displayMainImage: function(img){
		//alert('display main image...');
		var newSrc = ($(this).get())[0].src;
		//alert('showing '+newSrc);
		var args = this.args;
		var key = args['key'];
		var id = args['id'];
		if (id == FOTO.Slider.data[key]['currentId']) {// what we loaded is still   mainImage.
			//var containerID = args['cID'];
			//window.alert('displayMainImage:  containerID '+containerID);
			var main = $('#'+FOTO.Slider.containerID+' .photoslider_main');
			var mainImg = FOTO.Slider.sliderMainImg;//$('#'+FOTO.Slider.containerID+' .photoslider_main img').get(0);
			var caption = $('#'+FOTO.Slider.containerID+' .photoslider_caption');
			var captionTxt = FOTO.Slider.getCaptionFromId(key,id);

			if(captionTxt == null){
				captionTxt = '&nbsp;'; //make it play nice in browsers like ie
			}
			//caption.html(captionTxt);							
			if (FOTO.Slider.descr[key] != '0') {
				caption.html("<a href='"+FOTO.Slider.descr[key]+"' >"+captionTxt+"</a>");
			} else {
				caption.html(captionTxt);							
			}			
		
			FOTO.Slider.newSrc = newSrc;
			FOTO.Slider.curH = this.height;
			FOTO.Slider.curW = this.width;
			
			FOTO.Slider.contTimer(key);		
			
			$(mainImg).parent().fadeOut("fast", function() {
				//alert('mainImg after fadeOut in displayImage');
				$(FOTO.Slider.sliderMainImg).attr('src',FOTO.Slider.newSrc);					
				FOTO.Slider.resizeMainImage();
				$(this).fadeIn("fast");
			});
		}
		//$(main).fadeIn(1000);
	},

	//preload an image and fire off a callback if needed
	preload: function(url,onLoadFunc,args){
		var image = document.createElement('img');
		if(onLoadFunc){
			image.onload = onLoadFunc;
		}

		if(args){
			image.args = args;
		}
	    //alert('loading '+url);
		image.src = url;
		this.imageCache[url] = image;
		return image;
	},

	enableSlideshow: function(key){
		$('#'+key+' .photoslider_control').css('display','block');
		this.data[key]['slideshow'] = true;
	},

	//loops through the images available and preloads them one at a time
	preloadImages: function(key,slot){		
		if(FOTO.Slider.isPreloading[key] == null){
			FOTO.Slider.isPreloading[key] = new Object();			
		}
		FOTO.Slider.isPreloading[key] = 1;
		//we've already started preloading "0" so start at "1"
		if(this.bucket[key] != null && this.bucket[key][slot] != null){
			this.preload(this.getUrlFromId(key,slot,false),FOTO.Slider.preloadImageChain,{key: key,slot: slot});
		}
	},
	
	stopPreload: function(key) {
		//alert('stopping preload...');
		if(FOTO.Slider.isPreloading[key] != null){
			//alert('preload is stopped...');
			FOTO.Slider.isPreloading[key] = 0;
		}
	},

	preloadImageChain: function(){
		var args = this.args;
		var key = args['key'];
		var slot = parseInt(args['slot'])+1;
		if(FOTO.Slider.bucket[key] != null && FOTO.Slider.bucket[key][slot] != null && FOTO.Slider.isPreloading[key] == 1){
			FOTO.Slider.preload(FOTO.Slider.getUrlFromId(key,slot,false),FOTO.Slider.preloadImageChain,{key: key,slot: slot});
		} else {
			FOTO.Slider.isPreloading[key] == 0;
		}
	},
	
	clearCurKey: function() {
		var key = FOTO.Slider.curKey;
		FOTO.Slider.stopPreload(key);
		if (this.data[key]['paused'] == false) {
			//alert('stop slide-show...');
			this.slideShowBtn.click();
			this.data[key]['paused'] = true;
			//alert('slide show is stopped...');
		}		
	},

	//returns the absolute coords based on where it is on the page (works w/ scrolled content)
	findAbsolutePos: function(el){
		var SL = 0, ST = 0;
		var is_div = /^div$/i.test(el.tagName);
		if (is_div && el.scrollLeft)
			SL = el.scrollLeft;
		if (is_div && el.scrollTop)
			ST = el.scrollTop;
		var r = { x: el.offsetLeft - SL, y: el.offsetTop - ST };
		r.width = el.offsetWidth;
		r.height = el.offsetHeight;

		if (el.offsetParent) {
			var tmp = this.findAbsolutePos(el.offsetParent);
			r.x += tmp.x;
			r.y += tmp.y;
		}
		return r;
	},

	//this is just like the findAbsolutePos, but stops if a parent's css is "position:relative;"
	findRelativePos: function(el){
		var SL = 0, ST = 0;
		var is_div = /^div$/i.test(el.tagName);
		if (is_div && el.scrollLeft)
			SL = el.scrollLeft;
		if (is_div && el.scrollTop)
			ST = el.scrollTop;
		var r = { x: el.offsetLeft - SL, y: el.offsetTop - ST };
		r.width = el.offsetWidth;
		r.height = el.offsetHeight;

		if (el.offsetParent) {
			if($(el.offsetParent).css('position') != 'relative'){
				//stop if we have a relative parent
				var tmp = this.findRelativePos(el.offsetParent);
				r.x += tmp.x;
				r.y += tmp.y;
			} else {
				r.x += 0;
				r.y += 0;
			}
		}
		return r;
	},

	cycleImage: function(key){
		var slot = parseInt(parseInt(this.data[key]['currentSlot'])+1); //force this to be a number

		//var thumb = $('#'+this.containerID+' .photoslider_thumb[@slot='+slot+']').get(0);
		var thumb = $(this.thumbBar).get(0).childNodes[slot];
		if( (thumb == null) || ( this.curNSlot==slot )){
			this.slideShowBtn.click();
			this.data[key]['paused'] = true;
			return false;			
		}
		$(thumb).click();
	},

	play: function(key){
		if(this.data[key]['paused']){
			this.data[key]['paused'] = false;
			this.data[key]['intervalCycle'] = setInterval(function(){FOTO.Slider.cycleImage(key);},FOTO.Slider.duration);
		}
		//this.data[key]['paused'] = false;
	},

	stop: function(key){
		this.data[key]['paused'] = true;
		if(this.data[key]['intervalCycle']){
			clearInterval(this.data[key]['intervalCycle']);
		}
	},

	pauseTimer: function(key) {
		if (this.data[key]['paused'] == false) {
			clearInterval(this.data[key]['intervalCycle']);
		}
	},
	
	contTimer: function(key) {
		if (this.data[key]['paused'] == false) {
			this.data[key]['paused'] = true;
			this.play(key);
		}
	},
	
	
	resetTimer: function(key){
		if(!this.data[key]['paused'] && this.data[key]['intervalCycle']){
			this.stop(key);
			this.play(key);
		}
	}

};


SKEL.Transitions = {

	/* Many of these functions come from Robert Penner and mootools
	**  http://www.robertpenner.com/easing/
	**  http://mootools.net
	**
	** For more methods check
	**  http://opiefoto.com/js/skel/transitions.js
	*/

	quadOut: function(t, b, c, d){
		return -c *(t/=d)*(t-2) + b;
	},

	backOut: function(t, b, c, d, s){
		if (!s) s = 1.70158;
		return c*((t=t/d-1)*t*((s+1)*t + s) + 1) + b;
	}

};


SKEL.EFFECTS.Slide = {
	counter: 0,
	fps: 50,

	//handles the animation from an attribute to an attribute
	animate: function(element,cssAttribute,from,to,duration,transition){

		if(element.css('display') != 'block'){
			element.skel_old_display = element.css('display');
		}

		//if there isn't a default transition set one
		if(!transition){
			transition = SKEL.Transitions.quadOut;
		}

		//cancel any current animation
		SKEL.EFFECTS.Slide.stop(element);

		var startTime = new Date().getTime();

		//IE doesn't support arguments, so make a function that explicitly calls with those arguments
		element.skel_animate_id = setInterval(function(){
			SKEL.EFFECTS.Slide.step(element,cssAttribute,from,to,duration,startTime,transition);
		},(1000/SKEL.EFFECTS.Slide.fps));

		return element.skel_animate_id;
	},

	//cancels any animation event
	stop: function(element){
		//console.log(this,element,element.skel_animate_id);
		//console.log(element.skel_animate_id);
		if(element.skel_animate_id){
			clearInterval(element.skel_animate_id);
			element.skel_animate_id = 0;
			if(element.skel_old_display){
				element.css('display',element.skel_old_display);
			}
		}

	},

	//cancels any animation event
	stopByIntervalId: function(id){
		if(id){
			clearInterval(id);
		}
	},

	step: function(element,cssAttribute,from,to,duration,start,transition){
		var curTime = new Date().getTime();

		if(cssAttribute == 'color' || cssAttribute == 'background-color'){
			from = this.hexToRgb(from);
			to = this.hexToRgb(to);
		} else {
			//what we use to finalize the unit
			var result = this.splitValue(from);
			var prefix = result.prefix;
			if(prefix == '-')
				prefix = '';
			var postfix = result.postfix;

			from = parseInt(from);
			to = parseInt(to);
		}

		//compute the new property
		var newValue = SKEL.EFFECTS.Slide.compute(curTime,from,to,duration,start,transition);

		var finished = false;

		if(curTime > (start+duration)){
			finished = true;
		}
		if(cssAttribute == 'color' || cssAttribute == 'background-color'){
			newValue = this.rgbToHex(newValue);
		} else {
			newValue = prefix+Math.round(newValue)+postfix;
		}

		if(finished){
			SKEL.EFFECTS.Slide.stop(element);
		}

		//window.alert('css: '+cssAttribute+' new:'+newValue+' element: '+element);
		element.css(cssAttribute,newValue);
	},

	//thanks to mootools and Robert Penner
	compute: function(time,from,to,duration,startTime,transitionFunc){
		var deltaTime = time-startTime;
		if(time > (startTime + duration)){
			//we're past our point, return max
			return to;
		} else {
			if(typeof(from) == 'object'){
				//if we have an object, compute all the transitions\
				var tmpObject = Array();
				from.forEach(function(value,index){
					newFrom = value;
					newTo = to[index];
					newValue = transitionFunc(deltaTime,newFrom,(newTo-newFrom),duration);
					tmpObject[index] = Math.round(newValue);
				});
				return tmpObject;
			} else {
				return transitionFunc(deltaTime,from,(to-from),duration);
			}
		}
	},

	hexToRgb: function(str){
		var hex = str.match(/^#?(\w{1,2})(\w{1,2})(\w{1,2})$/);
		if(hex){
			if(hex[1] != ''){
				hex[1] = parseInt(hex[1],16);
				hex[2] = parseInt(hex[2],16);
				hex[3] = parseInt(hex[3],16);
			}
		}

		return (hex) ? hex.slice(1) : false;
	},

	rgbToHex: function(rgb){
		if (rgb.length < 3) return false;
		if (rgb[3] && (rgb[3] == 0) && !rgb) return 'transparent';
		var hex = [];
		for (var i = 0; i < 3; i++){
			var bit = (rgb[i]-0).toString(16);
			hex.push((bit.length == 1) ? '0'+bit : bit);
		}
		return '#'+hex.join('');
	},

	//returns prefix,postfix,value eg: #ff0000 {prefix: #, value: ff0000}, abc123efg {prefix: abc, value: 123, postfix: efg}
	splitValue: function(str){
		result = {
			prefix: '',
			postfix: '',
			value: ''
		}
		if(str != ''){
			var res = str.match(/([^0-9]*)([0-9]+)([^0-9]*)/);
			//try{
			result = {
				prefix: res[1],
				postfix: res[3],
				value: res[2]
			};
		}
		return result;

	}

}