/* JSGal v0.83: Copyright (c) 2004-2009 by Andreas S. Krebs (jsgal@sberk.net) */
// below are the gallery parameters (may be changed in the xml file)
var imgrows=3;
var imgcols=3;
var pagesinrow=20;
var thumbzoom=1.0;
var thumbheight_nozoom=150;
var thumbwidth_nozoom=null;
var thumbheight=150;	// if you change this you probably also want to change the height of the thumbcell in the styles!!
var thumbwidth=null;	// use null to resize keeping aspect ratio
var thumbcellw=212;
var thumbcellh=174;
var imagezoom=1.0;
var imageheight_nozoom=600;
var imagewidth_nozoom=null;
var previewScale=0.7;
var ilnzoom=1.0;
var imageheight=600;
var imagewidth=null;	// use null to resize keeping aspect ratio
var imagetarget=null;	// the target browser window name for displaying original image or null for current window
var imagecellw=840;
var imgnumdigits=4;

var title=null;
var files=new Array();	// the array with the image names
var images=new Array();	// the array for the images
var thumbs=new Array(); // the array for the thumbs
var titles=new Array(); // the array for the image titles
var descriptions=new Array();	// the array with the image descriptions
var scales=new Array();	// the array with the image scaling modes

var defGal=0;			// the default gallery
var defImg=0;			// the default image
var wrapGals=1;			// navigate between galleries when reaching start/end of current gallery
var horizGalNav=0;		// use horizontal gallery navigation (default vertical)
var galsInRow=5;		// the number of galleries in horiz navigation
var collapseGals=0;		// collapse or expand galleries navigation
var galleries=new Array();	// the array for the gallery xml file
var galtitles=new Array();	// the array with the gallery titles
var curMode=new Array();	// the array with the current mode for the galeries
var curImgs=new Array();	// the array with the current image for the galeries
var curThumbZooms=new Array();	// the array with the current thumb zooms for the galeries
var curImgZooms=new Array();	// the array with the current image zooms for the galeries
var curPreviewZooms=new Array();	// the array with the current preview zooms for the galeries
var imgPosData=new Array();	// the array with the image elements (for mouse over)

var ilnheight;
var ilnwidth;
var imgspage;
var numpages;
var numpagerows;
var slideTimeout;

// here are all the texts we use
var TXT_PREVIOUSIMG="<";
var TXT_NEXTIMG=">";
var TXT_PREVIOUSPAGE="<<";
var TXT_NEXTPAGE=">>";
var TXT_SHOWALL="Show All";
var TXT_ORIGSIZE="Original size...";
var TXT_EXPANDGALS="<>";
var TXT_COLLAPSEGALS="><";

var TXT_MSG_LOADGALS="loading galleries ...";
var TXT_ERR_LOADGALS="error loading gallery: ";
var TXT_MSG_LOADGAL="loading gallery ...";
var TXT_ERR_LOADGAL="error loading gallery: ";

// here are the tooltip
var TT_PREVIOUSIMG="Display Previous Image";
var TT_NEXTIMG="Display Next Image";
var TT_PREVIOUSPAGE="Goto Previous Page";
var TT_NEXTPAGE="Goto Next Page";
var TT_SHOWALL="Show All Images On A Single Page";
var TT_SHOWGALLERY="Switch To Gallery: ";
var TT_SHOWPAGE="Goto Page: ";
var TT_SHOWIMAGE="Display Image: ";
var TT_EXPANDGALS="Expand Galleries";
var TT_COLLAPSEGALS="Collapse Galleries";

// the IDs of the main elements - will be changed depending on vert or horiz galleries nav
var GALS_ID="gals";
var NAV_ID="nav";
var MAIN_ID="main";
var PAD_ID="padtab";	// ID of element to do vertical padding on
var ILNDIV_ID="inlinediv";

// here are the display modes
var MODE_PAGE		=1;
var MODE_SHOWALL	=2;
var MODE_IMAGE		=3;

// here are the variables we store the current values in
var current_mode	=-1;
var current_page	=-1;
var current_image	=-1;
var current_gallery	=-1;

// since changing the source of an image doesn't work for opera we need a work around
var browserIsOpera=(navigator.userAgent.indexOf("Opera")>=0);
var browserIsIE=((navigator.userAgent.indexOf("MSIE")>=0) && !browserIsOpera);

function showPage(page)
{
  if(page>numpages)
    page=numpages;

  if(page<1)
    page=1;

  renderPage(MODE_PAGE, page, -1);

  disableSlideshow();
}

function showAll()
{
  renderPage(MODE_SHOWALL, -1, -1);

  disableSlideshow();
}

function showImage(imgno)
{
  hideInlineImage();
  
  if(imgno>=images.length)
    imgno=images.length-1;

  if(imgno<0)
    imgno=0;

  renderPage(MODE_IMAGE, Math.floor(imgno/imgspage)+1, imgno);

  disableSlideshow();
}

var waitImg;
function waitForImg()
{
  if(!waitImg.complete)
    setTimeout("waitForImg();", 200);
  else
  {
    slideTimeout=setTimeout("nextSlide(1);", document.getElementById("delaysel").value*1000);

    // let's also preload the next image
    var imgno=current_image+1;

    if(imgno>=images.length)
      imgno=0;

    waitImg.src=images[imgno];
  }
}

function gotoImage(imgno)
{
  imgno--;

  if(imgno>=images.length)
    imgno=images.length-1;

  if(imgno<0)
    imgno=0;

  renderPage(current_mode, Math.floor(imgno/imgspage)+1, imgno);
}

function nextSlide(dist)
{
  if(slideTimeout)
    clearTimeout(slideTimeout);

  var el=document.getElementById("slideshow");

  if(el.checked && images.length>0)
  {
    var imgno=(current_image<0) ? (current_page-1)*imgspage : current_image;
    var incr=dist*document.getElementById("dirsel").value;

    imgno+=incr;
    if((imgno<0 || imgno>=images.length) && wrapGals && galleries.length>1)
    {
      nextGallery(incr);
      imgno=current_image;

      el.checked=true; // enable slideshow again after loading gallery
    }
    else
    {
      if(imgno<0)
        imgno=images.length-1;

      if(imgno>=images.length)
        imgno=0;

      renderPage(MODE_IMAGE, Math.floor(imgno/imgspage)+1, imgno);
    }

    // preload next image
    preloadImage(imgno+incr);
    
    // since image.complete only works once, we have to create a new image here
    
    waitImg=new Image();
    waitImg.src=images[imgno];

    // now let's wait for the image to load
    waitForImg();
  }
  else
    disableSlideshow();
}

function nextGallery(incr)
{
  var galno=current_gallery+incr;
  
  if(galno<0)
    galno=galleries.length-1;

  if(galno>=galleries.length)
    galno=0;

  var imgno=(incr<0) ? -1 : 0;	// -1 means show last image in gallery

  showGallery(galno, MODE_IMAGE, -1, imgno);
}

function disableSlideshow()
{
  var el=document.getElementById("slideshow");

  if(el.checked)
    el.checked=false;
}

