/* This script will produce the effect of a turning page in an open book. It requires at least four images and, if the pages are not to keep swopping sides, it requires an even number too.  Ideally, these images are the  same width and height. (In this display each image used is itself made up of different size pictures.) To ensure a smooth effect, all the images for the book are first downloaded, before the page-turn effect is applied, otherwise blank pages or partly loaded pages appear. The image.onload event is used to detect the successful loading of an image. The procedure used is to assign the src to an invisible test image. If the onload event for this image is fired, then it might be considered that the full image has been downloaded. Unfortunately IE browsers sometimes fail to download a full image. To check if this has happened, the image height is measured. If it exceeds a certain minimum, the image download is considered successful. If not, it is rechecked and if the height remains unchanged for a given number of measurements, the image is considered faulty and further downloading ceases.. 
	 If the download is a considered a success, its src is transferred to the appropiate element in 'imgBase', the array of images needed for the 'pageflip' and then the next download is initiated. The process continues until all images needed for the 'pageflip' are downloaded after which the function 'startFlip' is called. If the onerror event occurs, due to an image being wrongly named or missing or any image downloaded is considered faulty, then the function 'startFlip' is not called and no page turning ensues. 
	The function 'startFlip' cause one page-turn initially. Further turns can be made by clicking on the open book display. A notice giving instructions how to do this is displayed. Once all the images have been used, the sequence begins again.
	It is possible to have the book with its spine parallel to the top of the screen or parallel to the side of the screen by changing the value of the variable 'spineHorizontal'.*/

   //Define preset values for page turning of book
	var pgImgWidth=242; // width of one image. Book's width will be twice this
	var pgImgHt=564; // page and book height
	var pgBorder=true;  // If true,a border will be set round each page
	var pgBorderColor="black";// color of border
	var pgBorderWidth="1px"; //width of border
	var turnSpeed=16;// speed pages turn over - the bigger this value, the faster
	var spineHorizontal=false; //This indicates spine of book is vertical. Set to true if spine of book is horizontal
	
   //Create object imgSources
	var imgSources=new Array( // these are images which appear as pages in the book.
	        'images/threePicsSmalla.jpg', //comma indicates more elements to come
           'images/threePicsSmallb.jpg',
           'images/threePicsSmallc.jpg',
           'images/threePicsSmalld.jpg',
           'images/threePicsSmalle.jpg',
           'images/threePicsSmallf.jpg',
		     'images/threePicsSmallg.jpg',
		     'images/threePicsSmallh.jpg',
		     'images/threePicsSmalli.jpg',
		     'images/threePicsSmallj.jpg' // no comma indicates last element in array
		);
	var noteDiv=document.createElement("div");
	
	
	
	var parag=document.createElement("p");
	var noteTxt ="";
	var noteNode=document.createTextNode(noteTxt);
   var bkLeftImg,bkMidImg,bkRightImg,imgSwop;// images used during page turning
   var pageElevation=0;
   var turningImg=3;  //this gives the index of the element in the imgBase array, which is used initially for bkMidImg or bkRightImg used in the 'turning page' display.
   var flipDirection=1;  //This changes to 0, when  turning page is at right angles to other pages.
	var turningImgSize; //width of visible turning page if spine vertical or height of turning page if spine horizontal
	var noTurn=false;
	var noteShown = false;
	imgBase=new Array(imgSources.length);// image base from which images for page turning display are chosen.
	loadingSideTracked=true;
	
	
	function getFlipImgs(){
	if(!document.getElementById){ return false;}
	if(!document.createElement){return false;}
	bkNoteData("In the process of getting more pictures.","340px");
	preloadImgs(0,imgSources.length,0);
	
	} //eof getFlipImgs
	
	
	function startFlip(){	
		//This function is only called if all images needed for the 'book' are preloaded.
		var bkDiv=document.getElementById("book"); // this div in index.html determines position of the 'flipped' images
		var positn=	findPosn(bkDiv);
		
		//Locate 'flipped' images in relation to bkdiv. Using position absolute makes settings for IE, Opera and Firefox the same.
		 xCoord=positn[0]-262;	// -262
		 yCoord=positn[1]-306;	//-306
		
		oldImg=bkDiv.getElementsByTagName("img");
		oldImg[0].style.visibility="hidden";
		bkLeftImg=document.createElement("img");
		bkDiv.appendChild(bkLeftImg);	
		bkRightImg=document.createElement("img");
		bkDiv.appendChild(bkRightImg);
		bkMidImg=document.createElement("img");
		bkDiv.appendChild(bkMidImg);	
		bkLeftImg.style.position=bkMidImg.style.position=bkRightImg.style.position="absolute";
		bkLeftImg.style.zIndex=bkRightImg.style.zIndex=0;bkMidImg.style.zIndex=1;
			
			bkLeftImg.style.left=xCoord+"px";
			bkMidImg.style.top=yCoord+"px";
			bkRightImg.style.top=yCoord+"px";
			
		if(spineHorizontal){
		bkLeftImg.style.top=pgImgHt+yCoord+1 +"px";
		bkMidImg.style.left=xCoord+"px";
		bkRightImg.style.left=xCoord +"px";
		
		}else{
		bkLeftImg.style.top=yCoord+"px";
		bkMidImg.style.left=pgImgWidth+xCoord+1+"px";
		bkRightImg.style.left=pgImgWidth+xCoord+1+"px";
		}
		
		/* The following ternary conditional operators could be used instead of the if/else statement above.
		bkLeftImg.style.top=(spineHorizontal?pgImgHt+yCoord+1:yCoord)+"px";
		bkMidImg.style.left=(spineHorizontal?xCoord:pgImgWidth+xCoord+1)+"px";
		bkRightImg.style.left=(spineHorizontal?xCoord:pgImgWidth+xCoord+1)+"px";
	  */

			bkLeftImg.style.height=pgImgHt+"px";
			bkMidImg.style.height=pgImgHt+"px";
			bkRightImg.style.height=pgImgHt+"px";
			bkLeftImg.style.width=pgImgWidth+"px";
			bkMidImg.style.width=pgImgWidth+"px";
			bkRightImg.style.width=pgImgWidth+"px";
			if(pgBorder){ //if b
				bkLeftImg.style.borderStyle=bkMidImg.style.borderStyle=bkRightImg.style.borderStyle="solid";
				bkLeftImg.style.borderWidth=pgBorderWidth;
				bkMidImg.style.borderWidth=pgBorderWidth;
				bkRightImg.style.borderWidth=pgBorderWidth;
				bkLeftImg.style.borderColor=bkMidImg.style.borderColor=bkRightImg.style.borderColor=pgBorderColor;
			} //end if b
			
			bkMidImg.src=imgBase[0].src;
			bkLeftImg.src=imgBase[1].src; 
			bkRightImg.src=imgBase[2].src; 
			
			bkLeftImg.onclick=bkMidImg.onclick=bkRightImg.onclick=pgTurnIfOK;
			bkImgs();
	} //eof startFlip


	function pgTurnIfOK(){
		if(pageElevation<Math.PI){return false;
		}else{
		nextTurn();
		}
	}

	function bkImgs(){
		if(!noTurn){ //if1
			if(spineHorizontal){ //if2
				turningImgSize=Math.abs(Math.round(Math.cos(pageElevation)*pgImgHt));
				MidOffset=!flipDirection?pgImgHt+1:pgImgHt-turningImgSize;
				bkMidImg.style.top=MidOffset+yCoord+"px";
				bkMidImg.style.height=turningImgSize+"px";
				} //end if2
				else{ 
				turningImgSize=Math.abs(Math.round(Math.cos(pageElevation)*pgImgWidth));
				MidOffset=flipDirection?pgImgWidth+1:pgImgWidth-turningImgSize;
				bkMidImg.style.left=MidOffset+xCoord+"px";
				bkMidImg.style.width=turningImgSize+"px";
				} //end else
			pageElevation+=turnSpeed/720*Math.PI;
			if(pageElevation>=Math.PI/2&&flipDirection){ //if3
				flipDirection=0;
				if(turningImg==imgSources.length){ // if4
				turningImg=0;
				} // end if4
				bkMidImg.src=imgBase[turningImg].src;
				turningImg++;
				 } //end if3
			if(pageElevation>=Math.PI){ //if5
				flipDirection=1;
				imgSwop=bkLeftImg;
				bkLeftImg=bkMidImg;
				bkMidImg=imgSwop;
				if(spineHorizontal){ //if6
				bkMidImg.style.top=yCoord+"px";
			} // end if 6
			else{
				 bkMidImg.style.left=pgImgWidth+1+xCoord+"px";	
			 }	 // end else	
				bkMidImg.src=bkRightImg.src;
				stopPgTurn;
				if(!noteShown){ // if7
					bkNoteData("Click on the pictures to turn them over.","330px");
					noteShown=true;
			} // end if7
		} //end if5
		else {
		setTimeout("bkImgs()",75);
		} //end else
		} // end if1
		else{
		setTimeout("bkImgs()",75);
	}//end else
} //eof bkImgs


