// picture functions for erik-style picture sites
// copyright 2001 - 2005 Erik Nilsson
// r050529

//Issues: 
//	control frame image size is fixed 60x40
//	control frame does not scroll (Not important at the moment.)
//	non-javascript version is lama
//	it would be nice to show the date the picture was taken. (Sort of half started.)



// start up
function init() {
 //init state object
 state = new stateOb(0,0)
 setBrowserVersion()
 initContent()
 lastChapter=findLastChapter()
 firstDisplayableImage = findFirstDisplayableImageInChapter(0)
 lastDisplayableImage = findLastDisplayableImageInChapter(top.lastChapter)
 if( "last" == g_firstDisplayedChapter) {
   top.newChapter(top.chapters.length-1)
 } else {
  top.newChapter(g_firstDisplayedChapter)
 }
  top.updateOneFrameType("controlFrame")
}



//
// Frames
//

//state object
function stateOb(chapter, image) {
 this.chapter=chapter
 this.image=image
}

//update a frame
function updateFrame(frameIndex, chapter, image) {
 if (frameIsType(frameIndex, "controlFrame")) {
   updateControlFrame(frameIndex, chapter)
 } else if (frameIsType(frameIndex, "pictureFrame")) {
   updatePictureFrame(frameIndex, chapter, image)
 }  else if (frameIsType(frameIndex, "thumbFrame")) {
   updateThumbFrame(frameIndex, chapter, image)
 } 
}


//scroll a frame
function scrollFrame(frameIndex, chapter, image) {
 if (frameIsType(frameIndex, "controlFrame")) {
   scrollControlFrame(frameIndex, chapter)
 }  else if (frameIsType(frameIndex, "thumbFrame")) {
   scrollThumbFrame(frameIndex, chapter, image)
 } 
}

//update all frames
function updateAllFrames() {
 for(var i=0; i<top.frames.length; i++) {
  updateFrame(i, top.state.chapter, top.state.image)
 }
}

//scroll all scrollable frames
function scrollAllFrames() {
 for(var i=0; i<top.frames.length; i++) {
  scrollFrame(i, top.state.chapter, top.state.image)
 }
}


// is this still used?
//update all frames, except one type of frame
function updateAllFramesExceptOneType(frameType) {
 for(var i=0; i<top.frames.length; i++) {
  if(!frameIsType(i, frameType)) {
   updateFrame(i, top.state.chapter, top.state.image)
  }
 }
}

//update  one type of frame
function updateOneFrameType(frameType) {
 for(var i=0; i<top.frames.length; i++) {
  if(frameIsType(i, frameType)) {
   updateFrame(i, top.state.chapter, top.state.image)
  }
 }
}

///// not used anymore?
//update all frames except one
function updateAllFramesButOne(frameIndex) {
 for(var i=0; i<frameIndex; i++) {
  updateFrame(i, top.state.chapter, top.state.image)
 }
 for(var i=frameIndex+1; i<top.frames.length; i++) {
  updateFrame(i, top.state.chapter, top.state.image)
 }
}

//returns true if the frame is of the given type, based on the frame name
//only the beginning of the frame name is checked, so you can have as
//many frames of the same type as you want: pictureFrame1, pictureFrame2, etc.
function frameIsType(frameIndex, frameType) {
 return (top.frames[frameIndex].name.indexOf(frameType)==0)
}

//write to a frame
function frameWrite(frameIndex, str) {
 top.frames[frameIndex].document.write(str)
}

//show what will be written to a frame, then write it
//this is a debugging tool
function frameWriteA(frameIndex, str) {
 alert("frame "+frameIndex+"\n"+str)
 frameWrite(frameIndex, str)
}

//force display of frame
function frameClose(frameIndex) { 
 top.frames[frameIndex].document.close()
}


//find index for a frame
function frameIndexOf(frameName) {
 for (var i=0; i< top.frames.length; i++) {
  if (top.frames[i].name == frameName) {
   return i
  }
 }
 return -1 //frame was not found
}

//height of a frame
function frameHeight(frameIndex) {
 return(top.frames[frameIndex].innerHeight ? top.frames[frameIndex].innerHeight : top.frames[frameIndex].document.body.clientHeight)
}

//height of the document in a frame
function frameContentsHeight(frameIndex) {
 return(top.frames[frameIndex].document.height ? top.frames[frameIndex].document.height : 
                                                 top.frames[frameIndex].document.body.scrollHeight)
}



//
// contents
//

//image object
function image(name, thumbName, thumbnailType, caption, shortCaption, comment, people, thumbnailHeight, docPosition, big) {
 this.name=name
 this.thumbName=thumbName
 this.thumbnailType=thumbnailType // 0=picture, 1=html, 2=title, 3=space 4=special picOfWeek thumbnail
 this.caption=caption
 this.shortCaption=shortCaption 
 this.comment=comment
 this.people=people
 this.thumbnailHeight=thumbnailHeight
 this.docPosition=docPosition
 this.big=big // 1 if there is a big file
}