function appendSimpleElement(parent, id, tag)
{
  var el=document.createElement(tag);

  if(id)
    setAttribute(el, 'id', id);
    
  if(parent)
    parent.appendChild(el);

  return el;
}

function appendText(parent, text)
{
  var el=document.createTextNode(text);

  if(parent)
    parent.appendChild(el);

  return el;
}

function updateText(parentId, text)
{
  var el=document.getElementById(parentId);

  // note: we expect the text element to be the first element !!!
  if(el && el.firstChild && el.firstChild.nodeType==3)
    el.firstChild.nodeValue=text;
}

/* this a workaround for the bugs in IE's setAttribute */
function setAttribute(node, name, value) 
{
  // to be on the save side we always set attributes again
  try
  {
    if(value)
    {
      var attr=document.createAttribute(name);
      attr.value=value;

      node.setAttributeNode(attr);
    }
    else
      node.removeAttribute(name);
  }
  catch(e)
  {
    alert("failed to set attribute "+name+"="+value+"at node:\n"+e);
  }
} 

function updateAttributes(elId)
{
  var el=document.getElementById(elId);

  if(el)
  {
    for(var i=1; (i+1)<arguments.length; i+=2) 
    {
      if(el.getAttribute(arguments[i])!=arguments[i+1])
        setAttribute(el, arguments[i], arguments[i+1]);
    }
  }
}

function appendElement(parent, id, tag, text)
{
  var el=appendSimpleElement(parent, id, tag);

  for(var i=4; (i+1)<arguments.length; i+=2) 
  {
    setAttribute(el, arguments[i], arguments[i+1]);
  }

  if(text)
    appendText(el, text);

  return el;
}

function appendGalleryLink(parent, id, galno)
{
  return appendElement(parent, id, "a", galtitles[galno], "class", "gal_enabled", "href", "javascript:showGallery("+galno+", "+MODE_PAGE+", 1, "+defImg+");", "title", TT_SHOWGALLERY+galtitles[galno]);
}

function updateGalleryLink(elId, galno)
{
  var st, ref, title;
 
  var cimg=curImgs[galleries[galno]];
  var cmode=curMode[galleries[galno]];

  if(!cimg)
    cimg=defImg;

  if(!cmode)
    cmode=MODE_PAGE;
 
  if(galno>=0 && galno<galleries.length)
  {
    st="gal_enabled";
    ref="javascript:showGallery("+galno+", "+cmode+", -1, "+cimg+");";
    title=TT_SHOWGALLERY+galtitles[galno];
  }
  else
  {
    st="gal_disabled";
    ref=null;
    title="";
  }
  
  updateAttributes(elId, "class", st, "href", ref, "title", title);
}

function appendNavLink(parent, id, title, tooltip, page, current)
{
  if((page>=1 && page<=numpages) || wrapGals)
  {
    var tt=current ? "" : tooltip;
    var cl=current ? "page_current" : "page_enabled";
    var ref=current ? null : getPageURL(page);

    return appendElement(parent, id, "a", title, "title", tt, "class", cl, "href", ref);
  }
  else
    return appendElement(parent, id, "a", title, "title", "", "class", "page_disabled");
}

function updateNavLink(elId, page, current, tooltip)
{
  var st, ref, title;

  if((page>=1 && page<=numpages) || wrapGals)
  {
    title=current ? "" : tooltip;
    ref=current ? null : getPageURL(page);
    st=current ? "page_current" : "page_enabled";
  }
  else
  {
    st="page_disabled";
    ref="";
    title="";
  }

  updateAttributes(elId, "class", st, "href", ref, "title", title);
}

function getPageURL(page)
{
  var ref;

  if(page>=1 && page<=numpages)
  {
    ref="javascript:showPage("+page+");";
  }
  else
  {
    var galno, imgno;

    if(page<=1)
    {
      galno=current_gallery-1;
      imgno=-1;
    }
    else
    {
      galno=current_gallery+1;
      imgno=0;
    }

    if(galno>=galleries.length)
      galno=0;

    if(galno<0)
      galno=galleries.length-1;

    ref="javascript:showGallery("+galno+", "+current_mode+", -1, "+imgno+");"
  }

  return ref;
}

function appendShowallLink(parent, id, title)
{
  return appendElement(parent, id, "a", title, "title", TT_SHOWALL, "class", "page_enabled", "href", "javascript:showAll();");
}

function appendImageNavLink(parent, id, title, tooltip, imgno)
{
  if((imgno>=0 && imgno<images.length) || wrapGals)
    return appendElement(parent, id, "a", title, "title", tooltip, "class", "img_enabled", "href", getImageURL(imgno));
  else
    return appendElement(parent, id, "a", title, "title", "", "class", "img_disabled");
}

function updateImageNavLink(elId, tooltip, imgno)
{
  var st, ref, tt;

  if((imgno>=0 && imgno<images.length) || wrapGals)
  {
    st="img_enabled";
    ref=getImageURL(imgno);
    tt=tooltip;
  }
  else
  {
    st="img_disabled";
    ref=null;
    tt="";
  }

  updateAttributes(elId, "class", st, "href", ref, "title", tt);
}

function getImageURL(imgno)
{
  var ref;

  if(imgno>=0 && imgno<images.length)
  {
    ref="javascript:showImage("+imgno+");";
  }
  else
  {
    var galno;

    if(imgno<0)
    {
      galno=current_gallery-1;
      imgno=-1;
    }
    else
    {
      galno=current_gallery+1;
      imgno=0;
    }

    if(galno>=galleries.length)
      galno=0;

    if(galno<0)
      galno=galleries.length-1;

    ref="javascript:showGallery("+galno+", "+MODE_IMAGE+", -1, "+imgno+");"
  }

  return ref;
}

function getImageTitle(imgno)
{
  var tit="";
  var n=imgno+1;
  var dc=0;

  while(n>=1)
  {
    dc++;
    n=n/10;
  }
  
  while(dc<imgnumdigits)
  {
    tit+="0";
    dc++;
  }

  tit+=(imgno+1);

  return tit+" - "+titles[imgno];
}

function getImageTooltip(imgno)
{
  if(files[imgno]==titles[imgno])
	return titles[imgno];
  else
    return files[imgno]+" - "+titles[imgno];
}

function appendImageLink(parent, id, imgno)
{
  var imgsrc, visible, title, tooltip;
  var thw=thumbwidth;
  var thh=thumbheight;
  var imgEl;

  if(imgno>=images.length)
  {
    imgsrc=null;
    visible=false;
    title=" ";
    tooltip=null;
  }
  else
  {
    imgsrc=thumbs[imgno];
    visible=true;
    title=getImageTitle(imgno);
    tooltip=getImageTooltip(imgno);

    if(scales[imgno]=="vert")
      thw=null;
    else if(scales[imgno]=="horiz")
      thh=null;
  }

  var el=appendElement(parent, id, "a", null, "class", "img_orig", "href", "javascript:showImage("+imgno+");", "title", tooltip);
  appendElement(el, id+"_img", "img", null, "class", "thumb", "src", imgsrc, "width", thw, "height", thh, "title", tooltip);
  appendSimpleElement(el, id+"_br", "br");
  appendElement(el, id+"_span", "span", title, "class", "thumbfooter");

  setElementVisible(el, visible);
} 

