/*  imgFader, version 1.0
 *  (c) 2008 Malte Sieb (http://www.maltesieb.de)
 *
 *  imgFader is freely distributable under the terms of the GPL license.
 *  For details, see my web site: http://www.maltesieb.org/skripte
 *
 *--------------------------------------------------------------------------
 *
 *	c	Container element id
 *  ce	Current visible element
 *  pe	Previous visible element
 *  fps	Frames per second
 *  eo	Current elements opacity
 *  po	Previous elements opacity
 *
 *  _g	Get										Alias for document.getElementById
 *  _a	Append									Append new image element to container
 *  _u	Update									Rebuild container after resorting images
 *  _so	Set opacity (element,aim of opacity)	Set opacity in 2 different methods
 *  _f	Fade function 							is called each frame
 *  _s	Show									Start fading to next image
 */

var Fade=function(c,v,d) { //c = container, d = variables
	/* Default values */
	this.fDur=1; // fade duration default
	this.delay=5; // delay default
	this.imgs=new Array(); //imgs default
	this.fo = new Array();
	this.ao = new Array();
	this.mode='random'; //mode default
	this.clear=true; //clear default
	this.minZ=10000; //minimum z-index default
	for (var i in d) this[i]=d[i]; // loads all values
	
	/* Prevent longer fade duration than delay */
	if (this.fDur>this.delay) this.fDur=this.delay;

	/* Script variables */
	this.v = v;
	this.ce=0; //current image
	this.eo=100; //end opacity for current image
	this.po=0; //end opacity for previous image
	this.fps=24; //frame rate
	this.d = (1/(this.fps*this.fDur))*100;
	this.c=c; //container element
	this.started = false;
	if(this.autostart) this.started = true;
	
	/* Prepare container element and put all images into it */
	if (this.interaction=="overauto" || this.interaction=="downauto") {
		this._g(this.c).setAttribute("onmouseover","javascript:"+this.v+".stop();");
		this._g(this.c).setAttribute("onmouseout","javascript:"+this.v+".start();");
	}
	if (this.clear) { 
		this._g(this.c).innerHTML=''; //this is good, it'll allow us to wipe the ul
		if(browser.isIE) {
			this._g(this.c).style.filter = "progid:DXImageTransform.Microsoft.Fade(duration="+this.fDur+")";
		}
	}
	this._g(c).style.position='relative'; //set container to relative to give z-index
	for (i=0;i<this.imgs.length;i++) {
		this._a(i,this.imgs[i]); //append the images to the container using prototype._a function
		this.ao[i] = (i==this.ce?this.eo:(i==this.pe?this.po:0));
	}
	if(browser.isIE) this._fie(this.ce);
	this._z(this.ce);
	
	/* Start the disaster */
	if (this.interaction!="over" || this.interaction!="down" || (this.autostart && this.started)) this.start();
};

Fade.prototype._z=function(i) {
	var k = this.imgs.length-(this.imgs.length-i);
	var ns = (this.imgs.length/2)-1;
	var s = this.imgs.length - ns;
	for(var j=0;j<this.imgs.length;j++) {
		if (k==0) k = this.imgs.length;
		k--;
		if(classOf(this.imgs[j]) == "Array" && this.imgs[j].length > 0) {
			this._g(this.imgs[j][0]).style.zIndex = this.minZ + k;
		}
	}
}

Fade.prototype.start=function() {
	var p=this;
	this.stop(); //ensures that no pre-existing load is occuring
	this.s=window.setInterval(function() {p._s()},this.delay*1000); //sets the delay and then runs the function this._s(), setInterval is perpetual
	this.started = true;
};

Fade.prototype.stop=function() {
	window.clearInterval(this.s);
	this.started = false;
};