//chapter object
function chapter(name, thumbnailType, caption, shortCaption, width) {
 this.name=name
 this.thumbnailType=thumbnailType // 0=picture, 1=html, 2=title, 3=space 4=special picOfWeek thumbnail
 this.caption=caption
 this.shortCaption=shortCaption 
 this.width=width
}



//
// navigation
//

function displayNavControls(frameIndex) {
 var previousTxt
 if( atFirstDisplayableThumbPostionInChapter() ) {
  previousTxt = "previous chapter"
 } else {
  previousTxt = "beginning of chapter"
 }

 frameWrite(frameIndex, "<table border=0 cellspacing=0 cellpadding=0><tr><td>" +
 navControlTag(frameIndex,"First",           navDescTxt("first",	findFirstDisplayableImage()),				false)+" &nbsp; "+
 navControlTag(frameIndex,"PreviousChapter", navDescTxt(previousTxt,	findPreviousChapter(top.state)),			false)+" &nbsp; "+
 navControlTag(frameIndex,"Previous",        navDescTxt("previous",	findPreviousDisplayableThumbPosition(top.state)),	false)+" &nbsp; "+
 navControlTag(frameIndex,"Next",            navDescTxt("next",		findNextDisplayableThumbPosition(top.state)),		true)+" &nbsp; "+
 navControlTag(frameIndex,"NextChapter",     navDescTxt("next chapter",	findNextChapter(top.state)),				true)+" &nbsp; "+
 navControlTag(frameIndex,"Last",            navDescTxt("last",		findLastDisplayableImage()),				true)+
 "</td></tr></table>")
}

// write navigation controls to the current document
function writeNavControlsToDocument() {
 displayNavControls(frameIndexOf(self.name))
}

// write a description of the navigation action for tooltip and status text
function navDescTxt(rawDescription, aState) {
 var description = rawDescription
 if ("" != stateShortCaption(aState)) {
  description = description + ":  " + stateShortCaption(aState)
 }

 return description
}

function navControlTag(frameIndex, rawName, description, isForwardMoving) {
 var moveFnName = "move"+rawName
 var findFnName = "find"+rawName
 var name = rawName.toLowerCase()
 var dimmed = false
 
 // figure out which direction we are going
 if(isForwardMoving) {
  imgFnName = "newImgForward"
  if(atLastDisplayableThumbPostion()) {
   dimmed = true // this control can't go anywhere, so dim it
   description = "Already at the end. Cannot go forward."
  }
 } else {
  imgFnName = "newImgBackward"
  if(atFirstDisplayableThumbPostion()) {
   dimmed = true // this control can't go anywhere, so dim it
   description = "Already at the beginning. Cannot go backward."
  }
 }
 safeDescription = encodeProtected(description) //Safe to use in Javascript in an HTML tag
 encodedDescription = encodeNormal(description) //Safe for alt text
 
 var tagTxt // holds the text for the tag

 if (true == dimmed) {
  // dimmed control is not actually a tag, just an image
  tagTxt = "<img name="+name+" src='"+name+"dim.gif' border=0 alt='"+encodedDescription+"'>"
 } else {
  // make a tag for an active control
  tagTxt = "<a href='JavaScript:top."+moveFnName+"()'"
 
  if(is_modern) {
   tagTxt = tagTxt+" onmouseover=\"top."+imgFnName+"("+frameIndex+",'"+name+"','"+safeDescription+"','hot');return true\" "+
                   "onmouseout=\"top."+imgFnName+"("+frameIndex+",'"+name+"','"+safeDescription+"','');return true\""
  }
  tagTxt = tagTxt+"><img name="+name+" src='"+name+".gif' border=0 alt='"+encodedDescription+"'></a>"
 } 
 return tagTxt
}

// Change an image, as in for a mouseover of a hotspot
function newImg(frameIndex, name, suffix, dimmed) {
 top.frames[frameIndex].document[name].src=name+suffix+".gif"
}

// Change nav control image unless we can't move forward
function newImgForward(frameIndex, name, description, suffix) {
 if('hot' == suffix) {
  top.displayStatus(description) //initiating hover, show description
 } else {
  top.displayStatus('') //terminating hover, hide description
 }

 if(!atLastDisplayableThumbPostion()) {
  top.frames[frameIndex].document[name].src=name+suffix+".gif"
  if(top.g_navControlsShowThumb == "yes") {
   if('hot' == suffix) {
    //initiating hover
    
   //show preview thumb
    newImg = new stateOb(0,0) 
    switch(name) {
     case 'next':
      newImg = findNextDisplayableThumbPosition(top.state);break;
     case 'nextchapter':
      newImg = findNextChapter(top.state) ;break;
     case 'last':
       newImg.chapter = top.lastChapter //start with very last image
       newImg.image = top.lastDisplayableImage
      break;
     default:
      break;
    }   
    if (thumbPositionHasPictureThumbNail(newImg)){
     top.frames[frameIndex].document['navFlash'].src=showFilePath(newImg, "thumb")
    } else {
     top.frames[frameIndex].document['navFlash'].src="grey.gif"
    }
   } else {
    //terminating hover, hide preview thumb
    top.frames[frameIndex].document['navFlash'].src='1.gif' 
   }
  }
 } 
}