function updateImageLink(elId, imgno)
{
  var imgsrc=thumbs[imgno];
  var visible=true;
  var title=getImageTitle(imgno);
  var tooltip=getImageTooltip(imgno);
  var thw=thumbwidth;
  var thh=thumbheight;

  if(imgno>=images.length)
  {
    imgsrc=null;
    tooltip=null;
    title=" ";
    visible=false;
  }
  else
  {
    if(scales[imgno]=="vert")
      thw=null;
    else if(scales[imgno]=="horiz")
      thh=null;
  }

  updateAttributes(elId, "href", "javascript:showImage("+imgno+");", "title", tooltip);
  updateAttributes(elId+"_img", "src", imgsrc, "width", thw, "height", thh, "title", tooltip);
  updateText(elId+"_span", title);

  var el=document.getElementById(elId);
  setElementVisible(el, visible);
}

function setElementVisible(el, visible)
{
  var disp=visible ? "" : "none";

  if(el && el.style.display!=disp)
    el.style.display=disp;
}

function removeChild(elId)
{
  var el=document.getElementById(elId);

  if(el && el.firstChild)
    el.removeChild(el.firstChild);
}

function replaceNodes(elId, childEl)
{
  var el=document.getElementById(elId);

  if(el)
  {
    if(el.firstChild)
    {
      if(childEl)
        el.replaceChild(childEl, el.firstChild);
      else
        el.removeChild(el.firstChild);
    }
    else if(childEl)
      el.appendChild(childEl);
  }
}

function createNavigation(mode, pageno)
{
  var rowEl, colEl, bodyEl, navEl;
  var prevStyle=(pageno>1) ? "navpage" : "navpage_disabled";
  var nextStyle=(pageno<numpages) ? "navpage" : "navpage_disabled";

  // check if really a create is required or maybe a simple update will do 
  if(mode==current_mode || (mode!=MODE_SHOWALL && (current_mode==MODE_IMAGE || current_mode==MODE_PAGE)))
  {
    if(mode!=current_mode || current_page!=pageno)
    {
      updateAttributes("pg_prev", "class", prevStyle);
      updateNavLink("pg_prev_link", pageno-1, false, TT_PREVIOUSPAGE);

      updateAttributes("pg_next", "class", nextStyle);
      updateNavLink("pg_next_link", pageno+1, false, TT_NEXTPAGE);

      if(current_page!=pageno)
      {
        updateAttributes("pg_"+current_page, "class", "jumppage");
        updateNavLink("pg_"+current_page+"_link", current_page, false, TT_SHOWPAGE+current_page);
      }

      updateAttributes("pg_"+pageno, "class", "jumppage_active");
      updateNavLink("pg_"+pageno+"_link", pageno, (mode!=MODE_IMAGE), TT_SHOWPAGE+pageno);
    }

    return null;
  }

  // now let's create the navigation
  navEl=appendElement(null, "ntab", "table", null, "class", "navigation");
  bodyEl=appendSimpleElement(navEl, "ntab_tb", "tbody");

  // create the with page links
  var inx=1;
  for(var r=0; r<numpagerows; r++)
  {
    rowEl=appendSimpleElement(bodyEl, "ntab_tr"+r, "tr");

    // create the previous link in first row
    if(r==0 && ((mode!=MODE_SHOWALL && numpages>1) || wrapGals==1))
    {
      colEl=appendElement(rowEl, "pg_prev", "td", null, "class", prevStyle, "rowspan", numpagerows);
      appendNavLink(colEl, "pg_prev_link", TXT_PREVIOUSPAGE, TT_PREVIOUSPAGE, pageno-1, false);
    }

    for(var i=0; i<pagesinrow && inx<=numpages; i++, inx++)
    {
      var style=(inx==pageno) ? "jumppage_active" : "jumppage";	  // is this the current page ?
      var pgn=((inx==pageno) && (mode==MODE_PAGE)) ? -1 : inx;    // in page mode we don't create a link

      colEl=appendElement(rowEl, "pg_"+inx, "td", null, "class", style);
      appendNavLink(colEl, "pg_"+inx+"_link", inx, TT_SHOWPAGE+inx, pgn, (inx==pageno) && (mode==MODE_PAGE));
    }

    // create the next link in first row
    if(r==0 && ((mode!=MODE_SHOWALL && numpages>1) || wrapGals==1))
    {
      if(numpages>1)
      {
        colEl=appendElement(rowEl, "showall", "td", null, "class", "showAll", "rowspan", numpagerows);
        appendShowallLink(colEl, "showall_link", TXT_SHOWALL);
      }

      colEl=appendElement(rowEl, "pg_next", "td", null, "class", nextStyle, "rowspan", numpagerows);
      appendNavLink(colEl, "pg_next_link", TXT_NEXTPAGE, TT_NEXTPAGE, pageno+1, false);
    }
  }

  return navEl;
}

function createThumbGallery(mode, pageno)
{
  var rowEl, colEl, bodyEl, mainEl;

  // create the page with thumbs
  var imgno=(pageno-1)*imgspage;

  // check if really a create is required or maybe a simple update will do 
  // updates don't work for opera due to not updated image sizes :-(
  if(!browserIsOpera && mode==current_mode)
  {
    if(mode!=MODE_SHOWALL && pageno!=current_page)
    {
      var i=0;
      for(var row=0; row<imgrows; row++)
      {
        for(var col=0; col<imgcols; col++)
        {
          updateImageLink("img_"+row+"_"+col+"_link", imgno);
          imgPosData[i].imgno=imgno;
          
          i++;
          imgno++;
        }
      }
    }

    return null;
  }

  var numrows=imgrows;

  // now let's create the image section
  mainEl=appendElement(null, PAD_ID, "table", null, "class", "gallery");
  bodyEl=appendSimpleElement(mainEl, "gtab_tb", "tbody");

  // for showAll we simply increase the rows per page, so that all thumbs fit
  if(mode==MODE_SHOWALL)
  {
    imgno=0;
    numrows=Math.ceil(images.length/imgcols);
  }

  imgPosData=new Array();
  var i=0;
  // create rows and cell with thumbs
  for(var row=0; row<numrows; row++)
  {
    rowEl=appendSimpleElement(bodyEl, "gtab_tr"+row, "tr");

    for(var col=0; col<imgcols; col++)
    {
      var id="img_"+row+"_"+col;

      colEl=appendElement(rowEl, id, "td", null, "class", "thumbcell", "width", thumbcellw, "height", thumbcellh);
      appendImageLink(colEl, id+"_link", imgno);
      imgPosData[i]=new MousePosData(id+"_link_img", imgno);
                 
      i++;
      imgno++;
    }
  }
   
  return mainEl;
}

