/*
The web pages which incorporate the use of 'expanding' images are: eden.html, dales.html, lake.html, pennine.html and howgill.html. These pages are supplementary to the main site. The javascript to do this is magnify.js and global.js.

Small photographs appear alongside the text in these web pages. Clicking on these will expand the image smoothly producing an enlargement. Some padding and a border are added once an image is full size, together with a caption and instruction on how to remove the enlarged image. When the mouse-cursor is moved off the enlargement to outside the border (or frame), the enlargement will return to its original thumbnail. The thumbnail image itself is not enlarged but remains on the web page. Two options can occur.
1),  Full sized images are downloaded with the web page and thumbnail versions of them are then displayed. This is acceptible if the number of images on the page is low so that the download time is not too long.
2). The original image is of thumbnail size and is later replaced by downloading an enlargement of itself, when the thumbnail is clicked on. Because the download time of a full page, containing several large images, could be excessive, a system using thumbnail images is used to reduce the initial download time. Further download time will only occur, when any thumbnail is clicked on, initiating the download of the enlargement of the thumbnail. Obviously, the viewer has the option to forego looking at the enlargements and save time on further downloads if he/she wishes.

  In case 2, downloading each enlargement will take time and so an invisible image element, testImgElem, is created first. The src attribute with name equal to the image to be downloaded is assigned to this image element.  If the 'image.onload' event is fired the test image could be deemed to have been downloaded.  However, rather than just relying on this event, the height of the image is tested repeatedly by reading the image's offseHeight. These readings are only carried out, while the image height is below a set minimum value and while successive heights are not the same more than a certain number of times, (given by the value of 'equalHtsAllowed'). If a measurement exceeds the minimum height specified, the download in the background is deemed complete and the src is now assigned to the image, which is to be enlarged. The reason for taking height readings is due IE browsers sometimes failing to download all of an image. In such cases an incomplete image would be displayed. Failing this test means that an error message, 'Downloading the enlargement of of the thumbnail failed', is displayed instead. If the image.onerror event fires, then an image is probably missing or wrongly named, in which case the same error message is displayed.  This is done by displaying an image having a blank background with this message on it.  Other methods, which put a message over the thumbnail were abandoned, (The reason for this was timing and synchronisation problems with Mozilla Firefox and to a lesser extent with Internet Explorer, although the Opera browser operated perfectly. This meant that the messages did not appear in the order given by the coding, especially as some of the coding uses a 'do...while' loop and took a relatively long time to complete and so a blank image appeared before the 'downloading failed' message did. If the background of this image was made opaque, then the message was blocked out all together.  A suggested method to correct the synchronisation problem by applying setTimeout, with time set to zero, to certain functions, was not proceeded with.)

	During the time the image is being downloaded, a message  stating 'Loading Enlargement', is placed over the thumbnail. informing the user what is happening. This is removed as soon as the enlarged image is in the browser's cache. This is displayed at first as a small image, a copy of the thumbnail, but then grows until it reaches a predetermined size, with its centre close to the centre of the page.The enlargement process is done in small steps by changing the image's size (style.width and style.height) and the image's position (style.top and style.left) every few millisecs. The time for each step, 'tStep', and the total time of the enlargement process, 'magnifyTime', applies to all images and can be reset within the javascript code. The mean change in width, height, left position and top position are calculated. Initially the changes are made 1.5 times these values, when the image is small, and at each step they are reduced by a constant amount until the final change is 0.5 times the mean value, when the image is large. Doing this reduces the changes in area of successive images as they get larger, compared with keeping the steps constant. 
 A minimum value of 'tStep' is about 8 (milliseconds).   'magnifyTime' may range from 500 to 1500. The smoothness of the transitions between successive images depends on 
a). having a reasonably high number of steps, (= magnifyTime/tStep),
b). on the length and width of the final image,
c). on the size of memory of the image being used in the expansion process and lastly
d). on the browser used.   In respect of smoothness, Internet Explorer and Opera are much better than Mozilla Firefox.. The shrinking process uses the same function, 'resize' as for enlarging, Whether enlargement or shrinking occurs is determined by the variable, 'direction', which is +1 for enlargement and -1 for shrinkage.

Each image which may be enlarged has the class "inflatableImg". At the time that the script is loaded, the code places the notice, "Click to enlarge.", over all these images. (Changing the width of the window once the page has been loaded, will cause the notice to move in relation to the images but most people are unlikely to do this.) Because the font may merge into some of the thumbnail images and not be clearly visible, the colour of the font can be adjusted in the HTML markup. The colour chosen is stored in the 'name' attribute of the image. The 'id' attribute is used for the title caption on the enlargement. It must not contain apostrophes. (You could use a grave accent ` U+0060 instead.) The 'alt' attribute acts as normal, so, if the image is missing or javascript is off, the value of 'alt' appears, where the image should be. When an image is clicked on, the 'onclick' event is removed from all the images, so that it is impossible to instigate multiple enlargements at the same time.

When an image reaches full size, a border is added and the function 'addLabels' uses DOM scripting to add an instruction above the image. This instruction tells the user how to shrink the enlarged image, which is done by taking the mouse cursor from inside to outside the border. Shrinking is activated by the 'onmouseout' event. The position of the instruction should fall on the image border but does tend to vary slightly, (depending on where the thumbnail is on the web page and on the screen).  A caption, giving information on the subject of the photo, is also added below the image. As mentioned earlier, this is taken from the 'id' attribute of the image.At the start of the shrink process, the caption, the instruction, the padding and the border are all removed from the enlargement.  When the shrinking process is finished, the 'copy' of the thumbnail is removed and the 'onclick' event replaced on all the images. 

The array loadRecord() keeps a record of the loading of each image. All values are set to -1 initially, indicating that each image is assumed not to have been down loaded. In the HTML mark-up, an image, not ending in '1.jpg' or '2.jpg' is specified as a large image and the thumbnail displayed on the page will be a reduced version of this large image. The browser's cache will already hold the large image, if the thumbnail is visible and so showing the enlargement can proceed immediately, when the thumbnail is clicked on. In this case, the value of loadRecord for these images is immediately set to +1.
 Images ending in '1.jpg' are thumbnail images and should be accompanied by a corresponding enlargement, ending in '2.jpg'.  Thus, after a test is made showing that the thumbnail image has its src ending in '1.jpg', a larger version, (ending in '2.jpg') needs to be downloaded. When a successful attempt to download this larger image is made the value of loadRecord[imgNo] is set to +1 and a visible display of the actual image occurs. If the download is unsuccessful, then as stated previously, the notice stating that 'the downloading of the enlargement of the thumbnail failed', occurs and its loadRecord remains at -1.  If a thumbnail, which has already been downloaded is clicked on again, its loadRecord will already be +1, indicating that it can be enlarged immediately, as the full size image will already be in the browser's cache, In this case the enlargement proceeds immediately without first trying to download an invisible image of itself.  If the image clicked on has already had an unsuccesful attempt to download its enlargement, then loadRecord is still -1 and a further attempt to download the enlargement is made.


Window geometry.
Besides needing to know the size of the element in order to carry out the enlargement process, it is necessary, to know the size of the window, how much the window has been scrolled and how much padding the element has.  Out of the browsers tested, IE is again the odd one out, as its methods for finding the last three properties differ from other browsers. This means extra object detection code has to be added for IE. The table below shows the differences, which had to be considered in the coding.

Property											Non IE browsers																						IE6+ browser with a !DOCTYPE					IE5, IE6, IE7 without !DOCTYPE

Window width							window.innerWidth																					document.documentElement.clientWidth		document.body.clientWidth
Window height							window.innerHeight																				document.documentElement.clientHeight		document.body.clientHeight
Window horizontal scroll		window.pageXOffset																			document.documentElement..scrollLeft			document.body.scrollLeft
Window vertical scroll			window.pageYOffset																				document.documentElement..scrollTop			document.body.scrollTop
Left padding of element		windows.getComputedStyle(element,null).paddingLeft								element.currentStyle.paddingLeft, for all IE browsers


This is the cascaded style of the element taking into account, global style sheets, inline styles and HTML attributes. For padding on the other sides of the element, replace Left by Right, Top or Bottom. Later browsers of IE are made compatible with earlier versions by omitting the !DOCTYPE tag before the HTML tag at the start of the document. This is known as 'quirks mode' or 'buggy' mode as position and size attributes of the element work incorrectly by including the element's border and padding. In the strict or standards mode, with the !DOCTYPE tag, the CSS position and size attributes of the element work correctly.

 A note on mouse events.
The design uses only one mouse event at a time - 'onclick' to trigger the enlargement process and 'onmouseout' to trigger the shrinking process.
Because only one event handler is used for a particular event on a particular object at any one time, DOM 0 event handling techniques were used. i.e. when enlarging the image, the event handler is 'magnify', the event is 'onclick' and the object is 'img' and when shrinking the image, the event handler is 'setupShrink', the event 'onmouseout' while the object remains 'img'. The changing sequence of mouse events used in the enlarge/shrink process is as follows. After an image has had the mouse clicked on it, so starting its enlargement, all 'onclick' events assigned to images which can be enlarged, are then nullified.  This is so that clicking on a second image does not start another enlarge/shrink process before with the first has finished. When a full size image is obtained, the event 'onmouseout' is added, which is assigned to the function 'setupShrink'.  As soon as the cursor moves from within the image frame to outside it, to start the shrinking process, the 'onmouseout' event is nullified. Finally all 'onclick' events are restored when the shrink process is complete, allowing the cycle to start again with another image or even the same image.

DOM 2 application Programming interface (API) not used.
The addition and removal of events was originally designed with DOM 2 event handling techniques using  'document.addEventListener' and 'document.removeEventListener', a total of 2 lines.However,  IE is the only browser that does not comply with the DOM level 2 event handling model, where an event (such as onclick, onmouseover etc.) is 'captured' by the event handler while providing details of when and where it occured.  Instead IE supports event propogation by bubbling, where events bubble up the hierarchy in the IE model. This can lead to memory leaks and a serious loss in performance unless the 'cancelBubble' property of the Event object is set to true by a specially designed event handler. Initially a special event handling programme, of over 70 lines, was used to get round the problem but was dropped when it was found possible to use DOM 0.instead. This event handling programme has not been discarded and has been placed in 'global.js' even though it is not now used. Places in the script, 'magnify.js', where DOM 2 techniques and the IE  'hack' were called have been kept but shielded from being read by using comment characters.
*/