// Change nav control image unless we can't move backward
function newImgBackward(frameIndex, name, description, suffix) {
 if('hot' == suffix) {
  top.displayStatus(description) //initiating hover, show description
 } else {
  top.displayStatus('') //terminating hover, hide description
 }

 if(!atFirstDisplayableThumbPostion()) {
  top.frames[frameIndex].document[name].src=name+suffix+".gif"
  if(top.g_navControlsShowThumb == "yes") {
   if('hot' == suffix) {
    //initiating hover

    //show preview thumb
    newImg = new stateOb(0,0) 
    switch(name) {
     case 'previous':
      newImg = findPreviousDisplayableThumbPosition(top.state);break;
     case 'previouschapter':
      newImg = findPreviousChapter(top.state) ;break;
     case 'first':
       newImg.chapter = 0 //start with very last image
       newImg.image = top.firstDisplayableImage
      break;
     default:
      break;
    }   
    if (thumbPositionHasPictureThumbNail(newImg)){
     top.frames[frameIndex].document['navFlash'].src=showFilePath(newImg, "thumb")
    } else {
     top.frames[frameIndex].document['navFlash'].src="grey.gif"
    }
   } else {
    //terminating hover, hide preview thumb
    top.frames[frameIndex].document['navFlash'].src='1.gif'
   }
  }
 }
}

// move functions

function movePrevious() {
 move(findPreviousDisplayableThumbPosition(top.state))
}


function moveNext() {
 move(findNextDisplayableThumbPosition(top.state))
}

function moveFirst() {
 move(findFirstDisplayableImage())
}

function moveLast() {
 move(findLastDisplayableImage())
}


function movePreviousChapter() {
 top.state = findPreviousChapter(top.state)
 top.updateFramesForNav()
}


function moveNextChapter() {
 top.state = findNextChapter(top.state)
 top.updateFramesForNav()
}


function move(aState) {
 if (top.thumbPostionIsDisplayable(aState)) {
  top.state=aState
  top.updateFramesForNav()
 }
}


function jump(chapter, image) {
 if (top.imageInChapterIsDisplayable(chapter, image)) {
  top.state.chapter = chapter
  top.state.image = image
  top.updateFramesForNav()
 }
}


// find functions

function findLastChapter() {
 return top.pix.length-1
}

function findLastImageInChapter(chapter) {
 return top.pix[chapter].length-1
}

function findLastImageInCurrentChapter() {
 return findLastImageInChapter(top.state.chapter)
}

function findFirstDisplayableImageInChapter(chapter) {
 //there must be one displayable image in the first chapter
 //this could more robustly return a state instead of an image number
 for(var i=0; !top.imageInChapterIsDisplayable(chapter, i); i++){}
 return i
}

function findLastDisplayableImageInChapter(chapter) {
 for(var i = top.pix[chapter].length-1; !top.imageInChapterIsDisplayable(chapter, i); i--) {}
 return i
}

function findPreviousThumbPosition(byRefState) {
 aState = new cloneOb(byRefState) //byval state

 if(aState.image > 0) {
  //not at the first image of a chapter, back up one image
  aState.image--
 } else {
  if(aState.chapter > 0) {
   //not at the first chapter, back up one chapter
   aState.chapter--
   aState.image=top.findLastImageInChapter(aState.chapter)
  }
 }
 return aState
}

function findNextThumbPosition(byRefState) {
 aState = new cloneOb(byRefState) //byval state

 if(aState.image < top.findLastImageInChapter(aState.chapter)) {
  //not at the last image of a chapter, go forward one image
  aState.image++
 } else {
  if(aState.chapter < top.lastChapter) {
   //not at the last chapter, go forward one chapter
   aState.chapter++
   aState.image=0
  }
 }
 return aState
}

function findNextDisplayableThumbPosition(byRefState) {
 aState = new cloneOb(byRefState) //byval state

 tmpState = new cloneOb(aState) // backup copy of state
 

 aState = findNextThumbPosition(aState) //go forward one
 while( (!thumbPostionIsDisplayable(aState)) &&
        (!isVeryLastThumbPostion(aState))) {
  //the thumbpostion is not the last image of the last chapter, and isn't displayable,
  //go forward, looking for a displayable image
  aState = findNextThumbPosition(aState)
 }
 if (!thumbPostionIsDisplayable(aState)) {
  //we were already at the last displayable thumb position
  aState.chapter = tmpState.chapter
  aState.image = tmpState.image
 }
 return aState
}
 
 
function findPreviousDisplayableThumbPosition(byRefState) {
 aState = new cloneOb(byRefState) //byval state
 tmpState = new cloneOb(aState) //copy of state
 aState = findPreviousThumbPosition(aState)  //back up one
 while( (!thumbPostionIsDisplayable(aState)) &&
        (!isVeryFirstThumbPostion(aState))) {
  //the thumbpostion is not the first image of the first chapter, and isn't displayable,
  //go backward, looking for a displayable image
  aState = findPreviousThumbPosition(aState)
 }

 if (!thumbPostionIsDisplayable(aState)) {
  //we were already at the first displayable thumb position
  aState.chapter = tmpState.chapter
  aState.image = tmpState.image
  }
 return aState
}