function createImageGallery(mode, imgno)
{
  var aEl, rowEl, colEl, bodyEl, mainEl;
  var prevStyle=(imgno>0) ? "img_navpage" : "img_navpage_disabled";
  var nextStyle=(imgno<images.length-1) ? "img_navpage" : "img_navpage_disabled";
  var title=getImageTitle(imgno);
  var tooltip=getImageTooltip(imgno);
  var imgw,imgh;

  imgw=imagewidth;
  imgh=imageheight;

  if(scales[imgno]=="vert")
    imgw=null;
  else if(scales[imgno]="horiz")
    imgh=null;

  // check if really a create is required or maybe a simple update will do
  // updates don't work for opera due to not updated image sizes :-(
  if(!browserIsOpera && mode==current_mode)
  {
    updateAttributes("img_prev", "class", prevStyle);
    updateImageNavLink("img_prev_link", TT_PREVIOUSIMG, imgno-1);

    updateText("image_name", title);
    updateAttributes("im", "title", tooltip);

    updateAttributes("img_next", "class", nextStyle);
    updateImageNavLink("img_next_link", TT_NEXTIMG, imgno+1);
       
    updateAttributes("img_nameref", "href", images[imgno]);

    updateAttributes("img_imgref", "src", images[imgno], "width", imgw, "height", imgh, "title", tooltip);
    updateText("img_os", descriptions[imgno]);
    updateAttributes("img_os", "title", files[imgno]);

    return null;
  }

  // now let's create the image section
  mainEl=appendElement(null, "gtab", "table", null, "class", "gallery");
  bodyEl=appendSimpleElement(mainEl, "gtab_tb", "tbody");

  // create the page with the image
  rowEl=appendSimpleElement(bodyEl, "gtab_tr0", "tr");

  // create the link for previous image
  colEl=appendElement(rowEl, "img_prev", "td", null, "class", prevStyle);
  appendImageNavLink(colEl, "img_prev_link", TXT_PREVIOUSIMG, TT_PREVIOUSIMG, imgno-1);

  // display image name in the middle
  appendElement(rowEl, "image_name", "td", title, "class", "img_jumppage_active", "title", tooltip);

  // create the link for next image
  colEl=appendElement(rowEl, "img_next", "td", null, "class", nextStyle);
  appendImageNavLink(colEl, "img_next_link", TXT_NEXTIMG, TT_NEXTIMG, imgno+1);

  // create the row with the image cell
  rowEl=appendSimpleElement(bodyEl, "gtab_tr1", "tr");
  colEl=appendElement(rowEl, PAD_ID, "td", null, "class", "picturecell", "colspan", 3, "width", imagecellw);

  // create a link link to the image containing the image
  aEl=appendElement(colEl, "img_nameref", "a", null, "class", "img_orig", "href", images[imgno], "target", imagetarget);
  appendElement(aEl, "img_imgref", "img", null, "class", "picture", "src", images[imgno], "width", imgw, "height", imgh, "title", tooltip);
  appendSimpleElement(aEl, "img_br", "br");
  appendElement(aEl, "img_os", "span", descriptions[imgno], "class", "picturefooter", "title", files[imgno]);

  return mainEl;
}

function mouseMovedInThumbGallery(ev)
{
  ev=ev || window.event;
  
  var x, y;
  
  if(ev.pageX || ev.pageY)
  {
    x=ev.pageX;
    y=ev.pageY;
  }
  else
  {
	x=ev.clientX+document.body.scrollLeft-document.body.clientLeft;
    y=ev.clientY+document.body.scrollTop-document.body.clientTop;
  }

  for(var i=0; i<imgPosData.length; i++)
  {
    if(imgPosData[i].isInside(x,y))
    {
   	  showInlineImage(imgPosData[i]);
      return;
	}
  }
}

function showInlineImage(ipd)
{
  document.onmousemove=null;	// disable mouse move for now
  
  // trigger a preload
  var img=preloadImage(ipd.imgno);
 
  var el=createInlineImage(ipd.imgno);
  
  if(el)
   	replaceNodes(ILNDIV_ID, el);

  var imgEl=ipd.getImgElement();
  var pos=ipd.getScreenPosition();
  var x=pos.x1+imgEl.offsetWidth/2;
  var y=pos.y1+imgEl.offsetHeight/2;
  
  // now we have to wait for the image to be loaded
  il_img=img;
  il_imgPosData=ipd;
  waitInlineLoaded(ipd.imgno, x, y);
}

var il_img;
var il_imgPosData;
var il_bw=0, il_bh=0;
function waitInlineLoaded(imgno, x, y)
{
  if(!il_img.complete)
  {
	setTimeout("waitInlineLoaded("+imgno+","+x+","+y+");", 200);
	return;
  }
  
  var ps=getPageSize(), bs=getBrowserSize();
  var pw=Math.max(ps.width, bs.width);
  var ph=Math.max(ps.height, bs.height);
  
  // initial positon at left top 
  var divEl=document.getElementById(ILNDIV_ID);
  var st=divEl.style;
  st.left=0;
  st.top=0;
  
  // set visible and set position afterwards
  updateAttributes(ILNDIV_ID, "class", "inlinediv");
  
  // offsetWidth and Height is only availabe now !!!!!
  var imgw=divEl.offsetWidth;
  var imgh=divEl.offsetHeight;
  
  x-=(imgw/2);
  y-=(imgh/2);
  
  // now make sure the inline is within browser window
  if(x+imgw>pw) x=pw-imgw;
  if(y+imgh>ph) y=ph-imgh;
  if(x<0) x=0;
  if(y<0) y=0;

  // finally set position and install mouse move handler
  st.left=x+"px";
  st.top=y+"px";

  document.onmousemove=mouseMovedInInlineImage;
  
  // now preload the next probable images
  preloadImage(imgno+1);
  preloadImage(imgno-1);
  preloadImage(imgno+imgcols);
  preloadImage(imgno-imgcols);
  preloadImage(imgno+imgcols+1);
  preloadImage(imgno-imgcols+1);
  preloadImage(imgno+imgcols-1);
  preloadImage(imgno-imgcols-1);
}

function preloadImage(imgno)
{
  var img=null;
  
  if(imgno>=0 && imgno<images.length)
  {
    img=new Image();
    img.src=images[imgno];
  }
  
  return img; 
}

function mouseMovedInInlineImage(ev)
{
  ev=ev || window.event;
  
  var x, y;
  
  if(ev.pageX || ev.pageY)
  {
    x=ev.pageX;
    y=ev.pageY;
  }
  else
  {
	x=ev.clientX+document.body.scrollLeft-document.body.clientLeft;
    y=ev.clientY+document.body.scrollTop-document.body.clientTop;
  }
  
  if(!il_imgPosData.isInside(x, y))
  {
    hideInlineImage();
  }
}

function hideInlineImage()
{
  updateAttributes(ILNDIV_ID, "class", "invisible");
  // enable normal mouse move again
  document.onmousemove=mouseMovedInThumbGallery;
}

