/* base directory (URL) containing images */
var jsphotodir;

/* array of photos with descriptions */
var jsphotoalbum  = new Array();

/* Title of the gallery */
var jsphototitle;

/* width of the main window */
var jsphotow;

/* current photo */
var jsphotocur = 0;

/* number of photos in jsphotoalbum array */
var jsphotocount = 0;

/* array of large images */
var jsphotoimages = new Array();

/* max number of images to preload */
var jsphotopreloadcount = 2;

/* get width of browser window */
var jsphotowidth;
if (window.outerWidth) {
  /* Mozilla, opera */
  jsphotowidth = window.outerWidth;
} else {
  /* MSIE */
  jsphotowidth = screen.width;
}

/* number of thumbnails on a index page */
var jsphotothumbsx;
var jsphotothumbsy;  
if (jsphotowidth > 850) {
  /* high-res */
  jsphotothumbsx = 5;
  jsphotothumbsy = 2;  
} else if (jsphotowidth > 700) {
  /* med-resolution */
  jsphotothumbsx = 4;
  jsphotothumbsy = 3;
} else {
  /* low-resolution */
  jsphotothumbsx = 3;
  jsphotothumbsy = 2;
}

/* current tab page */
var jsphotocurtab = 1;

/* array of thumbnail images */
var jsphotothumbs = new Array();

/* number of image currently on load */
var jsphotoloading = -1;
var jsphotoloaded = new Array();

/* name and life-time of a cookie to track visited photos */
var jsphotocookiename = "";
var jsphotoexpiredays = 10;

/* visited status of photos */
var jsphotovisited = new Array();

/* handle of help window */
var jsphotohelpwin = null;

/* first part of image title in index and single-image pages */
var jsphotopagehead = "Imagen";
var jsphotoindexhead = "Imágenes";

/* caption & hint of prev and next buttons in single-image page */
var jsphotoprevtext = "&lt;";
var jsphotonexttext = "&gt;";
var jsphotoprevhint = "Imagen anterior.";
var jsphotonexthint = "Imagen siguiente.";

/* caption & hint of prev and next buttons in index page */
var jsphotoprevindextext = "&lt;";
var jsphotonextindextext = "&gt;";
var jsphotoprevindexhint = "Página anterior.";
var jsphotonextindexhint = "Página siguiente.";

/* hint texts for moving between tabs */
var jsphototoindexhint  = "Cerrar imagen y retornar a la página índice.";
var jsphototosinglehint = "Agrandar esta imagen";

/* return to index button */
var jsphotoclosetext = "X";
var jsphotoclosehint = "Cerrar imagen y retornar a la página índice.";

/* help button */
var jsphotohelpetext = "?";
var jsphotohelphint  = "Mostrar ayuda de como usar la galería de imágenes.";

/* help */
var jsphotohelptitle = "Uso de la galería de imágenes";
var jsphotohelptext = "" +
"<p>La página índice muestra una vista preliminar de la galería de imágenes.  " +
"Dependiendo del número de imágenes en la galería, puede haber varios indices "+
"de página. Presione la flecha ubicada en la barra del título para cambiar " +
"entre índices de página.</p>"+
"<p>Haga clic en una imagen para ver esa imagen en particular en tamaño grande. " +
"Al ver la imagen  tamaño grande, use los botones en la barra de título para " +
"moverse rápidamente entre las imágenes del álbum. Para volver al índice de la " +
"página, haga clic en la [X] ubicada en la esquina superior de la barra de titulo. " +
"También puede devolver al índice haciendo clic en la imagen grande. " +
"</p>";
var jsphotohelpclose = "[Cerrar la ventana]";

/* style sheet for help (empty = none) */
var jsphotohelpstylefile = "";

/* max thumbnail width & height */
var jsphotothumbsmaxw = 100;
var jsphotothumbsmaxh = 75;

/* max image size (must not be zero) */
var jsphotomaxw;
var jsphotomaxh;
if (jsphotowidth > 850) {
  /* high-res */
  jsphotomaxw = 935;
  jsphotomaxh = 635;
} else if (jsphotowidth > 700) {
  /* med-resolution */
  jsphotomaxw = 740;
  jsphotomaxh = 420;
} else {
  /* low-resolution */
  jsphotomaxw = 535;
  jsphotomaxh = 330;
}