function findPreviousChapter(byRefState) {
 aState = new cloneOb(byRefState) //byval state
 image = aState.image //remember where we started
 aState.image = findFirstDisplayableImageInChapter(aState.chapter)
  
 if (image == aState.image) {
  //we were already at the end of the chapter
  //go to the previous chapter if there is one.
  if (aState.chapter > 0) {
   aState.chapter --
   aState.image = findFirstDisplayableImageInChapter(aState.chapter)
  }
 }
 return aState
}

 
function findNextChapter(byRefState) {
 aState = new cloneOb(byRefState) //byval state

 if (aState.chapter < lastChapter) {
  //Not at last chapter, go to next one
  aState.chapter ++
  aState.image = findFirstDisplayableImageInChapter(aState.chapter)
 } else {
  //at last chaper, move to last image in chapter
  aState.image = findLastDisplayableImageInChapter(aState.chapter)
 } 
 return aState
}

// return the short cation of a state
function stateShortCaption(aState) {
 return top.pix[aState.chapter][aState.image].shortCaption
}

function findFirstDisplayableImage() {
 aState = new stateOb(0,0) 
 aState.image = findFirstDisplayableImageInChapter(aState.chapter)
 return aState
}

function findLastDisplayableImage() {
 aState = new stateOb(top.lastChapter,top.lastDisplayableImage) 
 return aState
}



// at functions

function atFirstDisplayableThumbPostion() {
 return ((0==top.state.chapter) && (top.firstDisplayableImage==top.state.image))
}

function atLastDisplayableThumbPostion() {
 return ((top.lastChapter==top.state.chapter) && (top.lastDisplayableImage==top.state.image))
}

function atFirstDisplayableThumbPostionInChapter() {
 return (findFirstDisplayableImageInChapter(top.state.chapter) == top.state.image)
}



// is functions

function currentThumbPostionIsDisplayable() {
 return thumbPostionIsDisplayable(top.state)
}

function thumbPostionIsDisplayable(aState) {
 return top.imageInChapterIsDisplayable(aState.chapter, aState.image)
}

function imageInChapterIsDisplayable(chapter, image) {
 thumbType = top.pix[chapter][image].thumbnailType
 return ((0==thumbType) || (1==thumbType) || (4==thumbType))
}

function thumbPositionHasPictureThumbNail(aState) {
 thumbType = thumbPositionThumbnailType(aState)
 return(0==thumbType || (4==thumbType))
}

function isVeryFirstThumbPostion(aState) {
 return ((0==aState.chapter) && (0==aState.image))
}


function isVeryLastThumbPostion(aState) {
 return ((aState.chapter==top.lastChapter) && (aState.image==findLastImageInChapter(top.lastChapter)))
}



//
// menus
//

function updateControlFrame(frameIndex, chapter) {
 writeFramePrefix(frameIndex, 15, 5, 5, g_controlBgImage)
 frameWrite(frameIndex, 
 "<table border=0 cellspacing=0 cellpadding=0>"+
 "<tr><td width=20></td><td align=left nowrap>"+
 "<font class=title size=+3>" + top.g_title + "</font>")
 if(top.g_navControlsInTitle == "yes") {
  //Show navigation controls to right of title
  frameWrite(frameIndex,"</td><td align=center valign=middle width=208>")
  displayNavControls(frameIndex)
  if(top.g_navControlsShowThumb == "yes") {
   //nav controls include a thumbnail quick reference
   frameWrite(frameIndex,"</td><td><img name=navFlash width=60 height=40 src='1.gif'>")
  }
 }
   frameWrite(frameIndex,"</td></tr>"+
  "<tr><td height=12></td></tr>"+
 "</table>"+
 "<table border=0 cellspacing=0 cellpadding=0>"+
  "<tr>"+
   "<td width=20 height=16><img src=1.gif width=20 height=1></td>")
 for(var i=0;i<top.chapters.length;i++) {
  displayMenuItem(frameIndex,i,chapter)
 }
 

 frameWrite(frameIndex,"</tr><tr><td height=38></td><td></td>")
 
 //lines between images
 for(i=1;i<top.chapters.length;i++) {
  if(0==top.chapters[i].thumbnailType) {
   //next option is a picture thumbnail, draw the line
   frameWrite(frameIndex,"<td align=center valign=middle><img src=black.gif width=10 height=1></td>")
  } else {
   //no line, just put some space in
   frameWrite(frameIndex,"<td align=center valign=middle><img src=1.gif width=10 height=1></td>")
  }
 }
 
 //space for cursor
 frameWrite(frameIndex,"</tr><tr><td></td><td></td>")
 for(i=0;i<top.chapters.length;i++) {
   frameWrite(frameIndex, "<td height=5><center>")
   makeCursor(frameIndex, i, i==chapter, top.g_controlFrameCursorHeight, top.g_controlFrameCursorWidth)
   frameWrite(frameIndex, "</center></td><td></td>")
 }
 frameWrite(frameIndex,"</tr></table>")
 
 writeFrameSuffix(frameIndex)
}