function createInlineImage(imgno)
{
  var tooltip=getImageTooltip(imgno);	
  var el;
  var imgw,imgh;

  imgw=ilnwidth;
  imgh=ilnheight;

  if(scales[imgno]=="vert")
    imgw=null;
  else if(scales[imgno]="horiz")
    imgh=null;

  // check if really a create is required or maybe a simple update will do
  // updates don't work for opera due to not updated image sizes :-(
  if(!browserIsOpera && document.getElementById("iln_img"))
  {
    updateAttributes("iln_img_nameref", "href", "javascript:showImage("+imgno+");", "title", tooltip);
	updateAttributes("iln_img", "src", images[imgno], "width", imgw, "height", imgh, "title", tooltip);

    return null;
  }

  el=appendElement(null, "iln_img_nameref", "a", null, "class", "inline_link", "href", "javascript:showImage("+imgno+");", "title", tooltip);
  appendElement(el, "iln_img", "img", null, "class", "inline_picture", "src", images[imgno], "width", imgw, "height", imgh, "title", tooltip, "onMouseout", "hideInlineImage()");

  return el;
}

// this method renders the complete page (for all modes)
function renderPage(mode, pageno, imgno)
{ 
  var navEl, mainEl;

  // disable on mouse move
  document.onmousemove=null;
  
  // we only set the title if the mode is initial
  if(current_mode<0)
  {
    var titleEl=appendText(null, title);

    if(titleEl)
      replaceNodes("title", titleEl);
  }

  // create the navigation area
  navEl=createNavigation(mode, pageno);
  if(navEl)
    replaceNodes(NAV_ID, navEl);

  // create the gallery area
  if(mode!=MODE_IMAGE)		// page or showall mode
  {
    mainEl=createThumbGallery(mode, pageno, imgno);

    if(imgno>=pageno*imgspage)
      imgno=pageno*imgspage-1;

    if(imgno<(pageno-1)*imgspage)
      imgno=(pageno-1)*imgspage;
  }
  else
    mainEl=createImageGallery(mode, imgno);

  if(mainEl)
    replaceNodes(MAIN_ID, mainEl);

  // update image number
  var num=imgno;

  if(num<0)
    num=(pageno-1)*imgspage;

  if(num<0)
    num="";
  else
    num++;

  document.getElementById("imgno").value=num;

  // now update the variables with the current values
  current_mode=mode;
  current_page=pageno;
  current_image=imgno;
  
  // now let's save the state in the cookie
  updateJsgalCookie();
  
  // update padding
  scaleToFitWindow();
  
  // enable mouse moved for gallery
  if(mode!=MODE_IMAGE)		// page or showall mode
	document.onmousemove=mouseMovedInThumbGallery;
}

function collapseGalleries(col)
{
  collapseGals=col;

  renderGalleries();
  recalcGallerySize(false);
}

function renderGalleries()
{
  var colEl, rowEl, bodyEl, galsEl=null;

  // hide the not needed rows for horiz or vert gallery navigation
  var vstyle, hstyle;
  if(horizGalNav || galleries.length<=1)
  {
    vstyle="invisible";
    hstyle="visible";

    GALS_ID="hgals";
    NAV_ID="hnav";
    MAIN_ID="hmain";
  }
  else
  {
    vstyle="visible";
    hstyle="invisible";

    GALS_ID="gals";
    NAV_ID="nav";
    MAIN_ID="main";
  }

  updateAttributes("hgalrow", "class", hstyle);
  updateAttributes("hnavrow", "class", hstyle);
  updateAttributes("hmainrow", "class", hstyle);
  updateAttributes("vgalnavrow", "class", vstyle);
  updateAttributes("vmainrow", "class", vstyle);

  // we only render the galleries area if there are at least 2 of them
  if(galleries.length>1)
  {
    galsEl=appendElement(null, "gstab", "table", null, "class", "gallerysel", "cellspacing", "0");
    bodyEl=appendSimpleElement(galsEl, "gstab_tb", "tbody");

    // now add support for collapsing galleries (only with vertical gallery navigation
    if(!horizGalNav)	
    {
        rowEl=appendSimpleElement(bodyEl, "gstab_tr_col", "tr");
        colEl=appendElement(rowEl, "gstab_tr_col_td", "td", null, "class", "navgal_col");
       
        var txt=(collapseGals) ? TXT_EXPANDGALS : TXT_COLLAPSEGALS;
        var tt=(collapseGals) ? TT_EXPANDGALS : TT_COLLAPSEGALS; 
        var val=(collapseGals) ? 0 : 1;

        // since IE doesn't allow to set the type of an input node, we have to use a link instead of a button :-(
        appendElement(colEl, "expand_galnav", "a", txt, "title", tt, "class", "button_col", "href", "javascript:collapseGalleries("+val+");");
    }

    if(horizGalNav || !collapseGals)
    {
      for(var i=0; i<galleries.length; i++)
      {
        var style=(i==current_gallery) ? "navgal_active" : "navgal";

        if(!horizGalNav || (i%galsInRow)==0) 
          rowEl=appendSimpleElement(bodyEl, "gstab_tr"+i, "tr");

        colEl=appendElement(rowEl, "gstab_tr"+i+"_td", "td", null, "class", style);

        appendGalleryLink(colEl, "gallery_"+i, i);
      }
    }
  }
  else
  {
    // we now also hide the galleries row
    updateAttributes("hgalrow", "class", "invisible");
  }

  // now add the nodes to the DOM
  if(galsEl)
    replaceNodes(GALS_ID, galsEl);
}

function updateGalleries(galNo)
{
  // mark old current as no longer active
  if(current_gallery>=0)
  {
    updateAttributes("gstab_tr"+current_gallery+"_td", "class", "navgal");
    updateGalleryLink("gallery_"+current_gallery, current_gallery);
  }

  // mark new gallery as active
  updateAttributes("gstab_tr"+galNo+"_td", "class", "navgal_active");
  updateGalleryLink("gallery_"+galNo, -1);

  // now we have to set the state variables
  current_mode=-1;
  current_page=-1;
  current_image=-1;
  current_gallery=galNo;
}

function showMessage(msg)
{
  replaceNodes("title", appendText(null, msg));
}

var JSCOOKIE="jsstyle";

function updateJsgalCookie()
{
  var gal=galleries[current_gallery];
  var imgno=(current_mode==MODE_PAGE) ? (current_page-1)*imgspage : current_image;
  // we no longer store the current page, but the first image to allow resizing
  var ck=document.getElementById('styletag').getAttribute('href')+","+current_mode+",-1,"+imgno+","+gal;
  var dt=new Date();
  
  ck+="|"+collapseGals+"|"+horizGalNav;

  // update values for current gallery before creating cookie
  curImgs[gal]=imgno;
  curMode[gal]=current_mode;
  curThumbZooms[gal]=thumbzoom;
  curImgZooms[gal]=imagezoom;
  curPreviewZooms[gal]=ilnzoom;

  for(var i=0; i<galleries.length; i++)
  {
    if(curImgs[galleries[i]] && curMode[galleries[i]])
    {
      ck+=","+galleries[i]+"#"+curMode[galleries[i]]+"#"+curImgs[galleries[i]];

      if(curThumbZooms[galleries[i]] && curImgZooms[galleries[i]])
      {
        ck+="#"+curThumbZooms[galleries[i]]+"#"+curImgZooms[galleries[i]];
        if(curPreviewZooms[galleries[i]])
          ck+="#"+curPreviewZooms[galleries[i]];
      }
    }
  }

  dt.setFullYear(dt.getFullYear()+1);	// let's set the cookie expiry time 1 year in the future
  
  document.cookie=JSCOOKIE+"="+escape(ck)+"; expires="+dt.toGMTString();  
}