/* document onload handler */
var jsphotoonload = "";

/* figure out the name of the css file to use */
var jsphotocss;
if (jsphotowidth > 850) { 
  jsphotocss = "normal.css"; 
} else if (jsphotowidth > 700) { 
  jsphotocss = "small.css"; 
} else { 
  jsphotocss = "tiny.css"; 
}



/*
 * Insert HTML code for showing a javascript photo book.
 *
 * The html-page is divided into two sections of which only one is visible
 * at the moment.  The first section contains thumbnail images, and by
 * clicking on an image shows brings in the image in larger size.
 *
 * Note that links cannot have href specifier without on-click returning
 * false or otherwise browsers chokes on links.  Initially <a href="">'s 
 * may seem to work, but if the images take a while to load, browsers fails 
 * to properly switch images after selecting a new one.  The problem is 
 * fixed by ensuring that on-click handler returns false.
 */
function jsphoto() {
  var x, y, i, img;

  /* currently visible ta */
  jsphotocurtab = 1;

  /* compute the number of images in the photo album */
  jsphotocount = Math.floor((jsphotoalbum.length)/4);

  /* read cookie which tells us the images the user has already seen */
  jsphotoreadcookie();

  document.write("<div align=\"center\">");
  document.write("<a name=\"jsphotoalbum\" id=\"jsphotoalbum\">");

  /*** index page ***/
  document.write("<p id=\"jsphototab1\">");
  document.write("<table border=\"0\" class=\"jsphoto\"");
  document.write(" cellpadding=\"0\" cellspacing=\"0\">");

  /* header row */
  document.write(
      "<tr valign=\"middle\" align=\"center\">" +
      "<td class=\"jsphototitlerow\">" +
      "<table width=\"100%\" border=\"0\"" +
      " cellpadding=\"0\" cellspacing=\"0\">" +
      "<tr>");

  /* prev button */
  document.write(
      "<td class=\"jsphototitlerow\">" +
      "<input type=\"button\" value=\"" + jsphotoprevindextext + "\"" +
      " onclick=\"jsphotoprevthumbs();\" id=\"jsphotoprevthumbs\"" + 
      " class=\"jsphotobutton\"" +
      " title=\""+jsphotoprevindexhint+"\" disabled />" +
      "</td>");

  /* page title */
  document.write(
      "<td class=\"jsphototitlerow\"\">" +
      "<input type=\"text\" id=\"jsphotoindextitle\"" +
      " value=\"" + jsphotoindextitle() + "\"" +
      " class=\"jsphototitle\" readonly />&nbsp;" +
      "</td>");

  /* forward button */
  document.write(
      "<td class=\"jsphototitlerow\">" +
      "<input type=\"button\" value=\""+jsphotonextindextext+ "\"" + 
      " onclick=\"jsphotonextthumbs();\" id=\"jsphotonextthumbs\"" + 
      " class=\"jsphotobutton\" title=\""+jsphotonextindexhint+"\" />" +
      "</td>");

  /* help */
  document.write(
      "<td class=\"jsphototitlerow\">" + 
      "<input type=\"button\" value=\"" + jsphotohelpetext + "\"" +
      " onclick=\"jsphotohelp();\"" +
      " class=\"jsphotobutton\" title=\"" + jsphotohelphint + "\" />" + 
      "</td>");

  document.write("</tr></table>");
  document.write("</td></tr>");

  /*  Thumbnails */
  document.write("<tr><td>");
  document.write("<table border=\"0\" class=\"jsphotothumbs\"");
  document.write(" cellpadding=\"0\" cellspacing=\"0\">");
  img = 0;
  for (y = 0; y < jsphotothumbsy; y++) {
    document.write("<tr valign=\"top\">");
    for (x = 0; x < jsphotothumbsx; x++, img++) {
      document.write(
          "<td align=\"center\" valign=\"top\">" +
          "<table border=\"0\" class=\"jsphotothumbbox\"" +
          " cellpadding=\"0\" cellspacing=\"0\">");

      /* thumbnail image */
      i = "jsphotothumb_" + x + "_" + y
      document.write(
          "<tr><td align=\"center\" valign=\"top\">" + 
          "<a href=\"" + jsphotosrc(img) + "\""+
          " id=\"" + i + "_link\" "+
          " class=\"" + 
            (jsphotovisited[img] ? "jsphotovisited" : "jsphotolink") + "\"" +
          " onclick=\"jsphotothumbselect("+x+","+y+");return(false);\">" +
          "<img class=\"jsphotothumbnail\" id=\"" + i + "_img\"" +
          " title=\"" + jsphototosinglehint + "\"" +
          (img<jsphotocount ? " src=\"" + jsphotothumbsrc(img) + "\"" : "")+
          " alt=\"[image]\">" +
          "</a><br>");

      /* picture title (be sure to set title to empty if no image) */
      document.write(
          "<font id=\"" + i + "_title\" class=\"jsphotothumbtitle\">"+
          (img<jsphotocount ? jsphotoalbum[img*4+2] : "") +
          "</font>");

      document.write("</td></tr></table></td>");
    }
    document.write("</tr>");
  }
  document.write("</table>");
  document.write("</td></tr>");

  document.write("</table>");
  document.write("</p>");

  /*** single image mode ***/
  document.write("<p id=\"jsphototab2\" class=\"jsphotohidden\">");
  document.write("<table border=\"0\" class=\"jsphoto\"");
  document.write(" cellpadding=\"0\" cellspacing=\"0\">");

  /* header row */
  document.write(
      "<tr valign=\"middle\">" + 
      "<td class=\"jsphototitlerow\" align=\"center\">" + 
      "<table width=\"100%\" border=\"0\"" +
      " cellpadding=\"0\" cellspacing=\"0\">" +
      "<tr>");

  /* prev button */
  document.write(
      "<td class=\"jsphototitlerow\">" + 
      "<input type=\"button\" value=\"" + jsphotoprevtext + "\"" + 
      " onclick=\"jsphotoprev();\" id=\"jsphotoprev\"" + 
      " class=\"jsphotobutton\" title=\"" +jsphotoprevhint+ "\" />" + 
      "</td>");

  /* image number and title */
  document.write(
      "<td class=\"jsphototitlerow\">" +
      "<input type=\"text\" id=\"jsphototitle\"" +
      " class=\"jsphototitle\" readonly />&nbsp;" + 
      "</td>");

  /* forward button */
  document.write(
      "<td class=\"jsphototitlerow\">" + 
      "<input type=\"button\" value=\"" + jsphotonexttext + "\"" +
      " onclick=\"jsphotonext();\" id=\"jsphotonext\"" +
      " class=\"jsphotobutton\" title=\"" +jsphotonexthint+ "\" />" + 
      "</td>");

  /* back to index */
  document.write(
      "<td class=\"jsphototitlerow\">" +
      "<input type=\"button\" value=\"" + jsphotoclosetext + "\"" + 
      " onclick=\"jsphotoindex();\"" + 
      " class=\"jsphotobutton\" title=\"" + jsphotoclosehint + "\" />" +
      "</td>");

  document.write("</tr></table>");
  document.write("</td></tr>");

  /* large image */
  document.write(
      "<tr><td>" + 
      "<div align=\"center\" >" + 
      "<table border=\"0\" class=\"jsphotosingle\"" +
      " cellpadding=\"0\" cellspacing=\"0\">" +
      "<tr valign=\"middle\"><td align=\"center\">" +
      "<a onclick=\"jsphotoindex();return(false);\"" +
      " href=\"" + location.href + "\" class=\"jsphotovisited\">" +
      "<img src=\"\" name=\"jsphotolarge\" class=\"jsphotolarge\"" +
      " title=\"" + jsphototoindexhint + "\"" +
      " alt=\"[image]\">" +
      "</a>" +
      "</td></tr>" +
      "</table>" +
      "</div>" +
      "</td></tr>");

  document.write("</table></p></div>");

  /* 
   * Prepare to fix images in the index page.  This is mostly to fix bugs
   * in Mozilla based browsers those do not seem to fix the thumbnails
   * when loading the page for the very first time.  (On-load handlers do
   * not seem to be called.)  To fix that, we overload the onload handler 
   * for the window, fix the sizes after the document has loaded, and then
   * call the previous handler.
   */
  jsphotoonload = window.onload;
  window.onload = jsphotoindex;

  /*
   * Check image status every now and then.  This fixes some display
   * problems at least on Opera.
   */
  window.setInterval("jsphotoonloadfallback()", 1000);
}


