//
//  JSviewer - Dynamic HTML JavaScript image viewer
//  jsviewer.js
//  version 1.1
// 
//  Copyright (c) 2002-2003 Seann Herdejurgen (seann@herdejurgen.com)
//  All rights reserved.
//
//  Redistribution and use in source and binary forms, with or without
//  modification, are permitted provided that the following conditions
//  are met:
//
//  1. Redistributions of source code must retain the above copyright
//     notice, this list of conditions and the following disclaimer.
//  2. Redistributions in binary form must reproduce the above copyright
//     notice, this list of conditions and the following disclaimer in the
//     documentation and/or other materials provided with the distribution.
//  3. The name of the author may not be used to endorse or promote products
//     derived from this software without specific prior written permission.
//
//  THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR
//  IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
//  OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
//  IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT,
//  INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING,
//  BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
//  LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED
//  AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY,
//  OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
//  OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
//  SUCH DAMAGE.
//
//  JSviewer is distributed as freeware for non-commercial use.
//
//  Documentation and updates available on-line at http://www.jsviewer.com/
//

//
// JavaScript cookie functions
//
function getCookie(name) {
   var cookies=document.cookie.split('; ')
   if (document.cookie=='') cookies.length=0
   for (var i=0;i<cookies.length;i++)
      if (cookies[i].indexOf(name+'=')==0) return unescape(cookies[i].split('=')[1])
   return ''
}

function setCookie(name,value) { document.cookie=name+'='+value+'; path=/' }

function initCookie(name,value) { if (getCookie(name)=='') setCookie(name,value) }

//
// Set default JSviewer preferences
//
// It is recommended that you set your own defaults in the
// script that calls JSviewer rather than changing them here.
//
// You can set your own defaults in HTML like this:
//
//    <script>
//    document.cookie='maxpect=1; path=/'
//    document.cookie='timer=5000; path=/'
//    </script>
//
function setDefaults() {
   initCookie('advanced',0)
   initCookie('cache',1)
   initCookie('colorbar',1)
   initCookie('controls',1)
   initCookie('maxpect',0)
   initCookie('slideshow','Stop')
   initCookie('thumbdir','.thumbs')
   initCookie('thumbnails',0)
   initCookie('thumbsize',75)
   initCookie('timer',8000)
   initCookie('transitions',1)
}

//
// Declare JSviewer global variables
//
var Images=new Array()
var History=new Array(100)
var form,index,lookahead,pic,pics,out,outerframe,recheck,timer
var X,Y,H,W,width,height,topOffset,bottomOffset
var dragging,dragX,dragY,dragZ
var memory=0
var GRADIENT=16
var R=new Array(0,  0,  0, 11,128,255,255,128, 64,128,255,255,255,128, 11,  0)
var G=new Array(0, 11,128,255,255,255,255,128, 11,  0,  0, 11, 64, 64, 64,  0)
var B=new Array(0,128,255,128, 11, 11,255,128, 64,128,255,128, 11,  0,  0,  0)

//
// Construct JSImage prototype
//
function JSImage() {
   this.image=new Image()
   this.error=0
   this.finished=0
   this.left=0
   this.top=0
   this.zoom=0
}

//
// Browser specific DHTML functions
//
function getDoc(name) {
   if (document.layers) return eval('document.'+name+'.document')
   if (document.all) return eval('document.all.'+name+'.document')
   return document.getElementById(name).ownerDocument
}

function divWidth(name) {
   if (document.layers) return eval('document.'+name+'.document.width')
   if (document.all) return eval('document.all.'+name+'.offsetWidth')
   return document.getElementById(name).offsetWidth
}

function divHeight(name) {
   if (document.layers) return eval('document.'+name+'.document.height')
   if (document.all) return eval('document.all.'+name+'.offsetHeight')
   return document.getElementById(name).offsetHeight
}

function getLayer(name) {
   if (document.layers) return eval('document.'+name)
   if (document.all) return eval('document.all.'+name+'.style')
   return document.getElementById(name).style
}

function getX(layer) {
   if (document.layers) return layer.x
   if (document.all) return layer.pixelLeft
   return parseInt(layer.left)
}

function getY(layer) {
   if (document.layers) return layer.y
   if (document.all) return layer.pixelTop
   return parseInt(layer.top)
}