/*List of Geometry variables
sizeInside.wWin, 
sizeInside.hWin,
getPadding.lPad,
getPadding.tPad,
getPadding.rPad,
getPadding.bPad,
getElemPosition.x,
getElemPosition.y,
getElemSize.wElem,
getElemSize.hElem
getWindowOffset.horizontalScroll,
getWindowOffset.verticalScroll'

List of image elements used in the coding.

imgElems is the array of image elements in the HTML mark-up with classname "inflatableImg".

elem is an image element which has just been clicked on.

tempImgElem is a hidden  image element placed in top left corner of the document. This is assigned the src attribute of an enlargement that 
is to be displayed later, once the enlargemen has been downloaded.  This is indicated by the height of tempImgElem meeting certain criteria.

img is an image element which is assigned the src attribute of the thumbnail enlargement, which is enlarged and shrunk
*/

///////////////INIT ////////////////////////

function init(){

loadRecord = new Array(); 
imgId=new Array();

//Get all images with class "inflatableImg"
imgElems = getElemsByClassName("inflatableImg", "img"); // The function getElemsByClassName is in global.js  
elemsL=imgElems.length;
for( var i=0;i<elemsL;i++) {
loadRecord[i]=-1;
imgId[i]=imgElems[i].getAttribute("id");

loadRecord[i+elemsL] = imgId[i];  //attach imgId array to end of loadRecord array.Separate later
} //end for

return[loadRecord]; 
} //eof init