/*
 * Some browsers fail to call on-load function when loading images.  To fix 
 * the issue, the function below is called from timer to check if an image 
 * is loaded without calling on-load, and to invoke on-load handler if needed.
 */
function jsphotoonloadfallback() {
  if (jsphotoloading >= 0) {
    /* an image being loaded */
    if (jsphotoimages[jsphotoloading].complete) {
      /* load complete without calling on-load */
      jsphotodelayedload();
    }
  }
}


/*
 * Move the browser view to show the full image/index page.  It would be best
 * to scroll the window to proper position with javascript, but Opera does
 * not have what it takes to find out the exact position of the jsphotoalbum 
 * anchor.
 */
function jsphotoshow() {
  /* 
   * Scroll window to show the jsphotoalbum anchor.  Opera 7.51 is a stupid 
   * browser, and fills the browser history with meaningless links because of 
   * this, but there is nothing we can do about it.  Replacing the address does
   * not work (browser jumps to the beginning of the page instead of the 
   * anchor), and it is not possible to find the pixel location of the achor 
   * so that we could use scroll the screen with javascript. 
   */
  location.hash = "jsphotoalbum";
}


/*
 * Give url of ith photo.
 */
function jsphotosrc(i) {
  if (jsphotodir != "") {
    return jsphotodir + "/" + jsphotoalbum[i*4+1];
  } else {
    /* absolute path */
    return jsphotoalbum[i*4+1];
  }
}