function setClip(layer,x,y,t,r,b,l) {
   layer=getLayer(layer)
   if (document.layers) {
      layer.clip.top=t
      layer.clip.right=r
      layer.clip.bottom=b
      layer.clip.left=l
      layer.moveTo(x,y)
   } else if (document.all) {
      layer.clip='rect('+t+'px '+r+'px '+b+'px '+l+'px)'
      layer.pixelLeft=x
      layer.pixelTop=y
      layer.overflow='hidden'
   } else {
      layer.left=x
      layer.top=y
      layer.clip='rect('+t+' '+r+' '+b+' '+l+')'
   }
}

function output(layer,html) {
   if (document.layers) {
      var doc=getDoc(layer)
      doc.open()
      doc.writeln(html)
      doc.close()
   } else if (document.all) {
      layer=eval(layer)
      layer.innerHTML=html
   } else document.getElementById(layer).innerHTML=html
}

function setXY(layer,x,y) {
   layer=getLayer(layer)
   if (document.layers) {
      layer.moveTo(x,y)
   } else if (document.all) {
      layer.pixelLeft=x
      layer.pixelTop=y
   } else {
      layer.left=x
      layer.top=y
   }
}

function center(layer,y) { setXY(layer,Math.round((width-divWidth(layer))/2),y) }

function setCursor(curtype) { if (document.all) document.body.style.cursor=curtype }

function setVisibility(layer,vis) {
   layer=getLayer(layer)
   layer.visibility=(vis?'visible':'hidden')
}

//
// JSviewer library functions
//
function randomPick() {
   return randomPick.arguments[Math.floor(Math.random()*randomPick.arguments.length)]
}

function pick(n,c) {
   var i=n
   if (c>1) while (i==n) i=Math.floor(n+Math.random()*c)%c
   return i
}

function isImage(i) {
   var name=form.pictures.options[i].value.split(';')[0]
   name=name.toLowerCase()
   var dot=name.lastIndexOf('.')
   var imagetypes='.gif.jpg.jpeg.png'
   return imagetypes.indexOf(name.substr(dot))!=-1?1:0
}

function save(image) {
   index=(index+1)%History.length
   History[index]=image
   History[(index+1)%History.length]=-1
   return image
}

function savePic() { setCookie('image',pic) }

function redraw() {
   savePic()
   window.location.reload()
   return false
}

function inheritColors(source) {
//rkh   document.bgColor=source.bgColor
   document.fgColor=source.fgColor
   document.linkColor=source.linkColor
   document.alinkColor=source.alinkColor
   document.vlinkColor=source.vlinkColor
}

function getOffsets() {
   var a=divHeight('navbar')
   var b=divHeight('advbar')-10
   var c=divHeight('colorbar')
   if (getCookie('controls')==0) topOffset=0
   else if (getCookie('advanced')==0) topOffset=a
   else if (getCookie('colorbar')==0) topOffset=a+b
   else topOffset=a+b+c
}

function font(s) { return '<font face=Arial,Helvetica>'+s+'</font>' }

function vstat(message) {
   return 'onmouseover="window.status='+message+'; return true" onmouseout="window.status=\'\'; return true"'
}

function stat(message) { return vstat("'"+message+"'") }

function link(func,extra,text) {
   return '<a href="Javascript:void '+func+'" style=text-decoration:none '+extra+'>'+text+'</a> '
}

function button(value,func,extra) {
   return '<input type=button value="'+value+'" onclick='+func+' '+extra+'> '
}

function checkbox(cookie,func,extra,text) {
   return '<input type=checkbox '+(getCookie(cookie)==1?'checked':'')+' onclick='+func+' '+extra+'> '+text+' '
}

function notify(message,w,h) {
   setClip('picture',0,0,0,width,height,0)
   output('picture',font(message))
   center('picture',Math.round((height-topOffset-bottomOffset-divHeight('picture'))/2)+topOffset)
}

//
// Image caching functions
//
function preFetch(i) {
   if (isImage(i) && Images[i].image.src=='') {
      Images[i].image.onload=function() { postFetch(i) }
      Images[i].image.onabort=function() { noFile(i) }
      Images[i].image.onerror=function() { noFile(i) }
      Images[i].image.src=form.pictures.options[i].value.split(';')[0]
   }
}

function noFile(i) { Images[i].error=1; postFetch(i) }