//////////ADDNOTICE //////////

function addNotice(imgId,uploaded) { // Onload, put an instruction on all ithumb mages, which have class="inflatableImg". 
var notice = "Click to magnify.";
var noticeNode= new Array();
var divNotice=new Array();

//Get all images with class "inflatableImg"
imgElems = getElemsByClassName("inflatableImg", "img"); // The function getElemsByClassName is in global.js  
  
//Run through these 'thumb' images and assign notices to appear on them
for( var i=0;i<imgElems.length;i++) {

// Get attribute name, which has been assigned the text colour
var col =imgElems[i].name;

//Get left, top and width of thumb images
var startPos=getElemPosition(imgElems[i]);
 var imgL=parseInt(startPos.x,10);
var imgT= parseInt(startPos.y,10);
var imgW = parseInt(getElemSize(imgElems[i]).wElem,10);

//Get length of notice in pixels
 var numNoticeLetters=notice.length;
var	lenText=Math.floor(numNoticeLetters*4.5); // This depends on font, font size and letters used in notice

//Append notices to div tags
noticeNode[i] = document.createTextNode(notice);
divNotice[i]=document.createElement("div");
divNotice[i].appendChild(noticeNode[i]);

//Assign styles to divs containing notices
divNotice[i].style.height="12px";
	divNotice[i].style.position = "absolute";
	divNotice[i].style.left = Math.floor(imgL+imgW/2-lenText/2)+"px";
	divNotice[i].style.top= imgT +"px";
	divNotice[i].style.backgroundColor="transparent";
	divNotice[i].style.color=col;
	divNotice[i].style.fontSize="8pt";
	divNotice[i].style.fontFamily="Arial";
	divNotice[i].zIndex=imgElems[i].style.zIndex+1;
	
	// Remove attribute alt from thumb images
imgElems[i].alt="";
	
	//Append divs to thumb images
	imgElems[i].parentNode.appendChild(divNotice[i]);
	
	} //end for	
	
} //eof addNoticeGetId

///////// GETELEMENT ///////////

function getElement(thisObject) {  // Convert thisObject's name string or object reference into a valid element object reference
    var elem;
    if (typeof thisObject == "string") { //if 1
		if(document.body && document.body.style){ //if2a
        if (document.getElementById) { //if3a
            elem = document.getElementById(thisObject);
        }  //end if 3a
         if (document.all) { //if 3b
            elem = document.all(thisObj);
        }//end if 3b
        }//end if 2a
         if (document.layers) { //if 2b
            elem= SeekLayer(document,thisObject);
        } // end if 2b
      } //end if1
    else {   // thisObject reference is an element
        elem = thisObject;
    } //end else
    return elem;
}  //eof getElement

///////// SIZEINSIDEWINDOW ////////
				
function sizeInsideWindow() {  // Get width, wWin, and height, hWin, inside browser window
    if (window.innerWidth) { // all browsers but I.E.
        return {wWin:window.innerWidth, hWin:window.innerHeight};
    }else if (document.documentElement && document.documentElement.clientWidth){ // I.E.6 when there is a DOCTYPE
        return {wWin:document.documentElement.clientWidth, hWin:document.documentElement.clientHeight};
    } else if (document.body.clientWidth) { // For I.E 4, I.E.5 and I.E.6 without a DOCTYPE, i.e  in quirks mode.
        return {wWin:document.body.clientWidth, hWin:document.body.clientHeight};
    }
    return {wWin:0, hWin:0};// return the identifier, wWin, with value zero
} //eof sizeInsideWindow

//////// GETPADDING ///////////////

