/**  MuseZoom 0.9.7 beta**  This script enables web browsers to navigate high-resolution images saved as component*  JPEGs following certain arbitrary conventions for resolution and relative coordinates.**  MuseZoom 0.9.7--with its accompanying files--works properly in NN4 and IE5 for Macintosh and (as*  far as I know, but with less testing) Windows. Some functions work in NN6 for Mac. This development*  version has a few unused variables, redundant calls, and brute-force functions yet to clean up.**  Truncated revision history:*  *  Version 0.9 worked properly in certain core browser environments, with certain inefficiencies.*  0.9.1 integrated into the main .js file what was previously a separate .js file to set metadata*  variables; this was a means of trying to address a timing issue which would cause Netscape 4 for Mac*  sometimes to call navigation functions with as yet undefined View attributes; for the same reason,*  that and later versions force makeView() if nowView is undefined in zoomIn(). This looks redundant*  with zoomIn()'s "preloaded" conditional, but nonetheless it seems to help N4 load the page.*  0.9.2 fixed a filename concatenation error that had no visible effect but hit server with bad requests.*  0.9.3 fixed an x-axis offset algorithm error in loadZoomIns(); in more attempts to work around N4*  loading issues, it called setMeta() in the page's head, adjusted state-testing conditionals, and it*  added function zoomCatcher() to the html page.*  0.9.4 added function loadCatcher() to try to avoid a possible initialization timing issue.*  0.9.5 fixed a newly found bug that broke newCenter() in IE5 if the page had been scrolled.*  0.9.6 added detection and warning for non-Mac browsers pending two bug fixes for Windows.*  0.9.7 added state testing to avoid calling undefined variables when preloading images, and*  for N4/Windows it fixed (I hope!) newCenter() as well as a layout issue (in HTML and CSS).*  0.9.8, if it comes to pass, will fix newCenter() in N6's DOM without breaking in IE5.**  Script author: Rob Lancefield <rlancefield at wesleyan.edu>*  Source code copyright (c) 2001 Davison Art Center, Wesleyan University*  Made using BBEdit for the DAC site at http://www.wesleyan.edu/dac/home.html**/// INITIALIZATION -- (check through for all vars not used across functions and reduce their scope)if (document.images) {  var preloaded = false;  // this remains false until set to true at end of makeView();  var metaloaded = false; // this remains false until set to true at end of setMeta();  var close_p = "<\/p>";  // set browser-detection variables for branching functions and for incompatibility warning  var net4 = false;  var net6 = false;  var mie5 = false;  var naVersion = navigator.appVersion;  var v4up = (naVersion.indexOf("4.") != -1);  var v5up = (naVersion.indexOf("5.") != -1);  if (navigator.appName == "Netscape") {     net4 = ((v4up) ? true : false);    net6 = ((v5up) ? true : false);  }  if ((navigator.appName == "Microsoft Internet Explorer") && v5up) {    mie5  = true;    var e = "";   // this prevents IE5 errors when calling newCenter() in its N6-compatible form as of v0.9.6   }    var mac = false;  if (naVersion.indexOf("Mac") >= 0) {    mac = true;  }  var warn = (mac == false) || ((net4 == false) && (net6 == false) && (mie5 == false));  // set variables for relative paths to directories housing image component files, navigation graphics, and metadata  var fileBase = "../../imag/";  // top directory of image directories based on accession numbers  var naviBase = "../navi/";     // directory housing all GIF images for navigation graphics  var metaBase = "../meta/";     // not yet used; directory to house XML-tagged metadata files  // preload navigation graphics  document.navRightDead = new Image();     document.navRightDead.src     = naviBase + "dead_vertical.gif";  document.navRightLive = new Image();     document.navRightLive.src     = naviBase + "right_live.gif";  document.navRightPres = new Image();     document.navRightPres.src     = naviBase + "right_pressed.gif";  document.navDownRightDead = new Image(); document.navDownRightDead.src = naviBase + "dead_corner.gif";  document.navDownRightLive = new Image(); document.navDownRightLive.src = naviBase + "downright_live.gif";  document.navDownRightPres = new Image(); document.navDownRightPres.src = naviBase + "downright_pressed.gif";  document.navDownDead = new Image();      document.navDownDead.src      = naviBase + "dead_horizontal.gif";  document.navDownLive = new Image();      document.navDownLive.src      = naviBase + "down_live.gif";  document.navDownPres = new Image();      document.navDownPres.src      = naviBase + "down_pressed.gif";  document.navDownLeftDead = new Image();  document.navDownLeftDead.src  = naviBase + "dead_corner.gif";  document.navDownLeftLive = new Image();  document.navDownLeftLive.src  = naviBase + "downleft_live.gif";  document.navDownLeftPres = new Image();  document.navDownLeftPres.src  = naviBase + "downleft_pressed.gif";  document.navLeftDead = new Image();      document.navLeftDead.src      = naviBase + "dead_vertical.gif";  document.navLeftLive = new Image();      document.navLeftLive.src      = naviBase + "left_live.gif";  document.navLeftPres = new Image();      document.navLeftPres.src      = naviBase + "left_pressed.gif";  document.navUpLeftDead = new Image();    document.navUpLeftDead.src    = naviBase + "dead_corner.gif";  document.navUpLeftLive = new Image();    document.navUpLeftLive.src    = naviBase + "upleft_live.gif";  document.navUpLeftPres = new Image();    document.navUpLeftPres.src    = naviBase + "upleft_pressed.gif";  document.navUpDead = new Image();        document.navUpDead.src        = naviBase + "dead_horizontal.gif";  document.navUpLive = new Image();        document.navUpLive.src        = naviBase + "up_live.gif";  document.navUpPres = new Image();        document.navUpPres.src        = naviBase + "up_pressed.gif";  document.navUpRightDead = new Image();   document.navUpRightDead.src   = naviBase + "dead_corner.gif";  document.navUpRightLive = new Image();   document.navUpRightLive.src   = naviBase + "upright_live.gif";  document.navUpRightPres = new Image();   document.navUpRightPres.src   = naviBase + "upright_pressed.gif";  document.navPreviousLive = new Image();  document.navPreviousLive.src  = naviBase + "previous_live.gif";  document.navPreviousPres = new Image();  document.navPreviousPres.src  = naviBase + "previous_pressed.gif";  document.navPreviousGrey = new Image();  document.navPreviousGrey.src  = naviBase + "previous_greyed.gif";  document.navZoomOutLive  = new Image();  document.navZoomOutLive.src   = naviBase + "zoom_out_live.gif";  document.navZoomOutPres  = new Image();  document.navZoomOutPres.src   = naviBase + "zoom_out_pressed.gif";  document.navZoomOutGrey  = new Image();  document.navZoomOutGrey.src   = naviBase + "zoom_out_greyed.gif";  document.navFullViewLive = new Image();  document.navFullViewLive.src  = naviBase + "full_view_live.gif";  document.navFullViewPres = new Image();  document.navFullViewPres.src  = naviBase + "full_view_pressed.gif";  document.navFullViewGrey  = new Image(); document.navFullViewGrey.src  = naviBase + "full_view_greyed.gif";  // create navigation image variables  document.hotUpRight = new Image();  document.hotRight = new Image();  document.hotDownRight = new Image();  document.hotDown = new Image();  document.hotDownLeft = new Image();  document.hotLeft = new Image();  document.hotUpLeft = new Image();  document.hotUp = new Image();  document.hotPrevious = new Image();  document.hotZoomOut = new Image();  document.hotFullView = new Image();  document.hotPrevious.src = document.hotZoomOut.src = document.hotFullView.src = naviBase + "blank_18x128.gif";  imageUpRight1 = new Image();  imageRight1 = new Image();  imageDownRight1 = new Image();  imageDown1 = new Image();  imageDownLeft1 = new Image();  imageLeft1 = new Image();  imageUpLeft1 = new Image();  imageUp1 = new Image();  imageInUpRight1 = new Image();  imageInDownRight1 = new Image();  imageInDownLeft1 = new Image();  imageInUpLeft1 = new Image();  imageZoomOut1 = new Image();  // initialize arrays for image-specific x and y jumps; these will hold numbers of overlapping x and y  // segments at levels 3 through 5, derived from four square quadrants cut from each corner of level 2  // for simplified (and thus more easily automatible) image production and consistent navigation code.  var xJumps = new Array(true,0,0,0,0,1);  var yJumps = new Array(true,0,0,0,0,1);  // initialize array and array variables to hold view history  var pastViews = new Array();  pastViews[0] = new View();  var undefined; // holds undefined value to undefine pastViews values for push/pop emulation  var accessionNumber = "";  var sourceWidth = "";  var sourceHeight = "";  var xMax = 5;  var yMax = 5;    View();  var nowView = new View("",1,1,1,5,1,1,xJumps,yJumps);  var goView  = new View("",1,1,1,5,1,1,xJumps,yJumps);  // initialize other global variables  var metaText = "hey!"; // in process  var rightAble = false;  var downRightAble = false;  var downAble = false;  var downLeftAble = false;  var leftAble = false;  var upLeftAble = false;  var upAble = false;  var upRightAble = false;  var inLevel = "";  var inRight = "";  var inDown = "";  var inLeft = "";  var inUp = "";  var nextRight = "";  var nextDown = "";  var nextLeft = "";  var nextUp = "";  var lOutNext = "";  var xOutNext = "";  var yOutNext = "";  var base = "";  var aspectRatio = "";  var xClick = "";  var yClick = "";  var upEvent = "";  var loadingZoomIns   = false;  var loadingZoomOut   = false;  var loadingAdjacents = false;  // var buttonClock = "";  var statusUpLeft = "";  var statusUpRight = "";  var statusDownLeft = "";  var statusDownRight = "";  var net6SmallMap = "";  var net6MapClick = "";  // set up Netscape 4 event handling for newCenter() calls from small image map  if (net4) {    document.captureEvents(Event.MOUSEUP);    document.onmouseup = newCenter;  }}// FUNCTIONS// define View as a class of objects to be used for nowView, goView, and pastViews arrayfunction View(base,level,x,y,lMax,xMax,yMax,xJumps,yJumps,sourceWidth,sourceHeight) {  this.b = base;          // base as filepath from "../../" through accession number  this.l = level;         // zoom level as integer  this.x = x;             // x location as integer  this.y = y;             // y location as integer  this.lm = lMax;         // maximum level depth integer  this.xm = xMax;         // maximum x at current level  this.ym = yMax;         // maximum y at current level  this.xj = xJumps;       // xJumps array  this.yj = yJumps;       // yJumps array  this.xs = sourceWidth;  // pixel width of original source image  this.ys = sourceHeight; // pixel height of original source image}// eventually this could read and transform xml-tagged metadata; for now, it's hardcoded// with item-specific string and integer content in this file. In v0.9b, this function was// in a separate file; moved here to try to fix intermittent timing issues when N4/Mac loads.function setMeta() {  if (document.images) {    /*  tagged data as currently in xml file (not yet actually pulled into this script):      <object_metadata>        <object_accession_number>1949.D3.1</object_accession_number>        <object_agent type="creator">Albrecht D&uuml;rer (German, 1471-1528)</object_agent>        <object_title>Knight, Death and Devil</object_title>        <object_year>1513</object_year>        <object_medium>Engraving</object_medium>        <object_support>Laid paper</object_support>        <object_plate_height unit="mm">243</object_plate_height>        <object_plate_width unit="mm">186</object_plate_width>        <object_inscription>Signed in plate: monogram in tablet, lower left</object_inscription>        <object_references>Bartsch 98; Dodgson 70; Meder 74b; Panofsky 205; Strauss 71</object_references>        <object_credit_line>Gift of George W. Davison (B.A. Wesleyan 1892), 1949</object_credit_line>      </object_metadata>      <image_metadata>        <source_height_px>4580</source_height_px>        <source_width_px>3575</source_width_px>      </image_metadata>    */        // later build below into View objects as nowView.meta.creator etc. or concatenate as nowView.metaText?    sourceHeight = 4580; sourceWidth = 3575;  // pixel dimensions of master source image;    accessionNumber = '1949.D3.1';            // these first 3 vars are global, declared above    var close_para = "<\/p>"; // local close_p works around timing issue of global var close_p sometimes still undefined    var close_span = "<\/span>";        var creator = 'Albrecht D&uuml;rer (German, 1471-1528)';  // pre-processing note: HTML entity versus database high-ASCII    var title = 'Knight, Death and Devil';     var medium = 'Engraving';     var support = 'laid paper';                               // pre-processing note: char 0 dropped from database uppercase    var watermark = '';    var year = '1513';    var plateHeight = '243';     var plateWidth = '186';     var inscription = 'Signed in plate with monogram, lower left';     var references = 'Bartsch 98; Meder 74b; Strauss 71';     var creditLine = 'Gift of George W. Davison (B.A. Wesleyan 1892), 1949';    metaText = '<p class="mainmeta">' + '<span class="creator">' + creator + ": " + close_span + '<span class="title">' + title + close_span + close_para;        metaText += '<p class="submeta">' + medium;    if (support) {        metaText += ' on ' + support;    }    metaText += ", " + year + ". ";    if (watermark) {      metaText += 'Watermark: ' + watermark + ". ";    }        if (plateHeight && plateWidth) {      metaText += 'Plate ' + plateHeight + " x "+ plateWidth + " mm. " ;    }        if (inscription) {      metaText += inscription + ". ";    }     if (references) {      metaText += 'References: ' + references + ". ";    }    if (creditLine) {      metaText += creditLine + ". ";    }    metaText += 'DAC ' + accessionNumber + "." + close_para;        metaloaded = true;    return metaText;  }}// initialize current View with image-specific values in accessionNumber, sourceWidth, sourceHeightfunction makeView() {  if (document.images && metaloaded) {    nowView.xs = sourceWidth;    nowView.ys = sourceHeight;    aspectRatio = nowView.ys/nowView.xs;    var mainPath = fileBase;    var components = accessionNumber.split(".");    for (var c = 0; c < components.length; c++) {      mainPath += pad4(components[c]) + "/";    }    mainPath += accessionNumber.replace(/\./g,"-") + "_l1x01y01.jpg";    nowView.b = mainPath.substr(0,(mainPath.lastIndexOf("l")));    pastViews[0].l = nowView.l = Math.abs(mainPath.substr((mainPath.lastIndexOf("l")+1),1));    pastViews[0].x = nowView.x = Math.abs(mainPath.substr((mainPath.lastIndexOf("x")+1),2));    pastViews[0].y = nowView.y = Math.abs(mainPath.substr((mainPath.lastIndexOf("y")+1),2));    if ((aspectRatio > 1.1) && (aspectRatio < 1.4)) {  // aspect ratio of KDD test image is 1.28; the      for (var l = 3; l <= nowView.lm; l++) {          // arbitrary range here of 1.1-1.4 is entirely a        nowView.xj[l] = Math.floor(Math.pow(2,(l-3))); // guess that sets KDD's xj3=1, xj4=2, xj5=4, but        nowView.yj[l] = Math.floor(Math.pow(2,(l-5))); // it will need tweaking to handle general cases      }    }    setStatus(nowView);    preloaded = true;  }}// this N6 stuff doesn't work yet called as a function here or read in on load above  -- fix to handle DOM and eventsfunction setN6() {  if (net6) {    net6SmallMap = document.getElementById("smallMap1");    net6MapClick = net6SmallMap.addEventListener("click", newCenter, true);  }}// pad and trim accession number component values to zero-padded 4-digit strings for directory names in image file pathfunction pad4(component) {  var padLong = "000" + component;  return padLong.substr(padLong.length-4,4);}// pad and trim x and y values (stored as integers in View properties) to zero-padded 2-digit strings for image file namesfunction pad2(coordinate) {  var padLong = "0" + coordinate;  return padLong.substr(padLong.length-2,2);}// set global variables for limits of movement from a location, assuming square grids from corners from level 2 downfunction goAbles() {  nowView.xm = nowView.ym = Math.pow(2,(nowView.l-1));  rightAble = (nowView.x < nowView.xm);  downAble  = (nowView.y < nowView.ym);  leftAble  = (nowView.x > 1);  upAble    = (nowView.y > 1);    upRightAble   = (upAble   && rightAble);  downRightAble = (downAble && rightAble);  upLeftAble    = (upAble   && leftAble);  downLeftAble  = (downAble && leftAble);}// set status bar text based on mouse position over main view to explain effect of clicking at that locationfunction setStatus() {  if (nowView.l < nowView.lm) {    statusUpLeft    = "Zoom in to upper left quadrant";    statusUpRight   = "Zoom in to upper right quadrant";    statusDownLeft  = "Zoom in to lower left quadrant";    statusDownRight = "Zoom in to lower right quadrant";  }  else if (nowView.l == nowView.lm) {    statusUpLeft = statusUpRight = statusDownLeft = statusDownRight = "This view is at the highest resolution; it is impossible to zoom in further.";  }}// if navigation buttons and small map are useable, display them; otherwise hide or grey out as interface cuesfunction setNavigation() {  if (pastViews.length > 1) {    document.images['prevView'].src = document.navPreviousLive.src;  }  else {    document.images['prevView'].src = document.navPreviousGrey.src;  }  if (nowView.l > 1) {    document.images['zoomOut'].src   = document.navZoomOutLive.src;    document.images['fullView'].src  = document.navFullViewLive.src;    document.images['smallMapImageOne'].src = nowView.b + "smallmap.jpg";    document.images['mapNote'].src   = naviBase + "map_note_live.gif";  }  else {    document.images['zoomOut'].src   = document.navZoomOutGrey.src;    document.images['fullView'].src  = document.navFullViewGrey.src;    document.images['smallMapImageOne'].src = naviBase + "zoom_note.gif";    document.images['mapNote'].src   = naviBase + "blank_36x128.gif";  }}// set current framing navigation bars based on possible directions of movement; a more// concise refactoring with loop and arrays might crash into N4 cache bug, so keep as is.function setBars(nowView) {  if (preloaded) {    if (rightAble) {      document.images['navRight'].src = document.navRightLive.src;      document.hotRight.src = document.navRightPres.src;    }    else {      document.images['navRight'].src = document.navRightDead.src;      document.hotRight.src = document.navRightDead.src;    }    if (downRightAble) {      document.images['navDownRight'].src = document.navDownRightLive.src;      document.hotDownRight.src = document.navDownRightPres.src;    }    else {      document.images['navDownRight'].src = document.navDownRightDead.src;      document.hotDownRight.src = document.navDownRightDead.src;    }    if (downAble) {      document.images['navDown'].src = document.navDownLive.src;      document.hotDown.src = document.navDownPres.src;    }    else {      document.images['navDown'].src = document.navDownDead.src;      document.hotDown.src = document.navDownDead.src;    }    if (downLeftAble) {      document.images['navDownLeft'].src = document.navDownLeftLive.src;      document.hotDownLeft.src = document.navDownLeftPres.src;    }    else {      document.images['navDownLeft'].src = document.navDownLeftDead.src;      document.hotDownLeft.src = document.navDownLeftDead.src;    }    if (leftAble) {      document.images['navLeft'].src = document.navLeftLive.src;      document.hotLeft.src = document.navLeftPres.src;    }    else {      document.images['navLeft'].src = document.navLeftDead.src;      document.hotLeft.src = document.navLeftDead.src;    }    if (upLeftAble) {      document.images['navUpLeft'].src = document.navUpLeftLive.src;      document.hotUpLeft.src = document.navUpLeftPres.src;    }    else {      document.images['navUpLeft'].src = document.navUpLeftDead.src;      document.hotUpLeft.src = document.navUpLeftDead.src;    }    if (upAble) {      document.images['navUp'].src = document.navUpLive.src;      document.hotUp.src = document.navUpPres.src;    }    else {      document.images['navUp'].src = document.navUpDead.src;      document.hotUp.src = document.navUpDead.src;    }    if (upRightAble) {      document.images['navUpRight'].src = document.navUpRightLive.src;      document.hotUpRight.src = document.navUpRightPres.src;    }    else {      document.images['navUpRight'].src = document.navUpRightDead.src;      document.hotUpRight.src = document.navUpRightDead.src;    }  }}// swap in depressed navigation bar image on mouseDown for user feedback while new view is loadingfunction hotPress(action) {  switch (action) {    case "previous":      document.navPrevious.src = document.hotPrevious.src;      break;    case "zoomout":      document.navZoomOut.src = document.hotZoomOut.src;      break;    case "fullview":      document.navFullView.src = document.hotFullView.src;      break;    case "upright":      document.navUpRight.src = document.hotUpRight.src;      break;    case "right":      document.navRight.src = document.hotRight.src;      break;    case "downright":      document.navDownRight.src = document.hotDownRight.src;      break;    case "down":      document.navDown.src = document.hotDown.src;      break;    case "downleft":      document.navDownLeft.src = document.hotDownLeft.src;      break;    case "left":      document.navLeft.src = document.hotLeft.src;      break;    case "upleft":      document.navUpLeft.src = document.hotUpLeft.src;      break;    case "up":      document.navUp.src = document.hotUp.src;      break;  }}// master function to preload images for three most likely types of possible movement from new locationfunction loadNexts(caller) {  // later use 'caller' for predictive algorithm determining sequence of calls to subfunctions?  if (document.images) {    if (nowView.l < nowView.lm) {      loadingZoomIns   = true;      loadZoomIns();    }    if (nowView.l > 1) {      loadingZoomOut   = true;      loadingAdjacents = true;      loadZoomOut();      loadAdjacents();    }  }}// determine, set, and preload images for zoomInfunction loadZoomIns() {  var inLevel = nowView.l+1;    inRight = nowView.x*2;  inLeft  = inRight-1;  inDown  = nowView.y*2;  inUp    = inDown-1;    xMax = yMax = Math.pow(2,nowView.l);  if ((nowView.xj[inLevel] == 1) && (inLeft == (xMax/2 + 1))) {  // This redirects KDD zoomIns from l2x02y01-04 via upLeft and downLeft    inLeft -= nowView.xj[inLevel];                               // to l3x02y01-04 rather than default l3x03y01-04 and from l3x02y01-04 via  }                                                              // upRight and downRight to l4x06y01-04 rather than default l4x04y01-04,  if ((nowView.xj[inLevel] == 2) && (inRight == (xMax/2))) {     // but won't necessarily handle general cases; tweak when have more images.    inRight += nowView.xj[inLevel];  }/*  if ((nowView.yj[inLevel] == 1) && (inUp == (yMax/2 + 1))) {    // this y-axis version was blindly transformed by analogy from the x-axis    inUp -= nowView.yj[inLevel];                                 // version (see comment above) that works for KDD; check with a horizontal  }                                                              // image to see if it works, and wrap both in conditionals based on aspectRatio  if ((nowView.yj[inLevel] == 2) && (inDown == (yMax/2))) {      // to skip when not needed. Possibly abstract shared jump-handling parts of    inDown += nowView.yj[inLevel];                               // goAdjacent, zoomIn, and zoomOut when general cases for all settle down.  }*/  var inBase = nowView.b + "l" + inLevel;  var padRight = "x" + pad2(inRight);  var padLeft  = "x" + pad2(inLeft);  var padDown  = "y" + pad2(inDown);  var padUp    = "y" + pad2(inUp);  imageInUpRight1.src   = inBase + padRight + padUp   + ".jpg";  imageInDownRight1.src = inBase + padRight + padDown + ".jpg";  imageInDownLeft1.src  = inBase + padLeft  + padDown + ".jpg";  imageInUpLeft1.src    = inBase + padLeft  + padUp   + ".jpg";  loadingZoomIns = false;}// determine, set, and preload image for zoomOutfunction loadZoomOut() {  lOutNext = nowView.l - 1;  xOutNext = Math.ceil(nowView.x/2);  yOutNext = Math.ceil(nowView.y/2);  // this redirects KDD zoomOuts from l4x06y01-08 to l3x02y01-04 (from default l3x03y01-04),  // but won't work as is for all cases--tweak and add y version when have more sample images;  // abstract shared jump-handling parts of goAdjacent, zoomIn, and zoomOut when settle down.  xMax = yMax = Math.pow(2,(lOutNext-1));  if ((nowView.xj[lOutNext] == 1) && (xOutNext == (xMax/2 + 1))) {    xOutNext -= nowView.xj[lOutNext];  }  imageZoomOut1.src = nowView.b + "l" + lOutNext + "x" + pad2(xOutNext) + "y" + pad2(yOutNext) + ".jpg";  loadingZoomOut = false;}// determine possible destinations and preload images for goAdjacentfunction loadAdjacents() {  // set variables for jumps from current location to allow square quadrants from corners in image production  var xOffsetRight = 0;  var yOffsetDown = 0;  var xOffsetLeft = 0;  var yOffsetUp = 0;  if ((nowView.xj[0] == true) && (nowView.x == (Math.pow(2,(nowView.l-1))/2 - Math.floor(nowView.xj[nowView.l]/2)))) {    xOffsetRight = nowView.xj[nowView.l];  }  if ((nowView.yj[0] == true) && (nowView.y == (Math.pow(2,(nowView.l-1))/2 - Math.floor(nowView.yj[nowView.l]/2)))) {    yOffsetDown = nowView.yj[nowView.l];  }  if ((nowView.xj[0] == true) && (nowView.x == (Math.pow(2,(nowView.l-1))/2 + Math.floor(nowView.xj[nowView.l]/2)) + 1)) {    xOffsetLeft = nowView.xj[nowView.l];  }  if ((nowView.yj[0] == true) && (nowView.y == (Math.pow(2,(nowView.l-1))/2 + Math.floor(nowView.yj[nowView.l]/2)) + 1)) {    yOffsetUp = nowView.yj[nowView.l];  }  // set possible destination components including any offsets; may exceed image limits, but movement is constrained later  nextRight = nowView.x + xOffsetRight + 1;  nextDown  = nowView.y + yOffsetDown + 1;  nextLeft  = nowView.x - xOffsetLeft - 1;  nextUp    = nowView.y - yOffsetUp - 1;  var padRight = "x" + pad2(nextRight);  var padDown  = "y" + pad2(padDown);  var padLeft  = "x" + pad2(padLeft);  var padUp    = "y" + pad2(padUp);  var thisBase = nowView.b + "l" + nowView.l;  var thisX    = "x" + pad2(nowView.x);  var thisY    = "y" + pad2(nowView.y);  // preload images for goAdjacent; although conditional logic is the same as for framing navigation bar loading  // above, keep separate so navigation gifs all load without waiting for far heavier (off-screen) JPEG preloads    if (rightAble) {    imageRight1.src     = thisBase + padRight + thisY   + ".jpg";  }   if (downRightAble) {    imageDownRight1.src = thisBase + padRight + padDown + ".jpg";  }  if (downAble) {    imageDown1.src      = thisBase + thisX    + padDown + ".jpg";  }  if (downLeftAble) {    imageDownLeft1.src  = thisBase + padLeft  + padDown + ".jpg";  }  if (leftAble) {    imageLeft1.src      = thisBase + padLeft  + thisY   + ".jpg";  }   if (upLeftAble) {    imageUpLeft1.src    = thisBase + padLeft  + padUp   + ".jpg";  }  if (upAble) {    imageUp1.src        = thisBase + thisX    + padUp   + ".jpg";  }  if (upRightAble) {    imageUpRight1.src   = thisBase + padRight + padUp   + ".jpg";  }  loadingAdjacents = false;}// execute the move to a new viewfunction goNext(caller) {  if (mie5 && caller == "zoomin") {    document.viewImage1.blur();  }  if (net6 && caller == "zoomin") {    document.anchors["smallMap1"].blur();  // document.anchors["viewImage1"].blur(); seems more sensible, but N6 returns "no properties" error  }  document.images["viewImage1"].src = goView.b + "l" + goView.l + "x" + pad2(goView.x) + "y" + pad2(goView.y) + ".jpg";  nowView = goView;  setStatus();  goAbles(nowView);  setBars(nowView);  setNavigation();  if (caller != "lastview") {    pastViews[pastViews.length] = new View;    pastViews[pastViews.length-1].l = nowView.l;    pastViews[pastViews.length-1].x = nowView.x;    pastViews[pastViews.length-1].y = nowView.y;    document.images['prevView'].src = document.navPreviousLive.src;  }  loadNexts(caller);}// go back to the previously displayed viewfunction lastView() {  if (preloaded && pastViews.length > 1) {    goView = nowView;    goView.l = pastViews[pastViews.length-2].l;    goView.x = pastViews[pastViews.length-2].x;    goView.y = pastViews[pastViews.length-2].y;    // goView = pastViews[pastViews.length-2];  would be more compact, but doesn't work -- how to pass entire object from array?    pastViews.length = pastViews.length-1;    goNext("lastview");  }}// zoom in to deeper-level view representing one quadrant of current viewfunction zoomIn(zoomQuadrant) {  if (preloaded && nowView.l < nowView.lm) {  // && loadingZoomIns == false    if (nowView.b == null || nowView.l == null || nowView.x == null || nowView.y == null) {      makeView();    }    loadNexts(nowView);  // N6 needs nowView passed to loadNexts() -- why?    goView = nowView;    goView.l += 1;    switch (zoomQuadrant) {      case "upright":        goView.x = inRight;        goView.y = inUp;        break;      case "downright":        goView.x = inRight;        goView.y = inDown;        break;      case "downleft":        goView.x = inLeft;        goView.y = inDown;        break;      case "upleft":        goView.x = inLeft;        goView.y = inUp;        break;    }    goNext("zoomin");  }}// go to shallower zoom-level view encompassing current view -- currently disregards jumps, so tweak to accomodate them.function zoomOut() {  if (preloaded && nowView.l > 1 && loadingZoomOut == false) {    goView = nowView;    goView.l -= 1;    goView.x = xOutNext;    goView.y = yOutNext;    goNext("zoomout");  }}// go to full view of objectfunction fullView() {  if (preloaded && nowView.l > 1) {    goView = nowView;    goView.l = 1;    goView.x = 1;    goView.y = 1;    goNext("fullview");  }}// go to adjacent detail view at current level -- called from framing buttons for adjacent zones if existfunction goAdjacent(goDirection) {  if (preloaded && nowView.l > 1) {   // third condition of (loadingAdjacents == false) made any adjacent move wait for up to 8 images to load    hotPress(goDirection);    loadNexts(nowView);    // buttonClock = window.setTimeout("setBars(nowView)",6000);    goAbles(nowView);    goView.l = nowView.l;    if ((goDirection == "right") && rightAble) {      goView.x = nextRight;      goView.y = nowView.y;    }    if ((goDirection == "downright") && downRightAble) {      goView.x = nextRight;      goView.y = nextDown;    }    if ((goDirection == "down") && downAble) {      goView.x = nowView.x;      goView.y = nextDown;    }    if ((goDirection == "downleft") && downLeftAble) {      goView.x = nextLeft;      goView.y = nextDown;    }    if ((goDirection == "left") && leftAble) {      goView.x = nextLeft;      goView.y = nowView.y;    }    if ((goDirection == "upleft") && upLeftAble) {      goView.x = nextLeft;      goView.y = nextUp;    }    if ((goDirection == "up") && upAble) {      goView.x = nowView.x;      goView.y = nextUp;    }    if ((goDirection == "upright") && upRightAble) {      goView.x = nextRight;      goView.y = nextUp;    }    goNext("goadjacent");  }}// set x and y click coordinate variables for Explorer 5 for newCenter()function setClick() {  if (mie5) {    xClick = window.event.offsetX + document.body.scrollLeft;    yClick = window.event.offsetY + document.body.scrollTop;  }}// go to another detail at current zoom level; eventually overlay red square on map for current location?function newCenter(evnt) {  var goodX = false;  var goodY = false;  if (net4) {    xClick = evnt.pageX - document.smallMapImageOne.x;    yClick = evnt.pageY - document.smallMapImageOne.y;    goodX = ((xClick >= 1) && (xClick <= 128));    goodY = ((yClick >= 1) && (yClick <= 128));  }  if (net6) { // newCenter() doesn't work yet in N6; for now, warn and and set vars so it won't try    alert("This map doesn't work yet with Netscape 6;\nall other navigation operates as it should.");/*    goodX = goodY = false;    xClick = e.clientX - parseInt(net6SmallMap.style.left);    yClick = e.clientY - parseInt(net6SmallMap.style.top);    goodX = ((xClick >= 1) && (xClick <= 128));    goodY = ((yClick >= 1) && (yClick <= 128));    // parseInt(document.getElementById('smallMapImage1').style.left approach didn't seem to work either*/  }  if (mie5) {    goodX = goodY = true;   }  if (goodX && goodY && nowView.l > 1) {    goAbles(nowView);    // ignore clicks in white padding areas, if any, that make thumbnail image square    if (nowView.xs != nowView.ys) {      var blank = Math.floor(64*(nowView.ys - nowView.xs)/nowView.ys);      var xBlank = ((blank > 0) ? blank : 0 );      var yBlank = ((blank < 0) ? blank : 0 );    }    if (((xClick > xBlank) && (xClick + xBlank) <= 128) && ((yClick > yBlank) && (yClick + yBlank) <= 128)) {      // having ignored clicks in thumbnail margins, scale click coordinates as if live area of image = 128 x 128 pixels      if (xBlank != 0) {        xClick = Math.floor((xClick - xBlank) * (128/(128-(xBlank*2))));      }      if (yBlank != 0) {        yClick = Math.floor((yClick - yBlank) * (128/(128-(yBlank*2))));      }      // account for nonexistent locations at current level      var xGrid = nowView.xm - nowView.xj[nowView.l];      var yGrid = nowView.ym - nowView.yj[nowView.l];      // set horizontal and vertical positions in current level's grid      var xNew = Math.ceil(xClick*xGrid/128);      var yNew = Math.ceil(yClick*yGrid/128);      if ((nowView.xj[nowView.l] > 0) && (xNew > xGrid/2)) {        xNew += nowView.xj[nowView.l];      }      if ((nowView.yj[nowView.l] > 0) && (yNew > yGrid/2)) {        yNew += nowView.yj[nowView.l];      }      goView.b = nowView.b;      goView.l = nowView.l;      goView.x = xNew;      goView.y = yNew;      goNext("newcenter");      if (net4) {        return false;  // this writes the text "false" to IE5.50.4522.1800 (and probably other IE5.X?) for Windows if executed      }    }  }}