function postFetch(i) {
   // Track browser cache memory usage
   if (isImage(i) && !Images[i].error) {
      if (Images[i].image.fileSize) memory+=Images[i].image.fileSize*1
      else memory+=Math.round(Images[i].image.width*Images[i].image.height/8)
   }
   Images[i].finished=1
   // Always pre-fetch next image if not in cache
   if (lookahead>=0 && isImage(lookahead) && Images[lookahead].image.src=='') return preFetch(lookahead)
   // Only pre-fetch first 64 MB of images
   if (getCookie('cache')==1 && memory<67108864) for (i=(pic+1)%pics; i!=pic; i=(i+1)%pics) {
      if (isImage(i) && Images[i].image.src=='') {
         // Use window.setTimeout to prevent stack overflow
         window.setTimeout('preFetch('+i+')',50); 
         return
      }
   }
}

function gofullScreen() {
   setCookie('fullscreen',1)
   if (document.all) {
      // Stop slide show
      window.clearTimeout(timer)
      savePic()
      window.open(document.URL,'JSviewer','fullscreen=1,toolbar=0,location=0,directories=0,status=0,menubar=0,scrollbars=0,resizable=0')
   } else {
      window.resizeTo(screen.availWidth,screen.availHeight); window.moveTo(0,0)
   }
}

function exitfullScreen() {
   setCookie('fullscreen',0)
   if (parent) parent.window.close(); else window.close()
}

function maxZoom() {
   var x,y,z
   x=width/Images[pic].image.width
   y=(height-topOffset-bottomOffset)/Images[pic].image.height
   // Scale using smaller zoom value
   z=(x<y?x:y)
   // Don't enlarge small pictures unless maxpect is on
   if (getCookie('maxpect')==0 && z>1) z=1
   Images[pic].zoom=z
}

function IEtransition(d) {
   var trans=getCookie('transitiontype')
   d='duration='+d
   if (trans=='') switch (Math.floor(Math.random()*17)) {
      case 0: trans='Barn('+d+',motion='+randomPick('in','out')+',orientation=',randomPick('horizontal','vertical')+')'
              break;
      case 1: trans='Blinds('+d+',bands='+randomPick(2,4,6,8)+',direction='+randomPick('up','down','right','left')+')'
              break;
      case 2: trans='CheckerBoard('+d+',squaresX='+randomPick(2,4,8,12)+',squaresY='+randomPick(2,4,8,12)+',direction='+randomPick('up','down','right','left')+')'
              break;
      case 3: trans='Fade('+d+',overlap='+randomPick(0.25,0.5,0.75,1)+')'
              break;
      case 4: trans='GradientWipe('+d+',gradientSize='+randomPick(0,0.1,0.3,0.5,0.7,0.9,1)+',wipeStyle='+randomPick(0,1)+',motion='+randomPick('forward','reverse')+')'
              break;
      case 5: trans='Inset('+d+')'
              break;
      case 6: trans='Iris('+d+',irisStyle='+randomPick('DIAMOND','CIRCLE','CROSS','PLUS','SQUARE','STAR')+',motion='+randomPick('in','out')+')'
              break;
      case 7: trans='Pixelate('+d+',maxSquare='+randomPick(5,10,20,30,40,50)+')'
              break;
      case 8: trans='RadialWipe('+d+',wipeStyle='+randomPick('CLOCK','WEDGE','RADIAL')+')'
              break;
      case 9: trans='RandomBars('+d+',orientation='+randomPick('horizontal','vertical')+')'
              break;
      case 10: trans='RandomDissolve('+d+')'
              break;
      case 11: trans='Slide('+d+',pushStyle='+randomPick('HIDE','PUSH','SWAP')+',bands='+randomPick(1,2,3,4,5,6,7)+')'
              break;
      case 12: trans='Spiral('+d+',gridSizeX='+randomPick(8,16,32,64)+',gridSizeY='+randomPick(8,16,32,64)+')'
              break;
      case 13: trans='Stretch('+d+',stretchStyle='+randomPick('HIDE','PUSH','SPIN')+')'
              break;
      case 14: trans='Strips('+d+',motion='+randomPick('leftdown','leftup','rightdown','rightup')+')'
              break;
      case 15: trans='Wheel('+d+',spokes='+randomPick(2,4,10,16,20)+')'
              break;
      case 16: trans='Zigzag('+d+',gridSizeX='+randomPick(8,16,32,64)+',gridSizeY='+randomPick(8,16,32,64)+')'
              break;
   }
   document.body.style.filter='progid:DXImageTransform.Microsoft.'+trans
   if (navigator.appVersion.indexOf('MSIE 5.0')!=-1) document.body.style.filter='revealTrans('+d+',transition='+Math.floor(Math.random()*23)+')'
   document.body.filters[0].Apply()
}