/*
 * Give url of ith thumbnail image.
 */
function jsphotothumbsrc(i) {
  if (jsphotodir != "") {
    return jsphotodir + "/" + jsphotoalbum[i*4];
  } else {
    /* absolute path */
    return jsphotoalbum[i*4];
  }
}


/*
 * Select thumbnail, and view the corresponding image in large size.
 */
function jsphotothumbselect(x,y) {
  var thumbs, img;

  /* compute the number of selected image */
  thumbs = jsphotothumbsx * jsphotothumbsy;
  img = Math.floor(jsphotocur / thumbs) * thumbs + x + y * jsphotothumbsx;

  /* is there an image below the cursor? */
  if (img < jsphotocount) {
    /* yes, load the selected image into view */
    jsphotoenlarge(img);

    /* switch to single-image mode */
    jsphotosettab(2);
  }
}


/*
 * Load all thumbnails to the index page.  The function is called after
 * the page has been completely loaded to fix bugs in Mozilla based 
 * browsers.
 */
function jsphotoindex() {
  var thumbs, img, f, x, y;

  /* ensure that we are looking at the index page */
  jsphotosettab(1);

  /* compute the number of first image */
  thumbs = jsphotothumbsx * jsphotothumbsy;
  img = Math.floor(jsphotocur / thumbs) * thumbs;

  /* disable forward button if necessary */
  f = document.getElementById("jsphotonextthumbs");
  if (f) {
    if (img + thumbs < jsphotocount) {
      f.disabled = false;
    } else {
      f.disabled = true;
    }
  }

  /* disable backward button if necessary */
  f = document.getElementById("jsphotoprevthumbs");
  if (f) {
    if (img >= thumbs) {
      f.disabled = false;
    } else {
      f.disabled = true;
    }
  }

  /* set page title */
  jsphotoindextitle();

  /* load the thumbnails to the page */
  for (y = 0; y < jsphotothumbsy; y++) {
    for (x = 0; x < jsphotothumbsx; x++, img++) {
      jsphotosetthumb(x,y,img);
    }
  }

  /* invoke previous onload handler */
  window.onload = jsphotoonload;
  if (jsphotoonload != null) {
    jsphotoonload();
  }
  jsphotoonload = null;
}


/*
 * Set title of index page.
 */