function getJsgalCookie()
{
  var s=document.cookie;
  var inx=s.indexOf(JSCOOKIE+"=");

  if(inx<0)
    return null;
  
  s=s.substring(inx+JSCOOKIE.length+1, s.length);

  inx=s.indexOf(";");
  if(inx>0)
    s=s.substring(0, inx);

  return unescape(s); 
}

function restoreState()
{
  // first let's try to load the galleries
  loadGalleries(document.getElementById("galleries").getAttribute("href"));

  try
  {
    var ck=getJsgalCookie();
    var cssfile, gallery, galNo=-1, mode=MODE_PAGE, page=-1, imgno=-1, imgsp=-1;

    if(ck)
    {
      var cks=ck.split(",");
   
      cssfile=cks[0];
      if(cks.length>=4)
      {
        mode=parseInt(cks[1]);
        page=parseInt(cks[2]);
        imgno=parseInt(cks[3]);

        if(cks.length>=5)
        {
          var cgs=cks[4].split("|");

          gallery=cgs[0];
          if(cgs.length>1)
            collapseGals=parseInt(cgs[1]);
          if(cgs.length>2)
            horizGalNav=parseInt(cgs[2]);
        }
      } 

      for(var i=5; i<cks.length; i++)
      {
        var gis=cks[i].split("#");

        if(gis.length>=3)
        {
          curMode[gis[0]]=parseInt(gis[1]);
          curImgs[gis[0]]=parseInt(gis[2]);

          if(gis.length>=5)
          {
            curThumbZooms[gis[0]]=parseFloat(gis[3]);
            curImgZooms[gis[0]]=parseFloat(gis[4]);
            
            if(gis.length>=6)
            {
              curPreviewZooms[gis[0]]=parseFloat(gis[5]);
            }
          }
        }
      }
    }
    else
      cssfile=document.getElementById('styletag').getAttribute('href');

    setStyle(cssfile);
    
    // now select style in combo box
    var opts=document.getElementById("stylesel").options;
    for(var i=0; i<opts.length; i++)
      opts[i].selected=(opts[i].value==cssfile);

    // load gallery if not current one
    if(gallery && galleries.length>0)
    {
      for(var i=0; i<galleries.length; i++)
      {
        if(gallery==galleries[i])
        {
          galNo=i;
          break;
        }
      }
    }

    if(galNo>=galleries.length)
      galNo=-1;

    if(galNo<0 && galleries.length>0)
    {
      if(defGal<0 || defGal>=galleries.length)
        galNo=galleries.length-1;
      else
        galNo=0;
    }

    // finally render galleries and restore page
    renderGalleries();

    // now restore the state of the page
    if(galNo>=0)
      showGallery(galNo, mode, page, imgno);
  }
  catch(e)
  {
    // if anything goes wrong we restore the first page
    renderGalleries();
    showPage(1);
  }
  
  scaleToFitWindow();
}

function toogleGalleryNavOrientation()
{
  // first remove nodes from current layout
  removeChild(GALS_ID);
  removeChild(NAV_ID);
  removeChild(MAIN_ID);

  // now render everything again with new orientation
  horizGalNav=(horizGalNav==0) ? 1 : 0;

  renderGalleries();
  showGallery(current_gallery, current_mode, current_page, current_image);
}

function showGallery(galNo, mode, page, imgno)
{
  var gallery;

  if(galNo>=galleries.length)
    galNo=galleries.length-1;

  if(galNo<0)
    galNo=0;

  gallery=galleries[galNo];
  thumbzoom=curThumbZooms[gallery];
  imagezoom=curImgZooms[gallery];
  ilnzoom=curPreviewZooms[gallery];
  calcImageSizes();

  if(loadGallery(gallery))
  {
    updateGalleries(galNo);

    // no valid image, so we use last image 
    if(imgno<0 || imgno>=images.length)
      imgno=images.length-1;

    if(mode==MODE_IMAGE)
      showImage(imgno);
    else if(mode==MODE_SHOWALL)
      showAll();
    else
    {
      if(page<1)	// if no page provide the imgno is the number of the first image
        page=Math.floor(imgno/imgspage)+1;

      showPage(page);
    }
  }
}

function setStyle(cssfile)
{
  var st=document.getElementById('styletag');
  st.setAttribute('href', cssfile);

  scaleToFitWindow();
  
  // now let's save the style in the cookie
  updateJsgalCookie();
}

function loadGalleries(galsUrl)
{
  showMessage(TXT_MSG_LOADGALS);

  try
  {
    var xmlDoc=parseDocument(galsUrl);
 
    var gals=xmlDoc.getElementsByTagName("jsgals");
    if(gals.length>0)
    {
      defGal=getIntAttribute(gals[0], "defaultGal", defGal);
      defImg=getIntAttribute(gals[0], "defaultImg", defImg);
      wrapGals=getIntAttribute(gals[0], "wrapGalleries", wrapGals);
      horizGalNav=getIntAttribute(gals[0], "horizgalleriesnav", horizGalNav);
      galsInRow=getIntAttribute(gals[0], "galleriesinhorizrow", galsInRow);
    }

    gals=xmlDoc.getElementsByTagName("gallery");
    galleries=new Array(gals.length);
    galtitles=new Array(gals.length);

    for(var i=0; i<gals.length; i++)
    {
      var file=gals[i].getAttribute("file");

      galleries[i]=getRelativeURL(galsUrl, file);
      galtitles[i]=(gals[i].firstChild) ? gals[i].firstChild.nodeValue : file;
    }
  }
  catch(e)
  {
    showMessage(TXT_ERR_LOADGALS+e);
    return false;
  }
}

function loadGallery(galurl)
{
  showMessage(TXT_MSG_LOADGAL);

  try
  {
    parseGallery(galurl);

    updateGallerySize();
  }
  catch(e)
  {
    showMessage(TXT_ERR_LOADGAL+e);
    return false;
  }

  return true;
}