function renderCaption() {
   // Draw image caption
   var comment=form.pictures.options[pic].value.split(';')[1]
   if (!comment) {
      setVisibility('caption',0)
      bottomOffset=0
   } else {
      output('caption',font(comment))
      setVisibility('caption',1)
      bottomOffset=divHeight('caption')+24
      center('caption',height-bottomOffset+12)
   }
}

function renderImage() {
   var option=form.pictures.options[pic]
   W=Math.floor(Images[pic].image.width*Images[pic].zoom)
   H=Math.floor(Images[pic].image.height*Images[pic].zoom)
   if (W>width) W=width
   if (H>height-topOffset-bottomOffset) H=height-topOffset-bottomOffset
   if (Images[pic].top>Math.floor(Images[pic].image.height-H/Images[pic].zoom))
      Images[pic].top=Math.floor(Images[pic].image.height-H/Images[pic].zoom)
   if (Images[pic].left>Math.floor(Images[pic].image.width-W/Images[pic].zoom))
      Images[pic].left=Math.floor(Images[pic].image.width-W/Images[pic].zoom)
   if (Images[pic].top<0) Images[pic].top=0
   if (Images[pic].left<0) Images[pic].left=0
   var x=Images[pic].left
   var y=Images[pic].top
   var z=Images[pic].zoom
   var t=Math.floor(y*z)
   var r=Math.floor(x*z+W)
   var b=Math.floor(y*z+H)
   var l=Math.floor(x*z)
   X=Math.floor(width/2-W/2-l)
   Y=Math.floor((height-topOffset-bottomOffset)/2-H/2-t)
   output('picture','<img border=0 src="'+option.value.split(';')[0]+'" alt="'+option.text+'" width='+Math.floor(Images[pic].image.width*z)+' height='+Math.floor(Images[pic].image.height*z)+' '+(document.all?(getCookie('nozoom')==''?'onmousedown=startDrag() onmousemove=drag() onmouseup=stopDrag() onmouseout=stopDrag()':'onclick=nextImage()'):'')+'>')
   if (Y+t<topOffset) Y=topOffset-t
   setClip('picture',X,Y,t,r,b,l)
   window.status=option.text
}

function drawScreen() {
   renderCaption()
   if (isImage(pic)) {
      if (Images[pic].error) {
         notify('Unable to load '+Images[pic].image.src)
      } else if (Images[pic].image.complete) {
         if (!Images[pic].zoom || getCookie('maxpect')==1) maxZoom()
         renderImage()
      }
   } else {
      var url=form.pictures.options[pic].value.split(';')[0]
      // Display web page instead of image
      if (document.all) {
         W=Math.floor(width*0.90); H=height-topOffset-bottomOffset
         X=Math.floor((width-W)/2); Y=topOffset
         setClip('picture',X,Y,0,W,H,0)
         output('picture','<iframe src='+url+' width='+W+' height='+H+' scrolling=auto></iframe>')
      } else notify('Unable to display '+url+' in this browser')
   }
}

function displayImage(i) {
   if (document.all) document.body.scroll='no'
   // Make sure image is cached before displaying it
   if (isImage(i) && !Images[i].finished) {
      if (Images[i].image.src=='') preFetch(i)
      setCursor('Wait')
      recheck=window.setTimeout('displayImage('+i+')',125)
      return
   }
   setCursor('Default')
   setCookie('thumbnails',0)

   // Setup IE transition
   if (document.all && getCookie('transitions')==1) IEtransition(getCookie('timer')/5000)

   // Track current picture on screen menu and in global variable
   pic=form.pictures.selectedIndex=i

   // Prefetch next image if current image is cached
   if (Images[pic].image.complete && lookahead>=0) preFetch(lookahead)

   // Queue up next image for slide show
   if (getCookie('slideshow')=='Stop') {
      window.clearTimeout(timer)
      timer=window.setTimeout('nextSlide()',getCookie('timer'))
   }

   // Draw image & caption on screen
   drawScreen()

   // Play IE transition
   if (document.all && getCookie('transitions')==1) document.body.filters[0].Play()
}