function nextTurn(){
		if(turningImg==imgSources.length){
			turningImg=0;
		} //end if
		bkRightImg.src=imgBase[turningImg].src;
		bkMidImg.style.zIndex=2;
		bkLeftImg.style.zIndex=1;
		pageElevation=0;
		turningImg++;
		setTimeout("bkImgs()",75);
} //eof nextTurn

	
function stopPgTurn(){
	noTurn=true;
}  //eof stopPgTurn
	
	
function bkNoteData(note,noteWidth){

   noteDiv.id="note";
   noteDiv.style.zIndex=2;
   var noteTxt=note;
   noteNode=document.createTextNode(noteTxt);
   document.body.appendChild(noteDiv);
   parag.appendChild(noteNode);
   noteDiv.style.borderWidth="2px";
   noteDiv.style.borderColor="black";
   noteDiv.style.border="solid";
   noteDiv.style.backgroundColor="#dfd";
	noteDiv.style.color="#806";
	noteDiv.style.position="absolute"; //Using absolute positioning makes settings for IE, Opera and Firefox the same
	noteDiv.style.zIndex=-1;
	noteDiv.style.top="200px"; 
	noteDiv.style.left="350px" //424
	 
	noteDiv.style.width=noteWidth;
	noteDiv.style.height="24px";
   parag.style.fontSize="14pt";
   parag.style.position="relative";
   parag.style.left=5 +"px";
   parag.style.top=-19 +"px"; 
   noteDiv.appendChild(parag);
   
} //eof bkNoteData
	
	
function findPosn(obj){
  var topCoor=leftCoor=0;
  while(obj!=null)
  {topCoor+=obj.offsetTop;
  leftCoor+=obj.offsetLeft;
  obj=obj.offsetParent;}
  return [leftCoor,topCoor] ; //return left and top co-ordinates in an array.
} //eof findPosn
  