var origcols;
var origrows;
function updateGallerySize()
{
  var evh=null;
  var bs=getBrowserSize();
  
  calcImageSizes();

  origcols=imgcols;
  origrows=imgrows;

  if(imgcols<1 || imgrows<1) 
    evh=checkGallerySize;

  // now let's handle the case were we should try to find optimal number of thumbs per page
  if(thumbwidth || thumbheight)
  {
    // the whole calculation is a best guess, since otherwise we would have to take the actual image
    // sizes and the current style sheet into account

    if(imgcols<1)
    {
      var tw=(thumbwidth) ? thumbwidth : (thumbheight*4)/3;                   // we expect 4x3 sizes if no width specified
      var bw=bs.width;		// the width we use for gallery

      if(horizGalNav || galleries.length<=1)
        bw*=0.99;	// with horiz galleries we use 99% 
      else if(collapseGals)
        bw*=0.95;	// with collapsed galleries we use 95%
      else
        bw*=0.8;	// will vertical galleries we use 80%    

      tw+=10;         // for a bit of border between the images

      imgcols=Math.floor(bw/tw);
    }

    if(imgrows<1)
    {
      var th=(thumbheight) ? thumbheight : (thumbwidth*3)/4;                   // we expect 4x3 sizes if no width specified
      var ch=Math.max(document.getElementById(MAIN_ID).offsetHeight, document.getElementById(GALS_ID).offsetHeight);
      var bh=bs.height-document.getElementById("docbody").offsetHeight+ch; 
      
      // for horizontal navigation we need additional vertical space
      if(horizGalNav)
        bh-=(15*(1+(galleries.length/galsInRow)));
    
      th+=35;         // for a bit of border and the image description below

      var cssfile=document.getElementById('styletag').getAttribute('href');
      if(cssfile=="slickgreen.css")	// here we have a really big border !!!
        th+=10;

      bh*=0.9;        // we use only 90% here

      imgrows=Math.floor(bh/th);
    }
  }

  if(imgcols<1)
    imgcols=1;

  if(imgrows<1)
    imgrows=1;

  // now let's update the remaining variables
  imgspage=imgrows*imgcols;
  numpages=Math.ceil(images.length/imgspage);
  numpagerows=Math.ceil(numpages/pagesinrow);

  // now set event handler for resize
  window.onresize=evh;
}

function checkGallerySize()
{
  recalcGallerySize(false);
}

function recalcGallerySize(doRepaint)
{
  var oldcols=imgcols;
  var oldrows=imgrows;
  var pimgno=(current_page-1)*imgspage;

  imgcols=origcols;
  imgrows=origrows;

  updateGallerySize();

  if(doRepaint || imgcols!=oldcols || imgrows!=oldrows)
  {
    // something has changed so we have to redraw the gallery
    var mode=current_mode;
    var imgno=current_image;
    
    current_mode=-1;
    current_page=-1;

    if(mode==MODE_IMAGE)
      showImage(imgno);
    else if(mode==MODE_SHOWALL)
      showAll();
    else
      showPage(Math.floor(pimgno/imgspage)+1);
  }
  
  scaleToFitWindow();
}

function scaleToFitWindow()
{
  var el=document.getElementById(PAD_ID);

  if(el)
  {
	var bs=getBrowserSize();
	var ps=getPageSize();

	// now set padding element height to fill page
	var h=bs.height-ps.height+el.offsetHeight;

	// in gallery mode we somehow seem to loose 2 pixels in IE ????
	if(browserIsIE && current_mode==MODE_IMAGE)
	  h-=2;		
	
	if(h<0) h=0;
		  
	el.style.height=h+"px";
  }
}

function m(el, tit)
{
  if(el)
    return tit+" h="+el.height+" sh="+el.scrollHeight+" ch="+el.clientHeight+" oh="+el.offsetHeight+"\n";
  else
	return tit+" undefined\n";
}

function zoomImages(fact)
{
  if(current_mode==MODE_IMAGE)
    imagezoom*=fact;
  else
    thumbzoom*=fact;

  if(imagezoom<=0)
    imagezoom=1.0;

  if(thumbzoom<=0)
    thumbzoom=1.0;

  // now trigger repainting
  recalcGallerySize(true);

  updateJsgalCookie();
}

function zoomPreview(fact)
{
  ilnzoom*=fact;

  if(ilnzoom<=0)
    ilnzoom=1.0;

  if(ilnzoom<=0)
    ilnzoom=1.0;

  calcPreviewSize();

  updateJsgalCookie();
}

function parseDocument(docurl)
{
  var xmlDoc=null;

  // first we try to load the XML file using an XMLDocument
  // we still need this since IE won't support loading from file system using XMLHttpRequest 
  try
  {

    // first create an xml document using the mozilla or IE way
    if(document.implementation && document.implementation.createDocument)
      xmlDoc=document.implementation.createDocument("", "", null);
    else if(window.ActiveXObject)
      xmlDoc=new ActiveXObject("Microsoft.XMLDOM");

    if(xmlDoc)
    {
      xmlDoc.async=false;
      xmlDoc.load(docurl);
    }
  }
  catch(e)
  {
    xmlDoc=null;
  }

  if(xmlDoc)
  {
    if(xmlDoc.parseError)         // handle IE errors
    {
      if(xmlDoc.parseError.errorCode!=0)
        throw xmlDoc.parseError.reason;
    }
    else if(xmlDoc.documentElement && xmlDoc.documentElement.tagName=="parsererror")        // handle mozilla errors
    {
        throw xmlDoc.documentElement.firstChild.nodeValue;
    }

    if(xmlDoc.firstChild)
      return xmlDoc;

// we ignore this throw to make it work with konquerer
//    throw "Error: failed to get XML document from "+docurl;
  }

  // now let's try to load using an XMLHttpRequest
  var xmlReq=null;

  // first let's create an XMLHTTPRequest and load the document using the mozilla or IE way
  if(window.XMLHttpRequest) 
    xmlReq=new XMLHttpRequest();
  else if(window.ActiveXObject)
  {
    try 
    {
      xmlReq=new ActiveXObject("Msxml2.XMLHTTP");
    }
    catch(e)
    {
      try
      {
        xmlReq=new ActiveXObject("Microsoft.XMLHTTP");
      }
      catch(e2) { }
    }
  }

  if(!xmlReq)
    throw "Error: XMLHttpRequest not supported by your browser";

  xmlReq.open("GET", docurl, false);
  xmlReq.send(null);

  // 0 is returned when loading from file system not using HTTP !!!
  if(xmlReq.status>0 && (xmlReq.status<200 || xmlReq.status>=400))	
    throw "Error during XMLHttpRequest: "+xmlReq.status+" - "+xmlReq.statusText;

  return xmlReq.responseXML;
}