function jsphotoindextitle() {
  var f, j, thumbs, img, title;
  
  /* number of images in page */
  thumbs = jsphotothumbsx * jsphotothumbsy;

  /* index of the very first image */
  img = Math.floor(jsphotocur / thumbs) * thumbs;

  /* make up the title */
  j = (img+1) + "-" + 
      (img+thumbs > jsphotocount ? jsphotocount : img+thumbs) + 
      "/" + jsphotocount;
  if (jsphototitle != "") {
    title = jsphotoindexhead + " " + j + ": " + jsphototitle;
  } else {
    title = jsphotoindexhead + " " + j;
  }

  /* set title */
  f = document.getElementById("jsphotoindextitle");
  if (f) {
    f.value = title;
  }

  return title;
}


/*
 * Show thumbnail at (x,y).  The functions loads images as needed, sets 
 * titles and hide unused images.
 */
function jsphotosetthumb(x,y,img) {
  var i, f1, f2, f3;

  /* construct name of the identifier in the html page */ 
  i = "jsphotothumb_" + x + "_" + y;

  /* find image, title and link */
  f1 = document.getElementById(i + "_img");
  f2 = document.getElementById(i + "_title");
  f3 = document.getElementById(i + "_link");

  /* does the image exist? */
  if (img < jsphotocount) {
    /* start loading image */
    jsphotothumbload(f1,x,y,img);
    f2.innerHTML = jsphotoalbum[img*4+2];

    /* color visited links with different style */
    if (jsphotovisited[img]) {
      f3.className = "jsphotovisited";
    } else {
      f3.className = "jsphotolink";
    }
    f3.href = jsphotosrc(img);
  } else {
    /* the image does not exist */
    f2.innerHTML = "";
    f3.className = "jsphotohidden";
  }
}


/*
 * Load ith thumbnail image in to an object, and resize the image after 
 * loading.
 */
function jsphotothumbload(f,x,y,i) {
  /* load thumbnail image when needed for the first time */
  if (jsphotothumbs[i] == null) {
    /* create image */
    jsphotothumbs[i] = new Image();

    /* resize corresponding image when loaded */
    jsphotothumbs[i].onload = "jsphotosizethumb("+x+","+y+","+i+");"

    /* start loading the image */
    jsphotothumbs[i].src = jsphotothumbsrc(i);
  }

  /* let the image show */
  f.onload = "jsphotosizethumb("+x+","+y+","+i+");"
  f.src = jsphotothumbs[i].src

  /* fix thumbnail size (if loaded already) */
  jsphotosizethumb(x,y,i);
}


/*
 * Set size of thumbnail image.  The function is typically invoked after 
 * loading an image.
 */
function jsphotosizethumb(x,y,img) {
  var i, f1, d1, d2, w1, h1;

  /* construct name of the identifier in the html page */ 
  i = "jsphotothumb_" + x + "_" + y;

  /* find image */
  if (img < jsphotocount  &&  jsphotothumbs[img] != null) {
    /* native width and height of the image */
    w1 = jsphotothumbs[img].width;
    h1 = jsphotothumbs[img].height;

    if (h1 > 0) {
      /* enlarge or shrink the image */
      d1 = w1 / h1;
      d2 = jsphotothumbsmaxw / jsphotothumbsmaxh;
      if (d1 < d2) {
        /* img1 is taller than img2 */
        h1 = jsphotothumbsmaxh;
        w1 = h1 * d1;
      } else {
        /* img1 is wider than img2 */
        w1 = jsphotothumbsmaxw;
        h1 = w1 / d1;
      }

      /* set new image size */
      f1 = document.getElementById(i + "_img");
      f1.width  = w1;
      f1.height = h1;
    }
  }
}


/*
 * Start preloading the very next big image once an image has been loaded.  
 * Only a few images are preloaded at a time to keep the browser fully 
 * functional all the time.
 */
function jsphotopreload() {
  var i;

  if (jsphotoloading < 0) {
    /* load images ahead of the current image */
    for(i=jsphotocur; i<jsphotocount && i<=jsphotocur+jsphotopreloadcount;i++){
      if (jsphotoimages[i] == null) {
        jsphotoload(i);
        return;
      }
    }

    /* load images behind current image */
    for (i = jsphotocur-1; i>=0 && i >= jsphotocur-jsphotopreloadcount; --i) {
      if (jsphotoimages[i] == null) {
        jsphotoload(i);
        return;
      }
    }
  }
}


/*
 * Finished loading an image.  Show the image if it is the current one, and
 * start preloading the next image.
 */
