Noisy=false ;

var defaultStepValue = 5;
var defaultFadeInterval = 50;
var defaultFadeInDelay = 500 ;
var defaultResidenceInterval = 10000 ;
var fadeTimeline=Array(1) ;
var styleColorRegEx_NS = /rgb\s*\((\d{1,3})\s*,\s*(\d{1,3})\s*,\s*(\d{1,3})\s*\)/ ;
var styleColorRegEx_IE = /#([0-9a-fA-F]{2,2})([0-9a-fA-F]{2,2})([0-9a-fA-F]{2,2})/ ;
if (Noisy) {alert('Starting fade script\ndefaultStepValue='+defaultStepValue+'  defaultFadeInterval='+defaultFadeInterval) ;}

function setFadeTimings(stepValue,fadeInterval,fadeInDelay,residenceInterval) { // optional, to alter default timing
	if (stepValue) defaultStepValue=stepValue ;
	if (fadeInterval) defaultFadeInterval=fadeInterval ;
	if (fadeInDelay) defaultFadeInDelay=fadeInDelay ;
	if (residenceInterval) defaultResidenceInterval=residenceInterval ;
}

function getColorValuesFromStyleDef(styleColor) {
	returnColorArray = new Array(0,0,0) ;
	matchArray=styleColor.match(styleColorRegEx_NS) ;
	if (matchArray) {
		for (i=1; i<matchArray.length; i=i+1) {
			returnColorArray[i-1] = parseInt(matchArray[i]) ;
		}
	} else {
		matchArray=styleColor.match(styleColorRegEx_IE) ;
		if (matchArray) {
			for (i=1; i<matchArray.length; i=i+1) {
				returnColorArray[i-1] = parseInt("0x"+matchArray[i]) ;
			}
		}
	}
	return returnColorArray ;
}

function getStyleFromSelector(selectorName) {
	var classFound=false ;
	if (selectorName.length>0) {
		for (sheet=0; (sheet<document.styleSheets.length && !classFound); sheet+=1) {
			if (Noisy) alert('checking sheet'+sheet) ;
			if (document.styleSheets.cssRules) {
				for (rule=0; (rule<document.styleSheets[sheet].cssRules.length && !classFound); rule+=1) {
					if (Noisy) alert('checking rule'+rule) ;
					thisRule=document.styleSheets[sheet].cssRules[rule] ;
					if (thisRule.selectorText=="."+selectorName) {
						classFound=true ;
						returnStyle=document.styleSheets[sheet].cssRules[rule].style ;
						break ;
					}
				}
			}
			if (classFound) {break;}
		}
	}
	if (classFound) {
		return returnStyle ;
	} else {
		return false ;
	}

}

function fadeText(textID,redHex,greenHex,blueHex,finalRed,finalGreen,finalBlue,redStepValue,greenStepValue,blueStepValue,interval,onComplete,iteration){ 
	if (iteration) {topLevel=false;} else {topLevel=true;}
	var textObj=document.getElementById(textID)
	if (redStepValue+greenStepValue+blueStepValue < 1) {// fading in (adding up to allow no change in any two colors)
		minRed=finalRed ;
		minGreen=finalGreen ;
		minBlue=finalBlue ;
	} else {
		minRed=0 ;
		minGreen=0 ;
		minBlue=0 ;
	}
	redHex=Math.max(minRed,Math.min(255,redHex+redStepValue)) ;
	greenHex=Math.max(minGreen,Math.min(255,greenHex+greenStepValue)) ;
	blueHex=Math.max(minBlue,Math.min(255,blueHex+blueStepValue)) ;
	if (Noisy) {Noisy=confirm("fading to ("+redHex+","+greenHex+","+blueHex+")") ;}
	textObj.style.color="rgb("+Math.round(redHex)+","+Math.round(greenHex)+","+Math.round(blueHex)+")";
	stillGoing=false ;
	if (redStepValue+greenStepValue+blueStepValue < 1) {// fading in
		if (redHex>finalRed||greenHex>finalGreen||blueHex>finalBlue) {
			stillGoing=true ;
		}
	} else if (redStepValue+greenStepValue+blueStepValue > 1) {// fading out
		if (redHex<finalRed||greenHex<finalGreen||blueHex<finalBlue) {
			stillGoing=true ;
		}
	}
	if (stillGoing) {
		setTimeout("fadeText('"+textID+"',"+redHex+","+greenHex+","+blueHex+","+finalRed+","+finalGreen+","+finalBlue+","+redStepValue+","+blueStepValue+","+greenStepValue+","+interval+",'"+onComplete+",false')",interval); 
		if (Noisy) alert('new fade step timer set') ;
	} else {
		if (Noisy) alert('fade finished, calling onComplete') ;
		if (topLevel) {eval(onComplete) ;}
	}
	return true ;
}

function fadeIn(textID,r,g,b,s,i,c) {
	rs=s*(256-r)/255*-1 ;
	gs=s*(256-g)/255*-1 ;
	bs=s*(256-b)/255*-1 ;
	if (Noisy) {alert('fading in: textID='+textID+'red='+r+', green='+g+', blue='+b+', red step='+rs+', green step='+gs+', blue step='+bs+', interval='+i)}
	fadeText(textID,255,255,255,r,g,b,rs,gs,bs,i,c) ;
	return true ;
}