function displayThumbs() {
   var THUMBDIR=getCookie('thumbdir')
   var THUMBSIZE=getCookie('thumbsize')*1
   var bufspace=10
   var across=Math.floor(width/(THUMBSIZE+2*bufspace))
   var down=Math.ceil(pics/across)+1
   setCursor('Default')
   setVisibility('caption',0)
   setClip('picture',0,topOffset,0,width,(THUMBSIZE+2*bufspace)*down,0)
   if (document.all && height<(THUMBSIZE+2*bufspace)*down) document.body.scroll='yes'
   if (pics) {
      var out=''
      for (var i=0; i<pics; i++) {
         var option=form.pictures.options[i]
         var thumb=option.value.split(';')[0]
         var desc=option.value.split(';')[1]
         var comment=option.text
         while (comment.indexOf("'")!=-1) comment=comment.replace("'","")
         out+='<a href="" onclick="window.displayImage(window.save('+i+')); return false" '+stat(comment)+'>'
         if (isImage(i) && (getCookie('pseudothumbs')==1 || thumb.indexOf('http://')==0)) {
            // Create psuedo thumbnails
            if (Images[i].image.complete) {
               var x,y,z
               x=Images[i].image.width/THUMBSIZE
               y=Images[i].image.height/THUMBSIZE
               z=(x>y?x:y)
               x=Math.round(Images[i].image.width/z)
               y=Math.round(Images[i].image.height/z)
               out+='<img border=0 hspace='+bufspace+' vspace='+bufspace+' src="'+thumb+'" width='+x+' height='+y+' alt="'+option.text+'">'
            } else out+=font(comment?comment:path[p])
         } else if (isImage(i) && !Images[i].error) {
            var path=thumb.split('/')
            var p=path.length
            path[p]=path[p-1]; path[p-1]=THUMBDIR
            thumb=path.join('/')
            out+='<img border=0 hspace='+bufspace+' vspace='+bufspace+' src="'+thumb+'" alt="'+option.text+'">'
         } else out+=font(comment?comment:path[p])
         out+='</a> '
      }
      output('picture',out)
   } else notify('No thumbnails available')
}

function display(i) {
   // Display image or thumbnails
   if (getCookie('thumbnails')==1) displayThumbs(); else displayImage(i)
}

//
// Image navigation
//
function firstImage() { displayImage(save(0)) }

function previousImage() {
   var image
   if (getCookie('entropy')==1) {
      index=(index+History.length-1)%History.length
      if (History[index]>=0) {
         image=History[index]
      } else {
         image=pick(pic,pics)
         History[index]=image
         History[(index+History.length-1)%History.length]=-1
      }
   } else image=(pic+pics-1)%pics
   displayImage(image)
}

function nextImage() {
   var image
   if (getCookie('entropy')==1) {
      index=(index+1)%History.length
      if (History[index]>=0) {
         image=History[index]
      } else {
         image=(lookahead<0?pick(pic,pics):lookahead)
         lookahead=pick(image,pics)
         History[index]=image
         History[(index+1)%History.length]=-1
      }
   } else {
      image=(pic+1)%pics
      lookahead=(image+1)%pics
   }
   displayImage(image)
}

function lastImage() { displayImage(save(pics-1)) }

//
// Slideshow functions
//
function nextSlide() {
   if (getCookie('slideshow')=='Stop') {
      if (getCookie('thumbnails')==0 && (!isImage(pic) || Images[pic].finished)) nextImage()
   } else form.slider.value='Start'
}

function slideshow(button) {
   if (button.value=='Start') {
      button.value='Stop'
      setCookie('slideshow','Stop')
      nextSlide()
   } else {
      window.clearTimeout(recheck)
      window.clearTimeout(timer)
      button.value='Start'
      setCookie('slideshow','Start')
   }
}

function faster() {
   if (getCookie('timer')>125) {
      setCookie('timer',Math.round(getCookie('timer')/2))
      if (getCookie('slideshow')=='Stop') {
         window.clearTimeout(timer)
         nextSlide()
      }
   } else alert("I can't push her any faster captain!")
}