function jsphotodelayedload() {
  if (jsphotoloading >= 0) {
    jsphotoloaded[jsphotoloading] = true;

    /* show current image */
    if (jsphotoloading == jsphotocur) {
      jsphotoimgsize();
      document.images["jsphotolarge"].src = jsphotoimages[jsphotocur].src;
    }

    /* not loading an image */
    jsphotoloading = -1;

    /* start preloading images */
    if (!jsphotoloaded[jsphotocur]) {
      /* 
       * Loading of the current visible image was postponed due to background
       * load - execute the postponed load to bring the image to display.
       */
      jsphotoload(jsphotocur);
    } else {
      jsphotopreload();
    }
  }
}


/*
 * Handle aborted image loads.
 */
function jsphotoabort() {
  if (jsphotoloading >= 0) {
    /* check if image is actually loaded to circumvent bugs in Opera */
    if (jsphotoimages[jsphotoloading].complete) {
      /* 
       * The image has been loaded but the on-load function has not been
       * called.  This is a bug in Opera 7.50.
       */
      jsphotodelayedload();
    } else {
      /* the image has not been loaded */
      with(Image) delete jsphotoimages[jsphotoloading];
      jsphotoimages[jsphotoloading] = null;
      jsphotoloaded[jsphotoloading] = false;
    }

    /* not loading an image anymore */
    jsphotoloading = -1;
  }
}


/*
 * Start loading ith image into memory.  This is used with the single-image 
 * display.
 */
function jsphotoload(i) {
  var src;

  /*
   * Only load an image if the image is not loaded yet, and not loading an 
   * image right now.
   */
  if (!jsphotoloaded[i]  &&  jsphotoloading < 0) {
    /* create new hidden image */
    jsphotoimages[i] = new Image();

    /* 
     * Set handler to be called after the image has been loaded.  This must
     * be specified before setting the src property since otherwise the
     * system could possibly load the image before we have set the handler.
     */
    jsphotoimages[i].onload = jsphotodelayedload;

    /*
     * Set handler to be called when user aborts the load.  Aborting image
     * loads is quite common here because we load images on the background,
     * and many browsers stop loading the image when the user clicks on a 
     * link.
     */
    jsphotoimages[i].onabort = jsphotoabort;
    jsphotoimages[i].onerror = jsphotoabort;

    /* specify the image to load */
    jsphotoloading = i;
    if (jsphotodir != "") {
      src = jsphotodir + "/" + jsphotoalbum[i*4+1];
    } else {
      /* each image has absolute path */
      src = jsphotoalbum[i*4+1];
    }
    jsphotoimages[i].src = src;
  }
}


/*
 * Enlarge or shrink the large image to match the window size.
 */
function jsphotoimgsize() {
  /* native width and height of the image */
  var w1 = jsphotoimages[jsphotocur].width;
  var h1 = jsphotoimages[jsphotocur].height;

  if (h1 > 0) {
    /* enlarge or shrink the image */
    var d1 = w1 / h1;
    var d2 = jsphotomaxw / jsphotomaxh;
    if (d1 < d2) {
      /* img1 is taller than img2 */
      h1 = jsphotomaxh;
      w1 = h1 * d1;
    } else {
      /* img1 is wider than img2 */
      w1 = jsphotomaxw;
      h1 = w1 / d1;
    }

    /* set new image size */
    document.images["jsphotolarge"].width  = w1;
    document.images["jsphotolarge"].height = h1;
  }
}


/*
 * Set ith image into display.  This is used with the single-image 
 * display mode.
 */