function scrollControlFrame(frameIndex, chapter) {
 // !!!! implement this!
}


// write the HTML for a pictorial menu item
function displayMenuItem(frameIndex, option, chapter) {
 var aChapter=top.chapters[option]
 var title = aChapter.shortCaption
 var caption = aChapter.caption
 var fName = aChapter.name
 var thumbType = aChapter.thumbnailType
 var width = aChapter.width
 
 frameWrite(frameIndex,"<td></td><td align=center valign=top rowspan=2")
 if(""!=width) {
  frameWrite(frameIndex," width="+width)
 }

 frameWrite(frameIndex,"><a name=a"+option+" class=smenu href=\"javascript:top.currentMenu('"+option+"')\"")
 if(is_modern) { 
  frameWrite(frameIndex,
   " onmouseover=\"top.menuMouseOver("+frameIndex+","+"'"+option+"');return true\" "+
   "onmouseout=\"top.menuMouseOut("+frameIndex+","+"'"+option+"');return true\">")
 } else {
   frameWrite(frameIndex,">")
 }
 if(option==chapter) {
  frameWrite(frameIndex,redText(title))
 } else {
  frameWrite(frameIndex,title)
 }
 if(0==thumbType) {
  frameWrite(frameIndex,
   "<br><img name=m"+option+" src='"+option+"/"+g_thumbDir+"/"+fName+"' alt=\""+caption+"\" border=0 height=38>")
 }
frameWrite(frameIndex,"</a></td>")
}


// onMouseOver action for menus
function menuMouseOver(frameIndex, option) {
 // if this image is for the current option, indicate this by not highlighting
 // otherwise, display the highlight image
 if(option!=top.state.chapter) {
  var fName = top.chapters[option].name
  var thumbType = top.chapters[option].thumbnailType

  displayStatus("click for pictures of: " + top.chapters[option].caption) // put the option on the status line 
  hoverCursor(frameIndex, option)

  if(("yes"==g_replaceMenuPictureOnHover) && (0==thumbType)) {
   top.frames[frameIndex].document["m"+option].src=option+"/"+g_thumbDir+"/o_"+fName
  }
 } else {
  displayStatus(' this is the current menu item ')
 }
}

// onMouseOut action for menus
function menuMouseOut(frameIndex, option) {
 var fName = top.chapters[option].name
 var thumbType = top.chapters[option].thumbnailType
 
 if(0==thumbType) {
  top.frames[frameIndex].document["m"+option].src=option+"/"+g_thumbDir+"/"+fName
 }
 if(option!=top.state.chapter) {
  clearCursor(frameIndex, option)
 }
 displayStatus('')
}


// make a particular menu item current
function currentMenu(option) {
 top.moveCursor("controlFrame", top.state.chapter, option)
 top.newChapter(option) 
}





//
// thumbnails
//

//write out an entire thumbnail frame
function updateThumbFrame(frameIndex, chapter, currentImage) {
 var chNames = pix[chapter]
 
 writeFramePrefix(frameIndex, 10, 20, 0, g_thumbBgImage)
 frameWrite(frameIndex, "<font class=scaption><center>"+
  "<table cellspacing=0 cellpadding=0>")
 
 if (chNames.length>1) {
  //more than one image in this chapter, so display thumbnail choices
  for (var i=0; i<chNames.length; i++) {
   frameWrite(frameIndex, 
    "<tr align=center><td width=5><img src=1.gif width=5 height=1></td><td width="+top.g_thumbWidth+">")

   var aPix=chNames[i]
   if(0==aPix.thumbnailType) {
    //regular picture thumb	
    displayPictureThumbPlaceholder(frameIndex, chapter, i)
   } else if((1==aPix.thumbnailType) || (4==aPix.thumbnailType)) {
    //text thumb
    displayTextThumb(frameIndex, chapter, i, currentImage)
   } else if(2==aPix.thumbnailType) {
    //title
    displayTitleThumb(frameIndex, chapter, i)
   } else if(3==aPix.thumbnailType) {
    //spacer
    displaySpacerThumb(frameIndex, aPix.name)
   } else {
    //unknown thumb type
    alert("Unknown thumbnail type: "+ aPix.thumbnailType)
   }

   //cursor for thumbnails
   frameWrite(frameIndex, "</td><td width=5>")
   makeCursor(frameIndex, i, i==currentImage, top.g_thumbFrameCursorHeight, top.g_thumbFrameCursorWidth)
   frameWrite(frameIndex, "</td></tr>")
  } 
  
  //now, fill in the thumbnails
  for (var i=0; i<chNames.length; i++) {
   var aPix=chNames[i]
   if(0==aPix.thumbnailType) {
    //regular picture thumb, fill it in
    displayPictureThumbPicture(frameIndex, chapter, i)
    //top.frames[frameIndex].document.images["thumb"+i].src="1.gif"
   }
  }
 }

 frameWrite(frameIndex, "</center></table></font>")
 writeFrameSuffix(frameIndex) 
}