function getPadding(elem) {  // get padding around element
	if (elem.currentStyle)  {  //I.E. browsers
		if (elem.currentStyle.paddingLeft)
			leftPad = parseInt(elem.currentStyle.paddingLeft, 10);// base 10
		if (elem.currentStyle.paddingRight)
			rightPad = parseInt(elem.currentStyle.paddingRight, 10); 
		if (elem.currentStyle.paddingTop)
			topPad = parseInt(elem.currentStyle.paddingTop, 10); 
		if (elem.currentStyle.paddingBottom)
			btmPad = parseInt(elem.currentStyle.paddingBottom, 10); 
	} else if (window.getComputedStyle) {   //browsers conforming to W3C standard
		leftPad= parseInt(window.getComputedStyle(elem,null).paddingLeft, 10);// base 10, second argument (given value null) required by Mozilla Firefox
		rightPad = parseInt(window.getComputedStyle(elem,null).paddingRight, 10);
		topPad = parseInt(window.getComputedStyle(elem,null).paddingTop, 10);
		btmPad = parseInt(window.getComputedStyle(elem,null).paddingBottom, 10);
	}
	return {lP:(leftPad),rP:(rightPad),tP:(topPad),bP:(btmPad)};
}//eof getPadding

/////// GETELEMPOSITION /////////
	
function getElemPosition(elem){  // Get position of element in the page. The argument is an element or element id.
if(typeof element == "string"){
element=document.getElementById(element);}
	var left = 0;
	var top = 0;

	// add any original element padding
	var elemPadding = getPadding(elem);
	left = elemPadding.lP;
	top = elemPadding.tP;
	if (elem.offsetParent)
	{
		left += elem.offsetLeft;
		top += elem.offsetTop;
		var parent = elem.offsetParent;
		while (parent) {
			left += parent.offsetLeft;
			top += parent.offsetTop;
			var parentTagName = parent.tagName.toLowerCase();
			if (parentTagName != "table" &&
				parentTagName != "body" && 
				parentTagName != "html" && 
				parentTagName != "div" && 
				parent.clientTop && 
				parent.clientLeft) {
				left += parent.clientLeft;
				top += parent.clientTop;
			}
			parent = parent.offsetParent;
		}
	}
	else if (elem.left && elem.top){
		left = elem.left;
		top = elem.top;
	} else {
		if (elem.x) left = elem.x;
		if (elem.y) top = elem.y;
	}
	return {x:left, y:top};
}	//eof getElemPosition
		
	/////////// GETELEMSIZE ///////////////
	
function getElemSize(elem)  {  // get size of element.
    var wElem = 0;
    var hElem = 0;
    if (elem.offsetWidth) {
			wElem = elem.offsetWidth; hElem = elem.offsetHeight;
    } else if (elem.clip && elem.clip.width) {
			wElem = elem.clip.width; hElem = elem.clip.height;
    } else if (elem.style && elem.style.pixelWidth) {
			wElem = elem.style.pixelWidth; hElem = elem.style.pixelHeight;
    }
    wElem = parseInt(wElem, 10); //base 10
    hElem = parseInt(hElem, 10); // base 10
    
   // remove any original element padding
   var padding = getPadding(elem);
   lPad=parseInt(padding.lP,10);  // convert to integer, radix 10
   rPad=parseInt(padding.rP,10);  // convert to integer, radix 10
   tPad=parseInt(padding.tP,10);  // convert to integer, radix 10
   bPad=parseInt(padding.bP,10);  // convert to integer, radix 10
   wElem -= (lPad + rPad-0);
   hElem -= (tPad + bPad-0);
   return {wElem:(wElem), hElem:(hElem)};
}	//eof getElemSize
	
	/////////// GETWINDOWOFFSET ///////////
	
function getWindowOffset() {  	// get no.of pixels the visible window has been moved by scrollbar
    if (window.pageYOffset) {// all browsers except I.E.
        return {horizontalScroll:window.pageXOffset, verticalScroll:window.pageYOffset};
    } else if (document.documentElement && document.documentElement.clientWidth){ // for IE6 with DOCTYPE
        return {horizontalScroll:document.documentElement.scrollLeft, verticalScroll:document.documentElement.scrollTop};
    } else if (document.body.clientWidth) { // for IE4, IE5 and IE6 without DOCTYPE
        return {horizontalScroll:document.body.scrollLeft, verticalScroll:document.body.scrollTop};
    }
    return {horizontalScroll:0, verticalScroll:0};
}	//eof getWindowOffset
		
/////////MAGNIFY ///// Function called by onclick event handler.///////////////////
		