function jsphotoenlarge(i) {
  var f, j;

  /* remember the image */
  jsphotocur = i;

  /* ensure that image is loaded */
  if (!jsphotoloaded[jsphotocur]) {
    /* start loading the image */
    jsphotoload(jsphotocur);
  } else {
    /* set image size */
    jsphotoimgsize();

    /* display the image on its currently loaded state */
    document.images["jsphotolarge"].src = jsphotoimages[jsphotocur].src;

    /* image already loaded, see a few more images could be preloaded */
    jsphotopreload();
  }

  /*
   * Opera does not invoke on-load function if the image is found from
   * cache.  Display the partially loaded image so that the user sees
   * the image although we never see it loaded.  This sometimes makes an
   * old image flash on screen.  However, missing this makes the coarse
   * image stick to the screen for long time.
   */
  if (jsphotoopera()  &&  jsphotoimages[jsphotocur] != null) {
    document.images["jsphotolarge"].src = jsphotoimages[jsphotocur].src;
  }

  /* disable forward button if necessary */
  f = document.getElementById("jsphotonext");
  if (f) {
    if (jsphotocur >= jsphotocount-1) {
      f.disabled = true;
    } else {
      f.disabled = false;
    }
  }

  /* disable backward button if necessary */
  f = document.getElementById("jsphotoprev");
  if (f) {
    if (jsphotocur <= 0) {
      f.disabled = true;
    } else {
      f.disabled = false;
    }
  }

  /* 
   * Set page title.  This does not seem to work on Opera 7.23 unless 
   * the user is already viewing a large image.  The title does not change
   * when invoked from index page.
   */
  f = document.getElementById("jsphototitle");
  if (f) {
    j = jsphotopagehead + " " + (i+1)+"/"+jsphotocount;
    if (jsphotoalbum[jsphotocur*4+2] == "") {
      /* no custom title */
      if (jsphototitle != "") {
        f.value = j +  ": " + jsphototitle;
      } else {
        f.value = j;
      }
    } else {  
      /* has a custom title */
      f.value = j + ": "+jsphotoalbum[jsphotocur*4+2];
    }
  }
 
  /* mark the image visited (lets hope the image still loads) */
  jsphotomarkvisited(i);
}


/*
 * Set ith tab visible.  Index page is in first tab, the details in second 
 * tab.
 */
function jsphotosettab(i) {
  var t1, t2;

  if (jsphotocurtab != i) {
    /* showing a different page */
    t1 = document.getElementById("jsphototab1");
    t2 = document.getElementById("jsphototab2");
    if (i == 1) {
      /* show the index page */
      t1.className = "jsphotovisible";
      t2.className = "jsphotohidden";
    } else {
      /* show the big image */
      t1.className = "jsphotohidden";
      t2.className = "jsphotovisible";
    }

    /* move the page to view */
    jsphotoshow();

    /* remember the current page */
    jsphotocurtab = i;
  }
}


/* 
 * Show the very next image (on the single-image page).
 */
function jsphotonext() {
  if (jsphotocur < jsphotocount-1) {
    /* switch to next image */
    jsphotoenlarge(jsphotocur + 1);
  }
}


/* 
 * Show the previous image on the single-image page.
 */
function jsphotoprev() {
  if (jsphotocur > 0) {
    /* switch to previous image */
    jsphotoenlarge(jsphotocur - 1);
  }
}


/* 
 * Show the very next index page.
 */
function jsphotonextthumbs() {
  var thumbs, img;

  /* compute the number of first image in page */
  thumbs = jsphotothumbsx * jsphotothumbsy;
  img = Math.floor(jsphotocur / thumbs) * thumbs;

  if (img + thumbs < jsphotocount) {
    /* switch to next page */
    jsphotocur = img + thumbs;
    jsphotoindex();
  }
}


/* 
 * Show the previous index page.
 */
function jsphotoprevthumbs() {
  var thumbs, img;

  /* compute the number of first image in page */
  thumbs = jsphotothumbsx * jsphotothumbsy;
  img = Math.floor(jsphotocur / thumbs) * thumbs;

  if (img >= thumbs) {
    /* switch to previous image */
    jsphotocur = img - thumbs;
    jsphotoindex();
  }
}


/*
 * Check if the user agent is Opera.
 */
function jsphotoopera() {
  if (navigator.userAgent.indexOf("Opera") != -1) {
    return true;
  } else {
    return false;
  }
}


/*
 * Get cookie for current photo gallery, and mark visited pages in 
 * jsphotovisited array.
 */