// display a picture thumbnail (without the picture), with correct link and behavior
// Since the thumnail images take some time to download, we'll end up trying to scroll to a position
// that doesn't exist yet in the window. so we make the whole table first.
function displayPictureThumbPlaceholder(frameIndex, aChapter, imageNum) {
 var aThumb=top.pix[aChapter][imageNum]
 var toolTip=aThumb.shortCaption
 var aName=aThumb.name
 
 frameWrite(frameIndex,"<a name=a"+imageNum+" href=\"JavaScript:top.jump('"+aChapter+"','"+imageNum+"')\"")

 if(is_modern) {
  frameWrite(frameIndex,
   " onmouseover=\"top.thumbMouseOver("+frameIndex+","+imageNum+",'"+encodeProtected(toolTip)+"');return true\" " +
   "onmouseout=\"top.thumbMouseOut("+frameIndex+","+imageNum+");return true\"")
 }
 frameWrite(frameIndex,"> <img name=thumb"+imageNum+" src=1.gif border=0 alt='"+encodeNormal(toolTip)+ "' height="+top.pix[aChapter][imageNum].thumbnailHeight+" width="+top.g_thumbWidth+"></a> ")
}


// display the picture in a picture thumbnail
function displayPictureThumbPicture(frameIndex, aChapter, imageNum) {
 var thumbnailName=aChapter+'/'+"thumb"+'/'+getThumbName(aChapter, imageNum)
 top.frames[frameIndex].document.images["thumb"+imageNum].src=thumbnailName
}

// we still need to be able to display a picture thumb, since this is called
// directly from javascript in the HTML
function displayPictureThumb(frameIndex, aChapter, imageNum) {
 displayPictureThumbPlaceholder(frameIndex, aChapter, imageNum) 
 displayPictureThumbPicture(frameIndex, aChapter, imageNum)  
}


// display a text thumbnail, with correct link and behavior
function displayTextThumb(frameIndex, aChapter, imageNum, currentImage) {
 var aThumb=top.pix[aChapter][imageNum]
 var toolTip=aThumb.shortCaption
 var thumbnailText=aThumb.shortCaption
 frameWrite(frameIndex,"<a name=a"+imageNum+" class=smenu href=\"JavaScript:top.jump('"+aChapter+"','"+imageNum+"')\"")

 if(is_modern) {
  frameWrite(frameIndex,
   " onmouseover=\"top.thumbMouseOver("+frameIndex+","+imageNum+",'"+encodeProtected(toolTip)+"');return true\" " +
   "onmouseout=\"top.thumbMouseOut("+frameIndex+","+imageNum+");return true\"")
 }
 frameWrite(frameIndex,">")
 if(currentImage==imageNum) {
  frameWrite(frameIndex,redText(thumbnailText))
 } else {
  frameWrite(frameIndex,thumbnailText)
 }
 frameWrite(frameIndex,"</a> "+spacer(2))
}



// display a title in a thumbnail display
function displayTitleThumb(frameIndex, aChapter, imageNum) {
 var titleText=top.pix[aChapter][imageNum].shortCaption
 frameWrite(frameIndex, spacer(10))
 frameWrite(frameIndex,	"<font class=scaption>"+titleText+"</font>"+spacer(2))
}

// onMouseOver action for picture thumbnails
function thumbMouseOver(frameIndex, option, status) {
 if(option!=top.state.image) {
  top.hoverCursor(frameIndex, option)
  top.displayStatus(status)
 } else {
  top.displayStatus('this is the current picture')
 }
}

// onMouseOut action for picture thumbnails
function thumbMouseOut(frameIndex, option) {
 if(option!=top.state.image) {
  top.clearCursor(frameIndex, option)
 }
 top.displayStatus('')
}


// display a spacer between thumbs
function displaySpacerThumb(frameIndex, space) {
 frameWrite(frameIndex, spacer(space))
}

// calculate document height for a frame, exclusive of the default margin
// !!! need to take a look at this to see if it is still needed !!!
function frameDocDefaultHeight(frameIndex) {
 return frameContentsHeight(frameIndex) - parseInt(g_frameMarginTop) - parseInt(g_frameMarginBottom)
}

// average height of a thumbnail item in a frame
// this doesn't account for space at the beginning or end of the document, 
// which might matter in short frames.
// !!! need to take a look at this to see if it is still needed !!!
function avgThumbnailHeight(frameIndex, chapter) {
 docH = frameDocDefaultHeight(frameIndex)
 itemCount = top.pix[chapter].length
 
 return docH/itemCount
}

// returns 1 if a thumbnail can be clicked on and selected, 0 otherwise
function thumbnailTypeisSelectable(thType) {
 return ((0 == thType) || (1 == thType) || (4 == thType))
}


//scroll a thumb frame
function scrollThumbFrame(frameIndex, chapter, image) {
 top.frames[frameIndex].scroll(0, thumbFrameScrollValue(frameIndex, chapter, image))
}

//amount to scroll to have the best chance of a thumbnail being in a frame
function thumbFrameScrollValue(frameIndex, chapter, image) {
 frameH = top.frameHeight(frameIndex)
 docH = frameDocDefaultHeight(frameIndex)
 
 scrollToCenter = top.pix[chapter][image].docPosition - (frameH/2)
 
 if (scrollToCenter < 0) {
  return 0
 } else if (scrollToCenter > docH) {
  return docH 
 } else {
  return scrollToCenter
 }
}