function magnify(thisObject){	
	
//initial value of variables
startLeft=0;
startTop=0;
initImgW=0;
initImgH=0;
winW=0;
winH=0;
hScroll=0;
vScroll=0;
finalImgW=0;
finalImgH=0;
deltaX=0;
deltaY=0;
deltaW=0;
deltaH=0;
imgId="";
imgTitle="";
paddingW=22;
borderW=20;
noSteps=0;
minImgHt=348;// lowest image height in lake.html and eden .html 
//cycles=0;
loadStart=false;
magnifyTime=1280; //Time in millisecs for complete enlargement to take place
tStep=32; // Time for each incremental step in the enlargement process


elem= getElement(thisObject);
 
//Get title of full sized image
imgTitle=elem.getAttribute("id");


imgNo=-1; // -1 indicates unknown imgNo

//Get imageNo
for (var i=elemsL;i<2* elemsL;i++){
	if(imgTitle == loadRecord[i]){
	imgNo=i-elemsL; 
	} //end if
}  //end for
	
	//Get parent node of element. (I.E. objects to 'parent'.)
	parentNd = elem.parentNode; 
   var startPos = getElemPosition(elem);
	startLeft=parseInt(startPos.x,10); // convert to integer, radix 10
	startTop=parseInt(startPos.y,10); // convert to integer, radix 10
	var initSize = getElemSize(elem);
	initImgW =parseInt(initSize.wElem,10); // convert to integer, radix 10
	initImgH =parseInt(initSize.hElem,10); // convert to integer, radix 10
   img=document.createElement("img"); // create 'floating' image that is to be enlarged/shrunk

   if (loadRecord[imgNo]=-1){
   
   }
   
   //Prevent further 'onclick' events, while magnify/shrink process is underway
   for( var i=0;i<imgElems.length;i++) {
   imgElems[i].onclick= null;
   } //end for
  

//Get name of possible larger image
	re=/1.jpg$/; //regular expression for format at end of src name
	 var posnDigit1= elem.src.search(re); // get position of digit 1, if it exists, before .jpg in src
	 
	 //Test if posnDigit not equal -1. If true, we have an src ending in 1.jpg implying image is a thumbnail
	
	if (posnDigit1!= -1){  //if a
	
	// Replace the 1 in the src name of the original image by 2 to give src of possible enlargement, which may be in folder
	 newImgSrc = elem.src.substring(0,posnDigit1) + "2" +".jpg";
	
	if(loadRecord[imgNo]==-1){ // if b. We have not loaded this image before, so show "Loading enlargement" sign, as enlargement  downloads.
	//setTimeout("waitSign(" + 'Loading enlargement' + "," + '#004499' + ")",0);

	waitSign("Loading enlargement","#004499");// put sign over thumbnail, elem
	
	var testImgElem=document.createElement("img");

	document.body.appendChild(testImgElem);
	
	 testImgElem.style.visibility="hidden"; 
	
	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;
	htElem=0;
	noEqualHts=0
	equalHtsAllowed=4;;
	do{
	lastHt=htElem;
  	  htElem = testImgElem.offsetHeight;
     htElem = parseInt(htElem, 10); // base 10
     if(htElem==lastHt){
     noEqualHts++;
     }
	} //end do
   while((htElem<minImgHt)&&(noEqualHts<=equalHtsAllowed));
   if(noEqualHts<=equalHtsAllowed){ //if1
//We can now proceed with displaying enlargement

 loadRecord[imgNo]=1; // indicates downloading of image has been attempted successfully
 
 testImgElem.parentNode.removeChild(testImgElem); // remove temporary image
	
divSign.parentNode.removeChild(divSign);  //Remove 'Loading Enlargement' sign

 img.src=newImgSrc;  // apply src of image ending in 2.jpg to img
  
  setParameters();
 
img.style.backgroundColor="#fff";// give image white background. 

  startMag(imgId,magnifyTime,tStep);

} //end if1
	else{ //else to if1. Downloading failed as some of the image failed to download.
	
	 
	 testImgElem.parentNode.removeChild(testImgElem); // remove temporary image
	
    divSign.parentNode.removeChild(divSign);  //Remove 'Loading enlargement' sign
  
   setParameters();
 
 //Apply background image containing the message 'Downloading of the enlargement of the thumbnail failed'
  img.style.backgroundImage="url(images/failNotice1.jpg)";
  startMag(imgId,magnifyTime,tStep);
	} //end else to if1

 } //eof testImgElem.onload
	
	
testImgElem.onerror=function(){// error such as corrupt image data or image not available
	
	//reset onload event to null
    this.onload=null;
   htElem=0; //This value is set to zero in case refence is made to it later.

    testImgElem.parentNode.removeChild(testImgElem); // remove temporary image
	
    divSign.parentNode.removeChild(divSign);  //Remove 'Loading enlargement' sign

    img.src=newImgSrc;  // apply src of image ending in 2.jpg to img
  
   setParameters();
 
 //Apply background image containing the message 'Downloading of the enlargement of the thumbnail failed'
  img.style.backgroundImage="url(images/failNotice1.jpg)";
  startMag(imgId,magnifyTime,tStep);

} //eof testImgElem.onerror

	
testImgElem.onabort= function(){//stop button on browser clicked
	//reset onload event to null
   this.onload=null;

  testImgElem.parentNode.removeChild(testImgElem); // remove temporary image

} //eof testImgElem.onabort

   //Apply src of image to be downloaded.
	 testImgElem.setAttribute("src",newImgSrc);//Assign src to tempImhElem	

}//end if b

else{ // else b. LoadRecord must ==1, so attempt to download large image has already been made successfully, hence show visible enlargement immediately
	  
 img.src=newImgSrc;  // apply src of image ending in 2.jpg to img
  setParameters();

 img.style.backgroundColor="#fff";// give image white background. 
 
 
  startMag(imgId,magnifyTime,tStep);
 
  } //end else b
	
	}  // end if a
  
  else{ //else a. Original image is a reduced  large image, hence no need to test if image has loaded
 	
    img.src=elem.src; // apply src of large image, which has been reduced in size, to img. This image does not end in 1.jpg or 2.jpg
	 loadRecord[imgNo]=1; // set loadRecord to indicate image has been downloaded
	 setParameters();
	  img.style.backgroundColor="#fff";// give image white background. 
	 startMag(imgId,magnifyTime,tStep);
	 } // end else a

} //eof magnify
	 
	 ///////SETPARAMETERS /////////////////////
	 
	 function setParameters(){

	//copy original image's attributes to its replacement
	img.border=elem.border;
	img.className = elem.className;
	img.id = "copy" + elem.id;
	imgId=img.id;
	img.width = elem.width;
	img.height = elem.height;
	img.alt = elem.alt;
	
	//set styles of replacement image
	   img.style.width = initImgW + "px";
		img.style.height = initImgH + "px";
		img.style.position = "absolute";
		img.style.left = startLeft + "px";
		img.style.top = startTop + "px";
		img.style.cursor = elem.style.cursor;
		img.style.zIndex = elem.style.zIndex +2;
		img.style.visibility="visible";
		
		//Attach image to parent of elem
		parentNd.appendChild(img);
		
	//Get window dimensions and x,y scroll offsets
	sizeWin=sizeInsideWindow();
	winW=parseInt(sizeWin.wWin,10); // convert to integer, radix 10
	winH= parseInt(sizeWin.hWin,10); // convert to integer radix 10
	
	winOffset=getWindowOffset();
	hScroll=parseInt(winOffset.horizontalScroll,10); // convert to integer, radix 10
	vScroll =parseInt(winOffset.verticalScroll,10); // convert to integer, radix 10
   basicGapW=40;
   basicGapH=30;
  maxWinW=1600;
  if(winW>maxWinW){winW=maxWinW};
	/* Get magnification to bring edge of image nearly to within 'basicgapW' or 'basicGapH' value from window edge, keeping aspect ratio unchanged.*/
	var scaleX= (winW*0.95-2*(basicGapW))/initImgW; //By taking 0.95 of winW, the gap around the image is always greater than the value of basicGapW and increases the wider the screen. 
	var scaleY= (winH*0.95-2*(basicGapH))/initImgH;
	var magnify;
	if(scaleX>scaleY){
	magnify =scaleY;
	}else{
	magnify = scaleX;
	}
	
	//Get width of new image when fully magnified
	finalImgW=parseInt(initImgW*magnify,10);
	finalImgH=parseInt(initImgH*magnify,10); 
	
	}  //eof setParameters
	
	///////STARTMAG/////////
	
	function startMag(imgId,magnifyTime,tStep){
	
	direction=1; //value of 'direction' used for magnification
  
  img=document.getElementById(imgId); 
  
	/* Get no. of incremental steps in the image magnification process,
	where tStep (milliisecs) is time per enlargement step and magnifyTime (millisecs) is time to magnify image fully.*/
	noSteps = magnifyTime/tStep; 
	
	//Get top and left positions of magnified image assuming image is in centre of visible window
	finishLeft=parseInt(winW/2 -paddingW -borderW+ hScroll-(finalImgW/2),10);	
	finishTop=parseInt(winH/2 + vScroll-(finalImgH/2),10) - paddingW - borderW;
	
	//Get incremental changes in left, top, width and height of replacement image
	maxShiftX=startLeft-finishLeft;
	maxShiftY=startTop-finishTop;
	meanDeltaX=(maxShiftX/noSteps)-0; 
	meanDeltaY=(maxShiftY/noSteps)-0;  
	increaseW=finalImgW-initImgW;
	increaseH=finalImgH-initImgH;
	deltaX=meanDeltaX*1.5; // start deltaX at 1.5 times the mean. leading to a final deltaX of 0.5 times the mean
	deltaY=meanDeltaY*1.5; 
	incrementalDeltaX=(meanDeltaX/noSteps)-0; //after each step the change,deltaX, in startLeft is altered by incrementalDeltaX
	incrementalDeltaY=(meanDeltaY/noSteps)-0;  //after each step the change, deltaY, in startTop is altered by incrementalDeltaY
	
	meanDeltaW=(increaseW/noSteps)-0;
	meanDeltaH =(increaseH/noSteps)-0; 
	deltaW=meanDeltaW*1.5;
	deltaH=meanDeltaH*1.5; 
	incrementalDeltaW=(meanDeltaW/noSteps)-0; //after each step, the change,deltaW, in imgW is altered by incrementalDelaW
	incrementalDeltaH=(meanDeltaH/noSteps)-0;  //after each step, the change, deltaH, in imgH is altered by incrementalDeltaH
	
	//Make replacement image visible and expand it, using function resize() with direction=1 
	
	img.style.visibility="visible";
	img.style.borderStyle="solid";
	img.style.borderWidth="thin";
	img.style.borderColor="#785018";
	imgW=initImgW;
	imgH=initImgH;
	
	resize(imgId,direction,imgW,imgH,tStep);
	}	//eof startMag
		
		
	/////////RESIZE ////////////
		
	function resize(imgId,direction,imgW,imgH,tStep){  //this function enlarges or shrinks the 'inflatable' image depending on the value of direction.

	//Get 'inflatable' image element
	img=document.getElementById(imgId);
	
	//Get left and top co-ordinates of replacement image for each size change
	deltaX-=incrementalDeltaX*direction-0; // reduce deltaX by incrementalDeltaX each step
	deltaY-=incrementalDeltaY*direction-0;  // reduce deltaY by incrementalDeltaY each step
	
	startLeft-=deltaX*direction-0;
	startTop-=deltaY*direction-0;
	
	deltaW-=incrementalDeltaW*direction-0; // reduce deltaW by incrementalDeltaW each step
	deltaH-=incrementalDeltaH*direction-0; //reduce deltaH by incrementalDeltaH each step
	
	//Get width and height of 'inflatable' image for each size change
	imgW+=deltaW*direction-0; //  Don't convert to integer as repeateded rounding builds up errors
	imgH+=deltaH*direction-0;  //  Don't convert to integer as repeateded rounding builds up errors
	
	//Update style values
	img.style.left=startLeft +"px";
	img.style.top=startTop + "px";
	img.style.width=imgW + "px";
	img.style.height=imgH + "px";
	
	//Ensure 'inflatable' image overlays existing text.
	img.style.zIndex =img.style.zIndex-0+1; //-0 ensures zIndex is a number.
	
	//Make 'inflatable' image visible
	
	img.style.visibility="visible"; 
	
	//Continue resizing 'inflatable' image every tStep millisecs until it has reached final width or height by calling resize() recursively.
	
	if((imgW*direction<finalImgW*direction)&&(imgH*direction<finalImgH*direction)) { //if b
	var str = "resize('" + imgId+"',"+ direction + "," +imgW + "," + imgH + "," + tStep +");";
	setTimeout(str, tStep);
	} // end if b
	
	else{//else b - end of an enlargement or a shrink
	
	 if (direction==1){  // if c  -   image has reached full size
	 
	// Add padding and border to the fullsize visible image - background colour already specified.
	
	img.style.padding=paddingW +"px";
	img.style.padding.color="#eeddcc";img.style.visibility="visible";
	img.style.border=borderW +"px";
	
	// For IE we set 'inset' border because IE's 'double' border lets underlying text show through.
	if(document.all){  //if d
	img.style.borderStyle= "inset"; 
	 img.style.borderColor = "#785018";
	// allow any non IE browser to pick a border that it supports, preferably 'double' 
	}// end if d
	 else{ //else d
	img.style.borderStyle= "double" || "solid";
	img.style.borderColor = "#785018";
	} //end else d
	
  // if (loadRecord[imgNo]==1){ //if e - Add caption,instructions and assign onmouseout event////////////////////    Query  /////////
	//Add caption and instructions to fullsize image
	addLabels(imgTitle,imgId);
	
	
	
	//Assign onmouseout event to operate on function 'setupShrink'. This event triggers a function, which shrinks the 'inflatable' image back to thumb size.
	e=window.event;
	img.onmouseout=function(){setupShrink(e,tStep)};  //We don't need anything sophisticated, so use DOM 0 event handling techniques
	//} // end if e
	
	/*
	 //If more than one event handler is wanted for a particular event on a particular object
	 //or there is a need to handle target's ancestor elements during capture or bubble phase, use DOM 2 methods
	if(document.addEventListener){  // for DOM 2 compatible browsers
	img.addEventListener("mouseout",setupShrink,false);
	}else{
	eventHandler.add(img,"mouseout",setupShrink);// special funcion  (found in 'global.js') needed for IE,which is not DOM 2 compatible.
	}
	*/
	
	} // end if c
	
	if(direction==-1){ // if f - image is fully shrunk
	
	//hide shrunken image and remove it from its parent
	if(img.style.display){ // if g
	img.style.display="none";
	} // end if g
	img.style.visibility="hidden";
	
	//Remove the visible 'inflatable' image from its parent, leaving the thumb image visible
	img.parentNode.removeChild(img); 
	
	//Reinstate onclick events for all 'inflatable' image elements
	for( var i=0;i<imgElems.length;i++) {
     imgElems[i].onclick= function(){magnify(this)};
   } //end of for
     return;
  } // end if f
 } //end else b
} //eof resize 
		
		
//////// SETUPSHRINK ///////////

  function setupShrink(e,tStep){   //This function is triggered by the event onmouseout, when the mouse cursor moves off the fullsize image.
  if(!e) e = window.event; 
 
 //Get 'inflatable' image element
   img=document.getElementById(imgId);
   shrink(img);
   } //eof setupShrink
   
   ///////SHRINK//////
   
   function shrink(img){
	
	// remove padding and outline from image
	img.style.padding=0 +"px";
	img.style.border=0+"px";
	img.style.borderStyle= "none";
	img.style.outlineWidth=0+"px";
	img.style.outlineStyle="none";
	var temp =finishLeft;
	finishLeft=startLeft;
	startLeft=temp;
	var temp=finishTop;
	finishTop=startTop;
	startTop=temp;
	imgW=finalImgW;
	imgH=finalImgH;
	finalImgW=initImgW;
	finalImgH=initImgH;
	direction=-1;  // value of direction used for shrink
	
	//Use DOM 0 method to remove onmouseout event which triggered function 'setupShrink' as its job is done.
	img.onmouseout=null;
	
	/*
	 // To remove event 'onmouseout', if it was added using DOM 2 methods
	if(document.removeEventListener){//for DOM 2 compatible browsers
		img.removeEventListener("mouseout",setupShrink,false);
	}else{
	eventHandler.remove(img,"mouseout",setupShrink);// special funcion (found in global.js).needed for IE browsers
	}
	*/
	
	//if (loadRecord[imgNo]==1){  ////////////////////////////////////QUERY////////////////////////////////////////////////////////////////////////////////
	divCaption.parentNode.removeChild(divCaption); // remove caption to 'inflatable' image
	divInstruction.parentNode.removeChild(divInstruction); // remove instruction to 'inflatable' image
	//}
	resize(imgId,direction,imgW,imgH,tStep); // reduce fullsize image back to 'thumb' size
} //eof setupShrink
	
	///////// ADDLABELS ////////////
	
	 function addLabels(text,imgId){ //Add caption and instruction to fullsize image, where 'text' is the name attribute of the thumbnail image.
	 
	 //Get 'inflatable' image element
	 img=document.getElementById(imgId);
	 
	 //Get parent node of 'inflatable' image
	 imgParent=img.parentNode;
	 
	 //Deduce length of caption in pixels
	numCaptionLetters=text.length;
	lenText=Math.floor(numCaptionLetters*4.5); // This depends on font, font size and letters used in caption.
	
	 //Create text node for caption
	var textNode= document.createTextNode(text);
	
	// Create div element
	divCaption = document.createElement("div");
	
	//Append caption to div element
	divCaption.appendChild(textNode);
	
	//Set up styles
	divCaption.style.height = "15px";
	divCaption.style.position = "absolute";
	divCaption.style.left = Math.floor(finishLeft + finalImgW/2 - lenText/2-25) + "px";
	divCaption.style.top = finishTop + finalImgH + borderW + paddingW +6 +"px";
	divCaption.style.textAlign = "center";
	divCaption.style.backgroundColor = "#ffffff";
	divCaption.style.color="#000000";
	divCaption.style.fontSize = "9pt";
	divCaption.style.fontFamily = "Arial";
	divCaption.style.zIndex=img.style.zIndex+5;
	
	//Append div element to parent of 'inflatable' image, (making div and img siblings).
	imgParent.appendChild(divCaption);
	
	//Write instruction for reducing size of photo.
	var instruction="< To shrink the photo, move the mouse-cursor from inside to outside the photo frame.>";
	
	//Get length of instruction in pixels
	numLettersInstruction=instruction.length;
	lenInstruction =Math.floor(numLettersInstruction*3.5);//This depends on font, font size and letters used in instruction.
	
	//Append instruction to new div element.
	var instructionNode= document.createTextNode(instruction);
	divInstruction = document.createElement("div");
	divInstruction.appendChild(instructionNode);
	
	 //Setup styles
	divInstruction.style.height="15px";
	divInstruction.style.position = "absolute";
	divInstruction.style.left = Math.floor(finishLeft + finalImgW/2 -15 -lenInstruction/2) + "px";
	divInstruction.style.top= finishTop+2  + "px";
	divInstruction.style.textAlign="center";
	divInstruction.style.backgroundColor="#306030";
	divInstruction.style.color="#ffffff";
	divInstruction.style.fontSize="8pt";
	divInstruction.style.fontFamily="Arial";
	divInstruction.style.zIndex=img.style.zIndex+3;
	 
	 //Append divInstruction to parent of fullsize image, (making divInstruction,divCaption and img siblings),
	imgParent.appendChild(divInstruction);
	}  //eof addLabels