function parseGallery(galurl)
{
  var xmlDoc=parseDocument(galurl);
  var thumbdir="";
  var imagedir="";
  var defscale="vert";	// vertical scaling is the default 

  // parse the document and set the javascript variables
  var el=getFirstElement(xmlDoc, "title");

  if(el && el.firstChild)
    title=el.firstChild.nodeValue;

  el=getFirstElement(xmlDoc, "thumbs");
  if(el)
  {
    imgrows=getIntAttribute(el, "rows", 3);
    imgcols=getIntAttribute(el, "columns", 3);
    pagesinrow=getIntAttribute(el, "pagesinrow", 20);
    thumbwidth_nozoom=getIntAttribute(el, "width", null);
    thumbheight_nozoom=getIntAttribute(el, "height", 150);
  }

  el=getFirstElement(xmlDoc, "images");
  if(el)
  {
    thumbdir=getAttribute(el, "thumbsdir", thumbdir);
    imagedir=getAttribute(el, "imagesdir", imagedir);
    imagewidth_nozoom=getIntAttribute(el, "width", null);
    imageheight_nozoom=getIntAttribute(el, "height", 600);
    previewScale=getFloatAttribute(el, "previewScale", 0.7);
    imagetarget=getAttribute(el, "target", imagetarget);
    defscale=getAttribute(el, "defscale", defscale);
  }
  
  // get relative URLs
  thumbdir=getRelativeURL(galurl, thumbdir);
  imagedir=getRelativeURL(galurl, imagedir);

  // add slash to thumbdir and imagedir if missing
  if(thumbdir.length>0 && thumbdir.charAt(thumbdir.length-1)!='/')
	  thumbdir+="/";

  if(imagedir.length>0 && imagedir.charAt(imagedir.length-1)!='/')
	  imagedir+="/";
  
  // now get all the images
  var imgs=xmlDoc.getElementsByTagName("image");
  files=new Array(imgs.length);
  images=new Array(imgs.length);
  thumbs=new Array(imgs.length);
  titles=new Array(imgs.length);
  descriptions=new Array(imgs.length);
  scales=new Array(imgs.length);

  for(var i=0; i<imgs.length; i++)
  {
    var file=imgs[i].getAttribute("file");

    files[i]=file;
    images[i]=imagedir+file;
    thumbs[i]=thumbdir+getAttribute(imgs[i], "thumb", file);
    titles[i]=getAttribute(imgs[i], "name", file);
    descriptions[i]=(imgs[i].firstChild) ? imgs[i].firstChild.nodeValue : TXT_ORIGSIZE;
    scales[i]=getAttribute(imgs[i], "scale", defscale);
  }
}

function calcImageSizes()
{
  if(thumbzoom<=0 || thumbzoom==NaN || thumbzoom==null)
    thumbzoom=1.0;

  if(imagezoom<=0 || imagezoom==NaN || imagezoom==null)
    imagezoom=1.0;

  thumbwidth=thumbwidth_nozoom ? Math.ceil(thumbwidth_nozoom*thumbzoom) : null;
  thumbheight=thumbheight_nozoom ? Math.ceil(thumbheight_nozoom*thumbzoom) : null;

  imagewidth=imagewidth_nozoom ? Math.ceil(imagewidth_nozoom*imagezoom) : null;
  imageheight=imageheight_nozoom ? Math.ceil(imageheight_nozoom*imagezoom) : null;

  if(thumbwidth || thumbheight)
  {
    thumbcellw=thumbwidth ? thumbwidth : Math.floor((thumbheight*4)/3);		// we expect 4:3 ratio
    thumbcellh=thumbheight ? thumbheight : Math.floor((thumbwidth*3)/4);  

    thumbcellw+=12;
    thumbcellh+=24;
  }
  else
  {
    thumbcellw="auto";
    thumbcellh="auto";
  }

  if(imagewidth || imageheight)
  {
    imagecellw=imagewidth ? imagewidth : Math.floor((imageheight*4)/3);		// we expect 4:3 ratio

    imagecellw+=40;
  }
  else
  {
    imagecellw="auto";
  }
  
  calcPreviewSize();
}

function calcPreviewSize()
{
  if(ilnzoom<=0 || ilnzoom==NaN || ilnzoom==null)
    ilnzoom=1.0;
  
  ilnwidth=imagewidth ? Math.ceil(imagewidth*previewScale*ilnzoom) : null;
  ilnheight=imageheight ? Math.ceil(imageheight*previewScale*ilnzoom) : null;
}

function getFirstElement(doc, tag)
{
  var els=doc.getElementsByTagName(tag);

  if(els.length>0)
    return els[0];
  else
    return null;
}

function getIntAttribute(el, attr, def)
{
  var val=getAttribute(el, attr, def);

  if(val)
    val=parseInt(val);

  return val;
}

function getFloatAttribute(el, attr, def)
{
  var val=getAttribute(el, attr, def);

  if(val)
    val=parseFloat(val);

  return val;
}

function getAttribute(el, attr, def)
{
  var val=el.getAttribute(attr);

  if(val)
  {
    if(val=="null")
      return null;
    else
      return val;
  }
  else
    return def;
}

function getBrowserSize()
{
  var w, h;
  
  if(window.innerHeight)
  {
	// not supported by IE - again :-(
    w=window.innerWidth;
    h=window.innerHeight;
  }
  else if(document.documentElement && document.documentElement.clientHeight)
  {
	w=document.documentElement.clientWidth;
	h=document.documentElement.clientHeight;
  }
  else
  {
	w=document.body.clientWidth;
	h=document.body.clientHeight;
  }

  return {width: w, height: h};
}

function getPageSize()
{
  var w, h;
  
  if(browserIsIE)
  {
    // again a special rule for IE, since documentElement.offsetHeight is not working :-(
    w=document.documentElement.scrollWidth;
    h=document.documentElement.scrollHeight;
  }
  else
  {
	w=document.documentElement.offsetWidth;
	h=document.documentElement.offsetHeight;
  }
	  
  return {width: w, height: h};
}

function getRelativeURL(base, url)
{
	if(url.indexOf("://")>=0 || url.indexOf("/")==0)	// this looks like an absolute url
		return url;
	
	var i=base.lastIndexOf("/");
	
	if(i>=0)
	{
		return base.substr(0, i)+"/"+url;
	}
	
	return url;
}

var dbg="";
function DEBUG(out)
{
  dbg+=out+"<BR>";
  var el=document.getElementById("debugOut");
  if(el)
  {
    el.innerHTML=dbg;
  }
}

// the classes we use
function MousePosData(id, ino)
{
  this.elId=id;
  this.imgno=ino;
  
  // now the methods
  this.getImgElement=function()
  {
	return document.getElementById(this.elId);
  }
  
  this.getScreenPosition=function()
  {
	 var imgEl=this.getImgElement();
	 var x1=0, y1=0, x2=-1, y2=-1;
	 
	 if(imgEl && this.imgno>=0 && this.imgno<images.length)
	 {
		var el=imgEl;
	    if(el.offsetParent)
		{
		  do
		  {
		    x1+=el.offsetLeft;
		    y1+=el.offsetTop;
		  }while(el=el.offsetParent);
		}

		x2=x1+imgEl.offsetWidth-1;
		y2=y1+imgEl.offsetHeight-1;	  		 
	 }
	 
	 return {x1: x1, y1: y1, x2: x2, y2: y2};
  };
  
  this.isInside=function(x,y)
  {
	  var pos=this.getScreenPosition();
	  
	  return (x>=pos.x1 && x<=pos.x2 && y>=pos.y1 && y<=pos.y2);
  }
}