function thumbPositionThumbnailType(aState) {
 return (pix[aState.chapter][aState.image].thumbnailType)
}


//
// images
//


//update display to refelect a new picture
function newImage(imageNum) {
 top.moveCursor("thumbFrame", top.state.image, imageNum)
 top.state.image=imageNum
 top.updateFramesForNewImage()
}

//update display to reflect a new chapter
function newChapter(chapterNum) {
 top.state.chapter=chapterNum
 //pick first displayable thumbnail
 top.state.image=0 //if there is at least one thumb, we won't crash, even if there is no appropriate image
 var i 
 for(i=0; i<top.pix[chapterNum].length; i++) {
  if(thumbnailTypeisSelectable(top.pix[chapterNum][i].thumbnailType)) { 
   top.state.image=i
   break
  }
 }
 top.updateFramesForNewMenu() 
 return true
}

function updatePictureFrame(frameIndex, chapter, image) {
 var aPix=top.pix[chapter][image]
 var shortCaption=aPix.shortCaption
 var caption=aPix.caption
 var comment=aPix.comment
 var people=aPix.people
 var name=aPix.name
 var big=aPix.big
 
 //set img width text
 var imgWidthTxt = ""
 if(g_smallImageWidth > 0) {
  //non-zero width means force the image to that width
  imgWidthTxt = " width="+g_smallImageWidth
 } 

 
 if("html"==showXtn(name)) {
  //html file, turn the frame over to it
  if("../"==name.substring(0,3)) {
   //file is up one level, leave off subdirectory name
   parent.frames[frameIndex].location.href=name.substring(3,name.length)
  } else {
   //file is in the normal place
   parent.frames[frameIndex].location.href=chapter+"/"+name
  }
 } else {
  //not an html file, treat as an image file
 
  writeFramePrefix(frameIndex, 0, 20, 20, g_pictureBgImage)


  frameWrite(frameIndex, "<table height='100%' width='100%'>" +
   "<tr><td align=center valign=middle>")

  if(shortCaption != "") {
   frameWrite(frameIndex,
    "<table border=0 cellspacing=0 cellpadding=0><tr><td"+imgWidthTxt+"><center>"+
    "<br><font class=caption><font color="+g_captionColor+"><b>"+shortCaption+"</b></font></font>"+
    "</center></td></tr></table><br>")
  }

  if(big) {
   //add link to show big picture in a different window
   frameWrite(frameIndex, "<a href='"+chapter+"/"+g_bigDir+"/"+name+"' target=bigpicture>")
  }

  frameWrite(frameIndex,"<img"+imgWidthTxt)
  frameWrite(frameIndex," border=0 src="+chapter+"/"+g_smallDir+"/"+name+">")

  if(big) {
   frameWrite(frameIndex, "</a>")
  }

  if(caption != "") {
   frameWrite(frameIndex,
    "<table border=0 cellspacing=0 cellpadding=0><tr><td"+imgWidthTxt+"><center>"+
    "<br><font class=caption><font color="+g_captionColor+">"+caption+"</font></font>"+
    "</center></td></tr></table>")
  }

  if(comment != "") {
   frameWrite(frameIndex,
    "<table border=0 cellspacing=0 cellpadding=0><tr><td"+imgWidthTxt+"><left>"+
    "<br><font class=scaption><font color="+g_captionColor+">"+comment+"</font></font>"+
    "</left></td></tr></table>")
  }
  
  if(people != "") {
   frameWrite(frameIndex,
    "<table border=0 cellspacing=0 cellpadding=0><tr><td"+imgWidthTxt+"><center>"+
    "<br><font class=scaption><font color="+g_captionColor+"><i>"+people+"</i></font></font>"+
    "</center></td></tr></table>")
  }
  frameWrite(frameIndex,"</td></tr></table>")
  writeFrameSuffix(frameIndex) 
 }
}



//
// cursors
//

//create a cursor position, via an <img>
function makeCursor(frameIndex, position, isCurrent, height, width) {
 frameWrite(frameIndex,	"<img border=0 name=cursor"+position+" src=")
 if(isCurrent) {
  frameWrite(frameIndex,top.g_cursorFile)
 } else {
  frameWrite(frameIndex, top.g_cursorClearFile)
 }
 frameWrite(frameIndex,	" width="+width+" height="+height+">")
}

//move a cursor in a particular frame type
function moveCursor(frameType, oldLoc, newLoc) {
 for(var i=0; i<top.frames.length; i++) {
  if(frameIsType(i,frameType)) {
   frameImages=top.frames[i].document.images
   frameImages["cursor"+oldLoc].src=top.g_cursorClearFile
   frameImages["cursor"+newLoc].src=top.g_cursorFile  
  }
 }
}


// functions to set and clear cursors, as for an onClick action
// these functions do not work properly under Netscape 4.7 
function setCursor(frameIndex, option) {
 if (!isUndefined(top.frames[frameIndex].document.images["cursor"+option])) {
  //this if clause will be false if there is no cursor for the hovered object
  top.frames[frameIndex].document.images["cursor"+option].src=top.g_cursorFile
 }
}