function preloadImgs(index,maxIndex,totalBar){
   // Get increment that progress bar changes for each image downloaded. It is safe to assume that the size of each image download is approximately the same.
	
   //get length of bar

    var barDiv=document.getElementById("indicatorHousing");
     var barLength=480;
   
   
  // incremental change in bar for each image loaded is rounded to nearest whole number. 
    barIncrement= Math.round(barLength/maxIndex);
    adjustedBarLength=barIncrement*maxIndex;// this ensures that barIncrements exactly fit into length of bar

    barDiv.style.width=adjustedBarLength+"px";
    barDiv.style.visibility="visible";
  
  //Set indication on progress bar to zero
	

	i=index;
	/*An invisible test image is created and added to the document. It is then assigned the required src. Its height is checked. If it is satisfactory, the test image is removed from the document and the src assigned to imgBase[i], knowing that it has been successfully preloaded.*/

	var testImgElem=document.createElement("img");
	document.body.appendChild(testImgElem);
	testImgElem.style.visibility="hidden"; 
	
	 //Apply src of image to be downloaded.
  
   
   testImgElem.onload = function(){//enlargement has been loaded into cache

	//reset onload event to null
   this.onload=null;
   
	/*Check that height of image is satisfactory before proceeding. Image.onload is fired when the image finishes loading. Unfortunately IE browsers can sometimes stop downloading an image before it is completed. To check for this, the height of the image is measured. If it is below a set minimum (minImgHt) and remains unchanged for a further number of measurements, given by the value of 'equalHtsAllowed', then an error is signalled.
	*/
	lastHt=-1;
	htNow=0;
	noEqualHts=0
	equalHtsAllowed=4;
	minImgHt=3*pgImgHt/4;
	do{
	lastHt=htNow;
  	  htNow = testImgElem.offsetHeight;
     htNow = parseInt(htNow, 10); // base 10
     if(htNow==lastHt){
     noEqualHts++;
     }
	} //end do
   while((htNow<minImgHt)&&(noEqualHts<=equalHtsAllowed));
   if(noEqualHts<=equalHtsAllowed){ //if1
	
	/* At this point a test image has been downloaded and its height checked successfully. We can now proceed with removing the test image and putting its equivalent as an element in imgBase array. 
	We also increment the indicator of the 'image download progress bar'.*/
	
	 totalBar=totalBar+barIncrement;
	//document.getElementById("indicator").style.width=totalBar +"px";
	 
	 var indicatorDiv=document.getElementById("indicator");
	 indicatorDiv.style.visibility="visible";
	 indicatorDiv.style.width=totalBar+"px";
	 
	 
	loadingSideTracked=true;
   testImgElem.parentNode.removeChild(testImgElem);
   imgBase[i]=new Image();
   imgBase[i].src=imgSources[i];
	if(i<maxIndex-1){// if2. Preload next image 
	i++;
	preloadImgs(i,maxIndex,totalBar);
	}else{  // else to if2. All images are preloaded, so start flip.
	
	//Remove 'Getting more pictures' sign and hide 'image loading progress bar'
	indicatorDiv.style.visibility="hidden";
	 barDiv.style.visibility="hidden";
	noteDiv.parentNode.removeChild(noteDiv); 
	parag.parentNode.removeChild(parag);
	noteNode.parentNode.removeChild(noteNode);
	startFlip();
	} //end else to if2
	} //end if1
	else{ //else to if1 The height of image downloaded is insufficient after checking more than 4 times
	//Replace 'Getting more pictures' sign and hide 'image loading progress bar'
	var indicatorDiv=document.getElementById("indicator");
	indicatorDiv.style.visibility="hidden";
	barDiv.style.visibility="hidden";
	noteDiv.parentNode.removeChild(noteDiv); 
	parag.parentNode.removeChild(parag);
	noteNode.parentNode.removeChild(noteNode);
	bkNoteData("No more pictures, as an error occured.","332px");
	
	return false;  //Because of an error, the function startFlip is not called.
	} //end else to if1
	} //eof testImgelem.onload


	testImgElem.onerror=function(){// assign onerror event, which will occur if an image url is wrong or an image is missing.
	this.onload=null;
	htElem=0;  //This value is set to zero in case refence is made to it later. (It is only updated when testImgElem.onload is fired.)
	
	testImgElem.parentNode.removeChild(testImgElem); // remove temporary image
	
	//Replace 'Getting more pictures' sign and hide 'image loading progress bar'
	var indicatorDiv=document.getElementById("indicator");
	indicatorDiv.style.visibility="hidden";
	barDiv.style.visibility="hidden";
	noteDiv.parentNode.removeChild(noteDiv); 
	parag.parentNode.removeChild(parag);
	noteNode.parentNode.removeChild(noteNode);
	bkNoteData("No more pictures, as an error occured.","332px");
	
	return false;  //Because of an error, the function startFlip is not called.
	} // eof testImg.onerror
	
	 testImgElem.setAttribute("src",imgSources[i]); //assign image source. This is done after assigning the onload and on error event
	
} //eof preloadImgs





 
addLoadEvent(getFlipImgs);