//////NEWNOTICE////

function newNotice(newNote){

divNotice[imgNo].removeChild(noticeNode[imgNo]);
noticeNode[imgNo]=document.createTextNode(newNote);
divNotice[imgNo].appendChild(noticeNode[imgNo]);
} //eof newNotice

//////// WAITSIGN ///////////

function waitSign(sign,culla){
   
//Get length of sign in pixels
numSignLetters =sign.length;
var lenSign=Math.floor(numSignLetters*4.5); //This depends on font size

//Append sign to new div element
var signNode=document.createTextNode(sign);
divSign=document.createElement("div");

//Get element elem using imgTitle as id.
elem=document.getElementById(imgTitle);
elemParent=elem.parentNode;

//Set up styles
divSign.style.visibility="visible";
divSign.style.height="12px";
divSign.style.position="absolute";
divSign.style.left=Math.floor(startLeft+initImgW/2-8 -lenSign/2) +"px";
divSign.style.top=startTop +"px";
divSign.style.backgroundColor=culla;
divSign.style.color="#ffddee";
divSign.style.fontSize="8pt";
divSign.style.fontFamily="Arial";
divSign.style.zIndex=elem.style.zIndex+2;
divSign.appendChild(signNode);

// append divSign to parent of elem
elemParent.appendChild(divSign);

} //eof waitSign


addLoadEvent(init);
addLoadEvent(addNotice); //The function addLoadEvent is in global.js