function clearCursor(frameIndex, option) {
 if (!isUndefined(top.frames[frameIndex].document.images["cursor"+option])) {
  //this if clause will be false if there is no cursor for the hovered object
  top.frames[frameIndex].document.images["cursor"+option].src=top.g_cursorClearFile
 }
}

function hoverCursor(frameIndex, option) {
 if (!isUndefined(top.frames[frameIndex].document.images["cursor"+option])) {
  //this if clause will be false if there is no cursor for the hovered object
  top.frames[frameIndex].document.images["cursor"+option].src=top.g_cursorHoverFile
 }
}


function redText(text) {
 return("<font color=red>"+text+"</font>")
}




//
// files
//

// show a file extnsion
function showXtn(fName) {
 var dotLoc = fName.lastIndexOf(".")
 if(dotLoc >= 0) {
  return(fName.substring(dotLoc+1, fName.length))
 } else {
  return("")
 }
}

function getThumbName(chapter, image) {
 if (""==top.pix[chapter][image].thumbName) {
  return(top.pix[chapter][image].name)
 } else
  return(top.pix[chapter][image].thumbName)
}


// show a file base name
function showBaseNm(fName) {
 var fPath
 //strip off extension
 var dotLoc = fName.lastIndexOf(".")
 if(dotLoc > 0) {
  fPath = fName.substring(0, dotLoc)
 } else {
  fPath = fName
 }

 //strip off path components
 var slashLoc = fPath.lastIndexOf("/")

 if(slashLoc > 0) {
  return(fPath.substring(slashLoc+1, fPath.length))
 } else {
  return(fPath)
 } 
}

//find one of the files corresponding to a particular state
function showFilePath(aState, picType) {
 if ((aState.chapter == top.g_weekPicPageChapter) && (aState.image == top.g_weekPicPageImage)) {
  //special case: weekpic page
  return g_picOfTheWeekChapter+'/'+picType+'/'+g_picOfTheWeekThumbName
 }
 return aState.chapter+'/'+picType+'/'+getThumbName(aState.chapter, aState.image)
}


//
// utility
//

// show a status message (stat may need to be encoded with encodeProtected()
function displayStatus(stat) {
  top.status=decodeProtected(stat)
}


// return a spacer (using a vacuous table)
function spacer(spc) {
 if (spc >= 0) {
  // a zero-height spacer is legal; a negative-height table should not be attempted
  return("<table><tr><td height="+spc+"></td></tr></table>")
 } else {
  return("")
 }
}


// encode single quotes so they will display
// (work-around for a pervasive browser bug)

// use to pass to an internal function via HTML
function encodeProtected(s) {
 return (s.split("'")).join("^~39;")
}

function decodeProtected(s) {
 return (s.split("^~39;")).join("'")
}


// use to pass to a javascript function
function encodeNormal(s) {
 return (s.split("'")).join("&#39;")
}

function decodeNormal(s) {
 return (s.split("&#39;")).join("'")
}


// object detection

function isObject(a) {
    return (a && typeof a == 'object') || isFunction(a);
}

function isUndefined(a) {
    return typeof a == 'undefined';
} 

function isNull(a) {
    return typeof a == 'object' && !a;
}

function isArray(a) {
    return isObject(a) && a.constructor == Array;
}

function isBoolean(a) {
    return typeof a == 'boolean';
}

function isEmpty(o) {
    var i, v;
    if (isObject(o)) {
        for (i in o) {
            v = o[i];
            if (isUndefined(v) && isFunction(v)) {
                return false;
            }
        }
    }
    return true;
}

//deep copy an object
function cloneOb(what) {
 for (i in what) {
  this[i] = what[i];
 }
}


// browsers

// determine browser type and version
function setBrowserVersion() {
 var agt=navigator.userAgent.toLowerCase();
 majorVer = parseInt(navigator.appVersion);
	
 is_ie     = ((agt.indexOf("msie") != -1) && (agt.indexOf("opera") == -1));
 is_firefox = agt.indexOf("firefox") != -1
 is_nav_esque = !is_ie

 is_nav4up = (is_nav_esque && (majorVer >= 4));
 is_ie4up  = (is_ie && (majorVer >= 4));
 is_modern = (is_ie4up || is_firefox)
 
 is_unsupported = !(true);
 return(!is_unsupported)
}

function reportBrowserVersion() {
 var agt=navigator.userAgent.toLowerCase();
 return ('majorVer '+majorVer+
        '\nis_ie '+is_ie+
        '\nis_firefox '+is_firefox+
        '\nis_nav_esque '+is_nav_esque+
        '\nis_modern '+is_modern+
        '\nis_nav4up '+is_nav4up+
        '\nis_ie4up '+is_ie4up+
        '\nis_unsupported '+is_unsupported+
 	'\n\nappVersion '+navigator.appVersion+'\nuserAgent '+agt);
}

function reportStatus() {
 alert(reportBrowserVersion());
}

// end //