function jsphotoreadcookie() {
  var i, j, visited, range, start, end;

  /* reset visited state */
  for (i = 0; i < jsphotocount; i++) {
    jsphotovisited[i] = false;
  }

  /* read visited states from a cookie */
  if (jsphotocookiename != ""  &&  document.cookie) {
    /* loop through cookies */
    i = 0;
    do{
      /* check name of the cookie */
      j = i + jsphotocookiename.length;
      if (document.cookie.substring(i,j) == jsphotocookiename) {
        /* start of cookie data */
        i = j;

        /* get index of last character of cookie data */
        j = document.cookie.indexOf(";", j);
        if (j < 0) j = document.cookie.length;

        /* get cookie data */
        visited = unescape(document.cookie.substring(i+1, j));

        /* extract ranges */
        i = 0;
        do{
          /* find end of range */
          j = visited.indexOf("/", i);
          if (j < 0) j = visited.length;

          /* extract range of visited pages */
          range = visited.substring(i,j);
          i = j + 1;

          /* modify the state of images specified by range */
          j = range.indexOf("-");
          if (j >= 0) {
            /* range of pictures */
            start = parseInt(range.substring(0,j));
            end   = parseInt(range.substring(j+1,range.length));

            /* mark range */
            if (start < 0) start = 0;
            if (end > jsphotocount) end = jsphotocount;
            while (start <= end) {
              jsphotovisited[start] = true;
              ++start;
            }
          } else { 
            /* single picture */
            j = parseInt(range);
            if (0 <= j  &&  j < jsphotocount) {
              jsphotovisited[j] = true;
            }
          }

        }while (i < visited.length);
        break;
      }
      
      /* find next cookie */
      i = document.cookie.indexOf(" ", i) + 1;
    }while (i != 0);
  }
}


/*
 * Mark an image visited, and save the state of all visited images to a 
 * cookie so that we can tell the user which images he has already seen. 
 */
function jsphotomarkvisited(img) {
  var visited, i, j, changed;

  /* is the state changed? */
  changed = false;
  if (jsphotovisited[img] != true) changed = true;

  /* mark an image visited */
  jsphotovisited[img] = true;

  /* save the state of visited images to cookie */
  if (jsphotocookiename != ""  &&  changed) { 
    /* skip un-seen pictures at the beginning */
    i = 0;
    while (i < jsphotocount  &&  !jsphotovisited[i]) {
      i++;
    }

    /* create list of visited pages */
    visited = "";
    while (i < jsphotocount) {
      /* find out length of consecutive range of visited pages */
      j = i;
      do{
        i++;
      }while (i < jsphotocount  &&  jsphotovisited[i]);

      /* append pages to list */
      if (visited != "") visited = visited + "/";
      if (i-j != 1) {
        /* range of images visited */
        visited = visited + j + "-" + (i-1);
      } else {
        /* single image visited */
        visited = visited + j;
      }

      /* skip other un-seen pictures */
      while (i < jsphotocount  &&  !jsphotovisited[i]) {
        i++;
      }
    }

    /* compute expiration date (in milliseconds after January 1, 1970) */
    var expires = new Date();
    expires.setTime(expires.getTime() + (jsphotoexpiredays*24*60*60*1000));

    /* set cookie */
    document.cookie = 
        jsphotocookiename + "=" + escape(visited) + "; " +
        "expires=" + expires.toGMTString();
  }
}


/*
 * Open help window.
 */
function jsphotohelp() {
  /* open popup window */
  jsphotohelpwin = window.open("","displayWindow",
      "toolbar=0,menubar=no,scrollbars=no,status=no,width=450,height=400");

  /* write document */
  jsphotohelpwin.document.write(
      "<html>" +
      "<head><title>" + jsphotohelptitle + "</title>");

  /* with custom help file */
  if (jsphotohelpstylefile != "") {
    jsphotohelpwin.document.write(
        "<link rel=\"stylesheet\" href=\"" + jsphotohelpstylefile + "\"" +
        " type=\"text/css\" media=\"screen\" />");
  }

  /* and the message */
  jsphotohelpwin.document.write(
      "</head>" +
      "<body bgcolor=\"#bbbec7\">" + 
      "<div align=\"center\"><h1>" + jsphotohelptitle + "</h1></div>" + 
      jsphotohelptext + 
      "<hr>" +
      "<div align=\"center\">" +
      "<a href=\"" + location.href + "\""+
      " onclick=\"self.close();\">" +
      jsphotohelpclose + "</a></div>" +
      "</body>" +
      "</html>");

  jsphotohelpwin.document.close();
 
  /* try to take focus */
  if (jsphotohelpwin.focus) jsphotohelpwin.focus();
}