function slower() { setCookie('timer',getCookie('timer')*2) }

//
// Toggle functions
//
function redisplay() {
   if (getCookie('thumbnails')==0) {
      if (Images[pic].zoom<1 || getCookie('maxpect')==1) maxZoom()
      drawScreen()
   } else displayThumbs()
}

function toggleVisibility() {
   setVisibility('advbar',getCookie('controls')==1 && getCookie('advanced')==1)
   setVisibility('colorbar',getCookie('controls')==1 && getCookie('advanced')==1 && getCookie('colorbar')==1)
   setVisibility('navbar',getCookie('controls')==1)
   setVisibility('noframes',outerframe && getCookie('controls')==1 && getCookie('fullscreen')!=1)
   getOffsets()
}

function toggleThumbs() {
   setCookie('thumbnails',1-getCookie('thumbnails'))
   display(pic)
}

function toggleControls() {
   setCookie('controls',1-getCookie('controls'))
   toggleVisibility(); redisplay()
   return false
}

function toggleAdvanced() {
   setCookie('advanced',(1-getCookie('advanced')))
   toggleVisibility(); redisplay()
   return false
}

function toggleTransitions(box) { setCookie('transitions',(box.checked?1:0)) }

function toggleMaxpect(box) {
   setCookie('maxpect',(box.checked?1:0))
   if (getCookie('thumbnails')==0 && getCookie('maxpect')==1) {
      getOffsets()
      maxZoom()
      drawScreen()
   }
}

function toggleRandom(box) {
   setCookie('entropy',(box.checked?1:0))
   lookahead=-1
}

function toggleCache(box) {
   setCookie('cache',(box.checked?1:0))
   if (box.checked) preFetch(pic)
}

//
// Background color functions
//
function color(a,b,c) {
   if (a<b) return Math.round(a+(b-a)*c/GRADIENT)
   return Math.round(b+(a-b)*(GRADIENT-c)/GRADIENT)
}

function hex(n) {
   var digits=new Array('0','1','2','3','4','5','6','7','8','9','A','B','C','D','E','F')
   return digits[Math.floor(n/16)]+digits[n%16]
}

function getColor(n,c) {
   var r,g,b
   var i=Math.floor(n/GRADIENT)
   n%=GRADIENT
   r=color(R[i],R[i+1],n)
   g=color(G[i],G[i+1],n)
   b=color(B[i],B[i+1],n)
   if (c) return '#'+hex(255-r)+hex(255-g)+hex(255-b)
   return '#'+hex(r)+hex(g)+hex(b)
}

//
// Drag & drop functions
//
function getx(event) { return document.all?window.event.clientX:event.pageX }

function gety(event) { return document.all?window.event.clientY:event.pageY }

function colorClick(event) {
   var x=getx(event)
   var y=gety(event)
   var l=getX(getLayer('colorbar'))
   var t=getY(getLayer('colorbar'))
   var XC=x-Math.round((width-(R.length-1)*GRADIENT)/2)
//rkh   document.bgColor=getColor(XC,0)
   document.fgColor=getColor(XC,1)
   if (outerframe) {
      outerframe.bgColor=document.bgColor
      outerframe.fgColor=document.fgColor
   }
}

function startDrag(event) {
   var x=getx(event)
   var y=gety(event)
   if (getCookie('thumbnails')==0) {
      dragging=1
      dragX=x+Math.round(Images[pic].left*Images[pic].zoom)
      dragY=y+Math.round(Images[pic].top*Images[pic].zoom)-topOffset
      if (document.all) {
         if (window.event.button==1) dragZ=0.2
         if (window.event.button==2) dragZ=-0.2
      } else {
         if (event.which==1) dragZ=0.2
         if (event.which==3) dragZ=-0.2
      }
      if (document.all) window.event.cancelBubble=true
      return false
   }
   if (document.routeEvent) document.routeEvent(event)
   return true
}