function fadeOut(textID,r,g,b,s,i,c) {
	rs=s*(256-r)/255 ;
	gs=s*(256-g)/255 ;
	bs=s*(256-b)/255 ;
	if (Noisy) {alert('fading out: textID='+textID+'red='+r+', green='+g+', blue='+b+', red step='+rs+', green step='+gs+', blue step='+bs+', interval='+i)}
	fadeText(textID,r,g,b,255,255,255,rs,gs,bs,i,c) ;
	return true ;
}

function getCurrentColorFromStyle(textID) {// defaults to black
	var thisTextObj=document.getElementById(textID)
	var thisColor
	var thisClassName=thisTextObj.className;
	if (thisTextObj.style) thisColor=thisTextObj.style.color ;
	if (thisColor=="") {
		if (Noisy) alert('no color defined inline, checking style sheet') ;
		thisStyle=getStyleFromSelector(thisClassName) ;
		if (thisStyle) {
			thisColor=thisStyle.color ;
		} else {
			thisColor="rgb(0, 0, 0)" ;
		}
	}
	parsedColors=getColorValuesFromStyleDef(thisColor) ;
	if (Noisy) {alert('start color:'+thisColor+'=['+parsedColors[0]+','+parsedColors[1]+','+parsedColors[2]+']\nclass:'+thisClassName) ;}
	return parsedColors ;
}

function fadeComplete(i) {
	i=i+1 ;
	if (Noisy) alert('fade['+(i-1)+'] complete') ;
	if (i<fadeTimeline.length) {
		eval(fadeTimeline[i]) ;
	}
}

function crossFadeText(textID,newText) {
	var stepValue = defaultStepValue ;
	var fadeInterval = defaultFadeInterval ;
	getCurrentColorFromStyle(textID) ;
	parsedColors=getCurrentColorFromStyle(textID) ;
	if (Noisy) {alert('start color:'+thisColor+'=['+parsedColors[0]+','+parsedColors[1]+','+parsedColors[2]+']\nclass:'+thisClassName) ;}
	
	fadeTimeline[0]='fadeOut("'+textID+'",'+parsedColors[0]+','+parsedColors[1]+','+parsedColors[2]+','+stepValue+','+fadeInterval+',"fadeComplete(0)")' ;
	fadeTimeline[1]='setTimeout("fadeComplete(1)", defaultFadeInDelay)' ;
	fadeTimeline[2]='document.getElementById("'+textID+'").innerHTML="'+newText+'"; fadeComplete(2)' ;
	fadeTimeline[3]='fadeIn("'+textID+'",'+parsedColors[0]+','+parsedColors[1]+','+parsedColors[2]+','+stepValue+','+fadeInterval+',"fadeComplete(3)")' ;
	eval(fadeTimeline[0]) ;
	return true ;
}

function rotationalCrossFade(textID,textArray,continuous,shortStart) {
	var stepValue = defaultStepValue ;
	var fadeInterval = defaultFadeInterval ;
	getCurrentColorFromStyle(textID) ;
	parsedColors=getCurrentColorFromStyle(textID) ;
	if (Noisy) {alert('start color:'+thisColor+'=['+parsedColors[0]+','+parsedColors[1]+','+parsedColors[2]+']\nclass:'+thisClassName) ;}
	
	for (txt=0; txt<textArray.length ; txt+=1) {
		tli=txt*5 ;
		if(txt==0 && shortStart) {
			thisInterval="defaultFadeInDelay" ;
		} else {
			thisInterval="defaultResidenceInterval" ;
		}
		fadeTimeline[tli]='setTimeout("fadeComplete('+tli+')", '+thisInterval+')' ;
		tli+=1 ;
		fadeTimeline[tli]='fadeOut("'+textID+'",'+parsedColors[0]+','+parsedColors[1]+','+parsedColors[2]+','+stepValue+','+fadeInterval+',"fadeComplete('+tli+')")' ;
		tli+=1 ;
		fadeTimeline[tli]='document.getElementById("'+textID+'").innerHTML="'+textArray[txt]+'"; fadeComplete('+tli+')' ;
		tli+=1 ;
		fadeTimeline[tli]='setTimeout("fadeComplete('+tli+')", defaultFadeInDelay)' ;
		tli+=1 ;
		fadeTimeline[tli]='fadeIn("'+textID+'",'+parsedColors[0]+','+parsedColors[1]+','+parsedColors[2]+','+stepValue+','+fadeInterval+',"fadeComplete('+tli+')")' ;
	}
	
	if (continuous) {fadeTimeline[tli+1]='setTimeout("fadeComplete(0)",defaultResidenceInterval)' ;}
	eval(fadeTimeline[0]) ;
	return true ;
}

function rotateQuotes(textID,textArray) {
	rotationalCrossFade(textID,textArray,true,true) ;
}