Fade.prototype._a=function(i,img) { //writes the image html to the container
	//<li title="Submenu Item 1" class="index_submenu_1"><a href="#">Submenu Item 1</a></li>
	//['li id name','link href','link title','link description','img href','img description']
	
	// old code this._g(this.c).innerHTML+='<img src="'+img+'" id="img'+i+'" alt="" />'+"\n";
	if(classOf(img) == "Array" && img.length > 0) {
		this._g(this.c).innerHTML+='<li title="'+img[2]+'" id="'+img[0]+'"><a href="'+img[1]+'"><span id="'+img[0]+'-title">'+img[2]+'</span><img src="'+img[4]+'" id="'+img[0]+'-img'+i+'" alt="'+img[5]+'" /><div id="'+img[0]+'-desc">'+img[3]+'</div></a></li>'+"\n";
		if(this.interaction=="over" || this.interaction=="overauto") {
			this._g(img[0]).setAttribute("onmouseover","javascript:"+this.v+".go("+(i+1)+");");
			this._g(img[0]).setAttribute("onmousedown","javascript:subMenuLinkHandler("+(i+1)+")");
		} else if (this.interaction=="down" || this.interaction=="downauto") {
			this._g(img[0]).setAttribute("onmousedown","javascript:"+this.v+".go("+(i+1)+");");
		}
		this._g(img[0]+'-img'+i).style.position='absolute'; //positions it as absolute, probably a legacy issue with browsers
		if(!browser.isIE)
			this._so(i,(i==this.ce?this.eo:(i==this.pe?this.po:0))); //set opacity function....interesting
	}
};

/**
 * Rebuild container e.g. after resorting images
 */
Fade.prototype._u=function(n) {
	this.imgs=n;
	this._g(this.c).innerHTML='';
	for (i=0;i<n.length;i++) {
		this._a(i,this.imgs[i]);
	}
};

/**
 * Alias for document.getElementById
 */
Fade.prototype._g=function(i){ return document.getElementById(i);};

/**
 * Check if URL already exists
 */
Fade.prototype._d=function(n){for(i=0;i<this.imgs.length;i++){if(n==this.imgs[i][0])return i;}return false;}

Fade.prototype._so=function(i,o){ //i = img integer, o = opacity
	var e=this._g(this.imgs[i][0]+'-img'+i);
	var d=this._g(this.imgs[i][0]+'-desc');
	var t=this._g(this.imgs[i][0]+'-title');
	o=o>100?100:(o<0?0:o); //checks the original opacity of the image?	 
	e.style.opacity=(o/100); 
	d.style.opacity=(o/100);  
	t.style.opacity=((100-o)/100); 
};

//to handle multiple fadeouts we need an array of current opacity settings
//should use this.ao, this.ce will store the id of the current object for this.ao
//we also need to store multiple fadeout intervals, therefore this.fo will need to be an array which refers to each objects id
Fade.prototype._fi=function(i) {
	if(classOf(this.imgs[i]) == "Array" && this.imgs[i].length > 0) {
		if(this.ao[i]>=100) window.clearInterval(this.fi);
		var o = ((this.ao[i]+this.d)>=100) ? 100 : Math.round(this.ao[i]+=this.d);
		this.ao[i] = o;
		this._so(i,o);
	}
}

//this.ao refers to an array containing each elements current opacity and that gets changed each time
//this.fo refers to an array containing the fade out instance of each object
Fade.prototype._fo=function(i) {
	if(classOf(this.imgs[i]) == "Array" && this.imgs[i].length > 0) {
		if(this.ao[i]<=0) window.clearInterval(this.fo[i]);
		var o = ((this.ao[i]-this.d)<=0) ? 0 : Math.round(this.ao[i]-=this.d);
		this.ao[i] = o;
		this._so(i,o);
	}
}

Fade.prototype._fie = function(cE) {
	var img_container = this._g(this.imgs[cE][0]);
	
	img_container.style.filter = "progid:DXImageTransform.Microsoft.Fade(duration="+this.fDur+")";
	
	img_container.filters[0].apply();


	var e=this._g(this.imgs[cE][0]+'-img'+cE);
	var d=this._g(this.imgs[cE][0]+'-title');
	e.style.filter="alpha(opacity=100)"; //sets the original opacity of the image for explorer
	d.style.filter="alpha(opacity=0)"; //sets the original opacity of the image for explorer

	var pimg_container = new Array();
	for(var i=0; i<this.imgs.length; i++) {
		e=this._g(this.imgs[i][0]+'-img'+i);
		if(i != cE && e.style.filter != "alpha(opacity=0)") {
			
			pimg_container[i] = this._g(this.imgs[i][0]);
			pimg_container[i].style.filter = "progid:DXImageTransform.Microsoft.Fade(duration="+this.fDur+")";
			pimg_container[i].filters[0].apply();
			
			t=this._g(this.imgs[i][0]+'-title');
			
			e.style.filter="alpha(opacity=0)";
			t.style.filter="alpha(opacity=100)";
			
			pimg_container[i].filters[0].play();
		}
	}
    
	//container.filters[0].play();
	img_container.filters[0].play();
}