function drag(event) {
   if (dragging) {
      var x=getx(event)
      var y=gety(event)
      var l=Images[pic].left
      var t=Images[pic].top
      if (dragX!=x+Math.round(Images[pic].left*Images[pic].zoom) &&
          dragY!=y+Math.round(Images[pic].top*Images[pic].zoom)-topOffset) dragZ=0
      Images[pic].left+=Math.round((dragX+X-x)/Images[pic].zoom)
      Images[pic].top+=Math.round((dragY+Y-y)/Images[pic].zoom)
      if (Images[pic].top>(Images[pic].image.height-H/Images[pic].zoom))
         Images[pic].top=Math.round(Images[pic].image.height-H/Images[pic].zoom)
      if (Images[pic].left>(Images[pic].image.width-W/Images[pic].zoom))
         Images[pic].left=Math.round(Images[pic].image.width-W/Images[pic].zoom)
      if (Images[pic].top<0) Images[pic].top=0
      if (Images[pic].left<0) Images[pic].left=0
      if (Images[pic].left!=l || Images[pic].top!=t) renderImage()
      if (document.all) window.event.cancelBubble=true
      return false
   }
   if (document.routeEvent) document.routeEvent(event)
   return true
}

function stopDrag(event) {
   var x=getx(event)
   var y=gety(event)
   if (dragZ!=0 && getCookie('thumbnails')==0) {
      dragZ+=Images[pic].zoom
      if (dragZ<0.1 || dragZ>5.0) {
         maxZoom()
         Images[pic].top=0
         Images[pic].left=0
      } else {
         Images[pic].top=Math.round((y-Y)/Images[pic].zoom-(y-Y-Images[pic].top*Images[pic].zoom)/dragZ)
         Images[pic].left=Math.round((x-X)/Images[pic].zoom-(x-X-Images[pic].left*Images[pic].zoom)/dragZ)
         Images[pic].zoom=dragZ
      }
      renderImage()
   }
   dragging=dragZ=0
   if (document.all) window.event.cancelBubble=true
   return false
}

//
// Mozilla wrappers for drag & drop
//
function mozimageClick(event) {
   var x=getx(event)
   var y=gety(event)
   var l=X+Math.floor(Images[pic].left*Images[pic].zoom)
   var t=Y+Math.floor(Images[pic].top*Images[pic].zoom)
   return x>l && x<l+W && y>t && y<t+H
}

function mozcolorClick(event) {
   var x=getx(event)
   var y=gety(event)
   var l=getX(getLayer('colorbar'))
   var t=getY(getLayer('colorbar'))
   return y>t && y<=t+divHeight('colorbar') && x>l && x<=l+divWidth('colorbar')
}

function mozstartDrag(event) {
   if (mozcolorClick(event) && getCookie('advanced')==1 && getCookie('colorbar')==1) {
      colorClick(event)
      return false
   }
   if (getCookie('thumbnails')==0 && mozimageClick(event) && isImage(pic) && !Images[pic].error) {
      if (getCookie('nozoom')=='') return startDrag(event)
      nextImage()
      return false
   }
   document.routeEvent(event)
   return true
}

function mozdrag(event) {
   if (getCookie('thumbnails')==0 && mozimageClick(event) && isImage(pic) && !Images[pic].error) return drag(event)
   dragging=0
   document.routeEvent(event)
   return true
}

function mozstopDrag(event) {
   if (getCookie('thumbnails')==0 && mozimageClick(event) && isImage(pic) && !Images[pic].error) return stopDrag(event)
   dragging=dragZ=0
   document.routeEvent(event)
   return true
}

//
// JSviewer main program
//
function init() {
   // Get screen dimensions
   if (document.all) {
      document.body.scroll='no'
      width=document.body.clientWidth
      height=document.body.clientHeight
   } else {
      width=window.innerWidth
      height=window.innerHeight
   } 
   dragZ=topOffset=bottomOffset=0

   // Set JSviewer default cookies
   setDefaults()

   // Inherit colors from environment
   if (getCookie('fullscreen')==1 && parent.opener && parent.opener.gofullScreen)
      inheritColors(parent.opener.document)
   else if (parent && parent.frames[0])
      inheritColors(outerframe=parent.frames[0].document)

   // Initialize navigation controls
   var datasrc=getDoc('data')
   datasrc=datasrc.forms[0].pictures
   if (datasrc) {
      var thumbs=link('toggleThumbs(window.pic)',vstat('getCookie(\'thumbnails\')==1?\'Show full size images\':\'Show thumbnail images\''),'thumbs')
      var first=button(' |&lt; ','firstImage()',stat('First image'))
      var previous=button(' &lt; ','previousImage()',stat('Previous image'))
      var menu='<select name=pictures onchange=displayImage(save(this.selectedIndex)) '+stat('Select an image to display')+'> '
      
      for (var i=0; i<datasrc.options.length; i++) {
         Images[i]=new JSImage()
         menu+='<option value="'+datasrc.options[i].value+'"> '+(i+1)+'. '+datasrc.options[i].text
      }
      menu+='</select> '
      var next=button(' &gt; ','nextImage()',stat('Next image'))
      var last=button(' &gt;| ','lastImage()',stat('Last image'))
      var slider=button(getCookie('slideshow'),'slideshow(this)','name=slider '+vstat('getCookie(\'slideshow\')+\' slideshow\''))
      var advanced=link('toggleAdvanced()',vstat('(getCookie(\'advanced\')==1?\'Hide\':\'Show\')+\' advanced controls\''),'advanced')
      switch (getCookie('controlstyle')) {
         case 'rkh': out=menu+first+previous+next+last+slider
                 break;
         default: out=thumbs+previous+menu+next+slider+advanced
      }
      output('navbar','<form name=navform>'+font(out)+'</form>')
      center('navbar',5)
   }

   // Initialize advanced controls
   out=link('slower()',stat('Display images slower'),'-')+' speed '+
       link('faster()',stat('Display images faster'),'+')
   if (getCookie('fullscreen')!=1) out+=link('gofullScreen()',stat('Maximize window size'),'full screen') // rkh
   if (document.all) out+=checkbox('transitions','toggleTransitions(this)',vstat('(this.checked?\'Disable\':\'Enable\')+\' image transitions\''),'transitions')
   out+=checkbox('maxpect','toggleMaxpect(this)',stat('Maximize image size on screen'),'max size')
   out+=checkbox('entropy','toggleRandom(this)',stat('Randomize images'),'random')
   out+=checkbox('cache','toggleCache(this)',stat('Pre-load images in the background'),'prefetch')
   output('advbar','<form>'+font(out)+'</form>')
   center('advbar',divHeight('navbar')-5)
   output('colorbar','<img src=spectrum.png width='+((R.length-1)*GRADIENT)+' alt="Choose a background color"'+(document.all?' onclick=colorClick()':'')+'>')
   center('colorbar',divHeight('navbar')+divHeight('advbar')-15)

   // Initialize misc controls
   output('closer',font(link('exitfullScreen()','','X')))
   setXY('closer',width-20,0)
   setVisibility('closer',getCookie('fullscreen')==1)
   output('controls',font(link('toggleControls()','','.')))
   setXY('controls',width-10,height-24)
   setVisibility('controls',1)
   output('noframes',font('<a target=_top href="'+document.URL+'" style=text-decoration:none><small>full screen</small></a>'))
   setXY('noframes',5,5)

   // Initialize picture frame
   notify('Loading images...')
   setVisibility('picture',1)

   // Set global to point to navform
   var doc=getDoc('navbar')
   form=doc.forms['navform']

   // Reset picture to last viewed picture
   pics=form.pictures.length
   pic=getCookie('image'); setCookie('image','')
   if (pic=='' || pic>=pics) pic=getCookie('entropy')==1?pick(-1,pics):0
   pic*=1; index=0; History[index]=form.pictures.selectedIndex=pic

   // Initialize lookahead
   lookahead=getCookie('entropy')==1?pick(pic,pics):(pic+1)%pics

   // Start pre-fetching images in the background
   preFetch(pic)

   // Setup hooks to drag, drop & zoom image if enabled
   if (document.captureEvents) {
      document.captureEvents(Event.MOUSEDOWN|Event.MOUSEMOVE|Event.MOUSEUP|Event.MOUSEOUT)
      document.onmousedown=mozstartDrag
      document.onmousemove=mozdrag
      document.onmouseup=mozstopDrag
      document.onmouseout=mozstopDrag
   }

   // Capture resize events
   if (window.captureEvents) window.captureEvents(Event.RESIZE)
   window.onresize=redraw

   // Display image or thumbnails
   toggleVisibility()
   display(pic)
}

// Create layer elements
var Layers=new Array('picture','caption','navbar','advbar','colorbar','closer','noframes','controls')
for (var i=0,out='';i<Layers.length;i++) out+='<div id='+Layers[i]+' style="position:absolute; visibility:hidden"></div>'
document.writeln(out)

window.onload=init