Fade.prototype._s = function(ce) {
	if (this.s) window.clearInterval(this.s); //if delay already started, stop it
	if (this.fi) {
		if(browser.isIE) {
			this._g(this.c).filters[0].Stop();
		} else {
			window.clearInterval(this.fi); //if fade already started, stop it
		}
	}
	
	var p=this,r,pE,cE;
	
	if (this.imgs.length>0) {
		this.pe=this.ce;
		if(ce || ce==0) {
			this.ce=ce;
		} else if (this.mode=='random') {
			do r=Math.round((Math.random()*this.imgs.length)-0.499);
			while(r==this.ce);
			this.ce=r;			
		} else if (this.mode=='pingpong') {
			//pingpong function for defining next object id
			if(this.ppc=='positive' && this.ce != (this.imgs.length-1)) {
				++this.ce;
			} else if (this.ce == 0) {
				++this.ce;
				this.ppc='positive';
			} else {
				--this.ce;
			}
			
			if(this.ce == (this.imgs.length-1)) this.ppc == 'negative';
			if(this.ce==0) this.ppc == 'positive';
		} else {
			if (++this.ce>(this.imgs.length-1))
				this.ce=0;
		}
		this._z(this.ce);
		
		pE = this.pe;
		cE = this.ce;
		
		if(browser.isIE) {
			this._fie(cE);
		} else {
			if(this.fo[this.ce]) window.clearInterval(this.fo[this.ce]);
			this.fi=window.setInterval(function() { p._fi(cE); },Math.round(this.fDur*1000/this.fps)); 
			this.fo[this.pe]=window.setInterval(function() { p._fo(pE); },Math.round(this.fDur*1000/this.fps));
		}
	}
	if (this.started) this.start(); //if not paused by mouseover this.stop() then resume the auto
	//this could be important for non auto fades
}


Fade.prototype.add = function(img,d) {
	var p,n=new Array();
	p=this._d(img[0]); //checks if element exists
	if (!p || d.force) { //if element doesn't exist or: if element exists and force is requested, add the identical element otherwise dont change element values
	/* should change this to re-write rather than duplicate, as id's shouldn't be duplicated, also img should be loaded as an array*/
		if (d.pos && d.pos=='first') d.pos=1; //checks semantic entry
		if (d.pos && d.pos<=this.imgs.length) { //checks if value is not illegal
			d.pos--; //corrects d.pos value to array value
			for (i=0;i<this.imgs.length;i++) { //clears space in array
				if (i<d.pos) n[i]=this.imgs[i]; //if less than requested position, leave in current position
				else if (i==d.pos) {n[i]=img;n[(i+1)]=this.imgs[i];} //if current position, move current array item up one and load in image
				else n[(i+1)]=this.imgs[i]; //if greater than requested position, move item up one
			}
			if (this.ce>=d.pos){this.ce++;} //if requested position is less than the current element, move it up one
			if (this.pe>=d.pos){this.pe++;} //if requested position is less than the previous element, move it up one
			this._u(n); //rebuild the container
			p=d.pos; //store requested position if it is an immediate load
		} else { //if there's no requested position, or the position is greater or equal to the array length, tac it on the end
			this.imgs[this.imgs.length]=img;
			p=this.imgs.length-1;
			this._a(p,img); //write the element into the container
		}
	}
	if (d.mode && d.mode=='immediate') {this._s(p);} //if immediate, force fade
};

Fade.prototype.go=function(p) {
	if (typeof p=='string' && p.indexOf('+')>-1) {
		p=parseInt(p.substr(1))+this.ce+1;
		if (p>this.imgs.length) p=p-this.imgs.length;
	} else if (typeof p=='string' && p.indexOf('-')>-1) {
		p=this.ce-parseInt(p.substr(1))+1;
		if (p<=0) p=p+this.imgs.length;
	}
	if(this.ce != (parseInt(p)-1)) this._s(parseInt(p)-1);
};

Fade.prototype.preload = function(img) {
	var i=new Image;
	i.src=img;
};
