// (c) Stephen P. Morse, 2002

      var ImageFrame = 0;
      var HeadFrame = 1;
      var EndFrame = 2;
      var JSFrame = 3;

      var display = false;

      function Ellis() {
        return (Mode()=="ellis" || Mode()=="both");
      }


      function ToEIDB() {
        var formPROCESS = self.parent.frames[HeadFrame].document.formPROCESS;
        var series;
        if (Ellis() || Mode() == "bost" || Mode() == "balt" || Mode() == "orleans" || Mode() == "phil" || Mode() == "ny") {
          series = formPROCESS.mSERIES.value;
        } else if (Mode() == "castle") {
          series = "M237";
        } else if (Mode() == "sanfran") {
          series = "M1410";
        } else if (Mode() == "galv") {
          series = "M1359";
        }
        var roll = formPROCESS.mROLL.value;
        while (roll.length < 4) {
          roll = "0" + roll;
        }
        var frame = formPROCESS.mFRAME.value;
        while (frame.length < 4) {
          frame = "0" + frame;
        }
        var rollframe = "G:\\" + series + "-" + roll + "\\" + series + "-" + roll + frame + ".TIF";
        url =
//          "http://www.ellisislandrecords.org/search/shipManifest.asp?show=" + rollframe +
          "http://www.ellisisland.org/search/shipManifest.asp?show=" + rollframe +
          "&origFN=" + rollframe;
        self.parent.location = url;
      }

      function BackURL() {
        var url = self.parent.location.toString();
        var query = getQueryString(url);
        var back = GetParameter(query, "back")
        return back ? back : "ellis.html";
        // note we'd like to get back to the caller if possible.  However it's not possible if
        // we were called from other than the white, blue, or gray forms, so in that case we
        // have no choice but to return to the white form.
      }

      function GetParameter(query, parameter) {

        // convert to array of individual arguments
        var arglist = query.split("&");

        // process each argument
        for (j in arglist) {
          var equalSign = arglist[j].indexOf("=");
          var leftSide = (equalSign == -1) ? arglist[j] : arglist[j].substr(0, equalSign);
          if (leftSide == parameter) {
            var rightSide = (equalSign == -1) ? "" : arglist[j].substr(equalSign+1);
            return unescape(rightSide);
          }
        }
        return "";
      }

      var mode = "";

      function Mode() {
        if (mode == "") {
          var query = getQueryString(self.parent.location.toString());
          mode = GetParameter(query, "mode");
          if (mode == "") {
            mode = "ellis";
          }
        }

        // switch to jewishgen server if for ellis island manifests and we are on my server
/*
        if (mode == "ellis") {
          var loc = String(self.parent.location); // get current URL
          loc = loc.split("?")[0]; // get rid of query string which could have "back=...morse ..."
          if (loc.toLowerCase().indexOf("morse") != -1 &&
              loc.toLowerCase().indexOf("ellis2") == -1) {
            self.parent.location.replace("http://www.jewishgen.org/databases/EIDB/mm.htm?"+query);
          }
        }
*/
        if (mode == "precastle" || mode == "postellis") { // no longer exist
          mode = "ny";
        }

        return mode;
      }

      function getQueryString(url) {
        var questionmarkPosition = url.indexOf("?");
        return (questionmarkPosition == -1) ? "" : url.substr(questionmarkPosition+1);
      }

      function DisplayEndFrame() {
        return (Mode() == "ellis" || Mode() == "castle" || Mode() == "both");
      }

      function extractEndFrameFromQuery(url) {
        if (!DisplayEndFrame()) {
          return;
        }

        // get query string portion of url
        var query = getQueryString(url.toString());

        // get end frame from query string
        if (GetParameter(query, "eframe") == "") {
          return;
        }

        var eFrameParameter = GetParameter(query, "eframe") - 0;
        var sFrameParameter = GetParameter(query, "sframe") - 0;
        // the "- 0" above converts the string to a number so as not to have problems with it later

        // initialize eFrame/sFrame input fields, also cache them into table
        var endframe = self.parent.frames[EndFrame].document.endFrame;
        endframe.eFrame.value = eFrameParameter;
        endframe.sFrame.value = sFrameParameter;
        var index = GetIndexFromTable();
        startFrameArray[index] = sFrameParameter;
        endFrameArray[index] = eFrameParameter;
      }


      function SetCookie(cookieName, cookieValue) {
        var expires = new Date();
        var today = new Date();
        expires.setTime(today.getTime() + 1000*60*60*24*365);
        document.cookie = cookieName + "=" + cookieValue + "; expires=" + expires.toGMTString();
      }

      function GetCookie(cookieName) {
        var cookies = document.cookie.split(";");
        for (var i=0; i<cookies.length; i++) {
          while (cookies[i].charAt(0) == " ") {
            cookies[i] = cookies[i].slice(1);
          }
          var thisCookie = cookies[i].split("=");
          if (thisCookie[0] == cookieName) {
            if (thisCookie.length > 1) {
              return thisCookie[1];
            } else {
              return "";
            }
          }
        }
        return "";
      }

      function LoadJS() {
        if (Mode() == "ellis") {
          self.parent.frames[ImageFrame].location.replace("mm2ellis.htm");
          self.parent.frames[JSFrame].location.replace("mmellis.htm");
          self.parent.frames[EndFrame].location.replace("mm3.htm");
        } else if (Mode() == "castle") {
          self.parent.frames[ImageFrame].location.replace("mm2castle.htm");
          self.parent.frames[JSFrame].location.replace("mmcastle.htm");
          self.parent.frames[EndFrame].location.replace("mm3.htm");
        } else if (Mode() == "both") {
          self.parent.frames[ImageFrame].location.replace("mm2both.htm");
          self.parent.frames[JSFrame].location.replace("mmboth.htm");
          self.parent.frames[EndFrame].location.replace("mm3.htm");
        } else if (Mode() == "ny") {
          self.parent.frames[ImageFrame].location.replace("mm2ny.htm");
          self.parent.frames[JSFrame].location.replace("mmny.htm");
        } else if (Mode() == "sanfran") {
          self.parent.frames[ImageFrame].location.replace("mm2sanfran.htm");
          self.parent.frames[JSFrame].location.replace("mmsanfran.htm");
        } else if (Mode() == "balt") {
          self.parent.frames[ImageFrame].location.replace("mm2balt.htm");
          self.parent.frames[JSFrame].location.replace("mmbalt.htm");
        } else if (Mode() == "orleans") {
          self.parent.frames[ImageFrame].location.replace("mm2orleans.htm");
          self.parent.frames[JSFrame].location.replace("mmorleans.htm");
        } else if (Mode() == "bost") {
          self.parent.frames[ImageFrame].location.replace("mm2bost.htm");
          self.parent.frames[JSFrame].location.replace("mmbost.htm");
        } else if (Mode() == "galv") {
          self.parent.frames[ImageFrame].location.replace("mm2galv.htm");
          self.parent.frames[JSFrame].location.replace("mmgalv.htm");
        } else if (Mode() == "phil") {
          self.parent.frames[ImageFrame].location.replace("mm2phil.htm");
          self.parent.frames[JSFrame].location.replace("mmphil.htm");
        } else if (Mode() == "postellis") {
          self.parent.frames[ImageFrame].location.replace("mm2postellis.htm");
          self.parent.frames[JSFrame].location.replace("mmpostellis.htm");
        }
      }

      function Startup() {

        // get query string portion of url
        var url = self.parent.location.toString();
        var query = getQueryString(url);
        // initialize state
        var formPROCESS = self.parent.frames[HeadFrame].document.formPROCESS;
        var parameter;
        if (Ellis()) {
          parameter = GetParameter(query, "scale");
          if (parameter == "") {
            parameter = GetCookie("mm_scale");
          }
          if (parameter != "") {
            formPROCESS.mSCALE.selectedIndex = parameter;
          }
        }
        if (Ellis() || Mode() == "bost" || Mode() == "balt" || Mode() == "orleans" || Mode() == "phil" || Mode() == "ny") {
          parameter = GetParameter(query, "series");
          if (parameter != "") {
            formPROCESS.mSERIES.selectedIndex = parameter;
          }
        }
        parameter = GetParameter(query, "roll");
        if (parameter != "") {
          formPROCESS.mROLL.value = parameter;
        }

        var oldFrame = formPROCESS.mFRAME.value;
        getDate();
        formPROCESS.mFRAME.value = oldFrame;

        parameter = GetParameter(query, "frame");
        if (parameter != "") {
          formPROCESS.mFRAME.value = parameter;
        } else {
          formPROCESS.mFRAME.value = FirstFrame();
        }
        parameter = GetParameter(query, "separate");
        if (parameter != "") {
          formPROCESS.nsSEPARATE.checked = (parameter=="true") ? true : false;
        }

        // following needs to come after we establish the default year, otherwise the year gets reset
        parameter = GetParameter(query, "display");
        if (parameter != "" && parameter == "true" ) {
          getURL(true);
        }

      }

      function FirstFrame() {
        var formPROCESS = self.parent.frames[HeadFrame].document.formPROCESS;
        var SERIES;
        if (Ellis() || Mode() == "bost" || Mode() == "balt" || Mode() == "orleans" || Mode() == "phil" || Mode() == "ny") {
          var index = formPROCESS.mSERIES.selectedIndex;
          SERIES = formPROCESS.mSERIES[index].value;
        } else if (Mode()=="castle") {
          SERIES = "M237";
        } else if (Mode() == "sanfran") {
          SERIES = "M1410";
        } else if (Mode() == "galv") {
          SERIES = "M1359";
        } else if (Mode() == "postellis") {
          SERIES = "T715";
        }
        var ROLL = formPROCESS.mROLL.value;

        if (Mode() == "ny") { // all ny record
          if (SERIES == "M237") {
            for (var i=0; i<parent.frames[JSFrame].nyLimitsM.length; i++) {
              if (parent.frames[JSFrame].nyLimitsM[i][0] == ROLL) {
                return parent.frames[JSFrame].nyLimitsM[i][1];
              }
            }
          } else {
            for (var i=0; i<parent.frames[JSFrame].nyLimitsT.length; i++) {
              if (parent.frames[JSFrame].nyLimitsT[i][0] == ROLL) {
                return parent.frames[JSFrame].nyLimitsT[i][1];
              }
            }
          }
          return 1;

        } else if (SERIES == "M237" && ROLL < 581) { // castle garden record
          for (var i=0; i<parent.frames[JSFrame].castleLimits.length; i++) {
            if (parent.frames[JSFrame].castleLimits[i][0] == ROLL) {
              return parent.frames[JSFrame].castleLimits[i][1];
            }
          }
          return 1;

        } else if (Mode() == "sanfran") { // san francisco record
          for (var i=0; i<parent.frames[JSFrame].sanfranLimits.length; i++) {
            if (parent.frames[JSFrame].sanfranLimits[i][0] == ROLL) {
              return parent.frames[JSFrame].sanfranLimits[i][1];
            }
          }
          return 1;

        } else if (Mode() == "balt") { // baltimore record
          if (SERIES == "M255") {
            for (var i=0; i<parent.frames[JSFrame].baltLimitsM.length; i++) {
              if (parent.frames[JSFrame].baltLimitsM[i][0] == ROLL) {
                return parent.frames[JSFrame].baltLimitsM[i][1];
              }
            }
          } else {
            for (var i=0; i<parent.frames[JSFrame].baltLimitsT.length; i++) {
              if (parent.frames[JSFrame].baltLimitsT[i][0] == ROLL) {
                return parent.frames[JSFrame].baltLimitsT[i][1];
              }
            }
          }
          return 1;

        } else if (Mode() == "orleans") { // new orleans record
          if (SERIES == "M259") {
            for (var i=0; i<parent.frames[JSFrame].orleansLimitsM.length; i++) {
              if (parent.frames[JSFrame].orleansLimitsM[i][0] == ROLL) {
                return parent.frames[JSFrame].orleansLimitsM[i][1];
              }
            }
          } else {
            for (var i=0; i<parent.frames[JSFrame].orleansLimitsT.length; i++) {
              if (parent.frames[JSFrame].orleansLimitsT[i][0] == ROLL) {
                return parent.frames[JSFrame].orleansLimitsT[i][1];
              }
            }
          }
          return 1;

        } else if (Mode() == "bost") { // boston record
          if (SERIES == "M277") {
            for (var i=0; i<parent.frames[JSFrame].bostLimitsM.length; i++) {
              if (parent.frames[JSFrame].bostLimitsM[i][0] == ROLL) {
                return parent.frames[JSFrame].bostLimitsM[i][1];
              }
            }
          } else {
            for (var i=0; i<parent.frames[JSFrame].bostLimitsT.length; i++) {
              if (parent.frames[JSFrame].bostLimitsT[i][0] == ROLL) {
                return parent.frames[JSFrame].bostLimitsT[i][1];
              }
            }
          }
          return 1;

        } else if (Mode() == "galv") { // galveston record
          for (var i=0; i<parent.frames[JSFrame].galvLimits.length; i++) {
            if (parent.frames[JSFrame].galvLimits[i][0] == ROLL) {
              return parent.frames[JSFrame].galvLimits[i][1];
            }
          }
          return 1;

        } else if (Mode() == "phil") { // philadelphia record
          if (SERIES == "M425") {
            for (var i=0; i<parent.frames[JSFrame].philLimitsM.length; i++) {
              if (parent.frames[JSFrame].philLimitsM[i][0] == ROLL) {
                return parent.frames[JSFrame].philLimitsM[i][1];
              }
            }
          } else {
            for (var i=0; i<parent.frames[JSFrame].philLimitsT.length; i++) {
              if (parent.frames[JSFrame].philLimitsT[i][0] == ROLL) {
                return parent.frames[JSFrame].philLimitsT[i][1];
              }
            }
          }
          return 1;

        } else if (Mode() == "postellis") { // ellis records 1935-1938
          for (var i=0; i<parent.frames[JSFrame].postellisLimits.length; i++) {
            if (parent.frames[JSFrame].postellisLimits[i][0] == ROLL) {
              return parent.frames[JSFrame].postellisLimits[i][1];
            }
          }

        } else {
          return 1;
        }
      }

      function SwitchDisplay(url) {
        var formPROCESS = self.parent.frames[HeadFrame].document.formPROCESS;
        var queryString = "?mode=" + Mode();
        queryString += ("&back=" + BackURL());
        if (Ellis()) {
          queryString += "&"
          queryString += ("scale=" + formPROCESS.mSCALE.selectedIndex);
        }
        if (Ellis() || Mode() == "bost" || Mode() == "balt" || Mode() == "orleans" || Mode() == "phil" || Mode() == "ny") {
          queryString += "&"
          queryString += ("series=" + formPROCESS.mSERIES.selectedIndex);
        }
        queryString += "&"
        queryString += ("roll=" + formPROCESS.mROLL.value);
        queryString += "&"
        queryString += ("frame=" + formPROCESS.mFRAME.value);
        queryString += "&"
        queryString += ("separate=" + formPROCESS.nsSEPARATE.checked);
        queryString += "&"
        queryString += ("display=" + display);
        self.parent.location.replace(url + queryString);
      }

      function advanceRoll(i) {
        var formPROCESS = self.parent.frames[HeadFrame].document.formPROCESS;
        var val = formPROCESS.mROLL.value;
        for (ii=0; ii<val.length; ii++) {
          if (val.charAt(ii) < '0' || val.charAt(ii) > '9') {
            val = val.substr(0, ii);
            break;
          }
        }
        formPROCESS.mROLL.value = (val - (-i));
        formPROCESS.mFRAME.value = FirstFrame();
        getDate();
        getURL(false);
      }

      function retardRoll(i) {
        var formPROCESS = self.parent.frames[HeadFrame].document.formPROCESS;
        var val = formPROCESS.mROLL.value;
        for (ii=0; ii<val.length; ii++) {
          if (val.charAt(ii) < '0' || val.charAt(ii) > '9') {
            val = val.substr(0, ii);
            break;
          }
        }
        if (parseInt(val) > i) {
          formPROCESS.mROLL.value = (val - i);
          formPROCESS.mFRAME.value = FirstFrame();
          getDate();
          getURL(false);
        } else if (parseInt(val) > 1) {
          formPROCESS.mROLL.value = 1;
          formPROCESS.mFRAME.value = FirstFrame();
          getDate();
          getURL(false);
        } else {
          alert("Already at first roll, cannot back up further");
        }
      }

      function advanceFrame(i) {
        var formPROCESS = self.parent.frames[HeadFrame].document.formPROCESS;
        if (DisplayEndFrame()) {
          var endframe = self.parent.frames[EndFrame].document.endFrame;
          var endFrameValue = endframe.eFrame.value;
          if (endFrameValue == "wait...") {
            endFrameValue = 9999;
          }
        }
        var val = formPROCESS.mFRAME.value;
        for (ii=0; ii<val.length; ii++) {
          if (val.charAt(ii) < '0' || val.charAt(ii) > '9') {
            val = val.substr(0, ii);
            break;
          }
        }
        if (!DisplayEndFrame() || parseInt(val) + i <= parseInt(endFrameValue)) {
          formPROCESS.mFRAME.value = (val - (-i));
          getURL(false);
        } else if (parseInt(formPROCESS.mFRAME.value) != parseInt(endFrameValue)) {
          formPROCESS.mFRAME.value = endFrameValue;
          getURL(false);
        } else {
          alert("Already at last frame, cannot advance further");
        }
      }

      function retardFrame(i) {
        var formPROCESS = self.parent.frames[HeadFrame].document.formPROCESS;

        if (DisplayEndFrame()) {
          var endframe = self.parent.frames[EndFrame].document.endFrame;
          var startFrameValue = endframe.sFrame.value;
          if (startFrameValue == "wait...") {
            startFrameValue = 1;
          }
        }
        var val = formPROCESS.mFRAME.value;
        for (ii=0; ii<val.length; ii++) {
          if (val.charAt(ii) < '0' || val.charAt(ii) > '9') {
            val = val.substr(0, ii);
            break;
          }
        }
        if (!DisplayEndFrame() || parseInt(val) - i >= parseInt(startFrameValue)) {
          formPROCESS.mFRAME.value = (val - i);
          getURL(false);
        } else if (parseInt(formPROCESS.mFRAME.value) > parseInt(startFrameValue)) {
          formPROCESS.mFRAME.value = FirstFrame();
          getURL(false);
        } else {
          alert("Already at first frame, cannot back up further");
        }
      }
	
      var firstShow = true;

      function getURL(fromStartup) {

        // make sure frame is in range
        var formPROCESS = self.parent.frames[HeadFrame].document.formPROCESS;

        // don't access EndFrame frame if from startup -- causes js error on N4
        if (DisplayEndFrame()) {
          var endFrameValue = 9999;
          var startFrameValue = 1;
          if (!fromStartup) {
            var endframe = self.parent.frames[EndFrame].document.endFrame;
            endFrameValue = endframe.eFrame.value;
            startFrameValue = endframe.sFrame.value;
          }
          if (endFrameValue == "wait...") {
            endFrameValue = 9999;
          }
        }
        if (DisplayEndFrame() && parseInt(formPROCESS.mFRAME.value) > parseInt(endFrameValue)) {
          if (!confirm("Frame value is out of range (larger than endframe).  Do you still want to display it?")) {
            return;
          }
        }
        if (startFrameValue == "wait...") {
          startFrameValue = 1;
        }
        if (DisplayEndFrame() && parseInt(formPROCESS.mFRAME.value) < parseInt(startFrameValue)) {
          if (!confirm("Frame value is out of range (smaller than startframe).  Do you still want to display it?")) {
            return;
          }
        }

        var oldValue = formPROCESS.mFRAME.value;
        getDateFromRoll();
        formPROCESS.mFRAME.value = oldValue;

        var SERIES;
        if (Ellis() || Mode() == "bost" || Mode() == "balt" || Mode() == "orleans" || Mode() == "phil" || Mode() == "ny") {
          var index = formPROCESS.mSERIES.selectedIndex;
          SERIES = formPROCESS.mSERIES[index].value;
        } else if (Mode()=="castle") {
          SERIES = "M237";
        } else if (Mode() == "sanfran") {
          SERIES = "M1410";
        } else if (Mode() == "galv") {
          SERIES = "M1359";
        }
        var ROLL = formPROCESS.mROLL.value;
        var FRAME = formPROCESS.mFRAME.value;
        var frameLength = 0;
        for (var j=0; j<FRAME.length; j++) { // get length of FRAME up to first non digit
          if (FRAME.charAt(j) < '0' || FRAME.charAt(j) > '9') {
            break;
          }
          frameLength++;
        }
        while (frameLength < 4) {
          FRAME = "0" + FRAME;
          frameLength++;
        }

        var vACTION;

        if (Mode() == "castle" || (Mode() == "both" && SERIES == "M237" && ROLL < 581)) { // castle garden record
          vACTION = "http://content.ancestry.com/Browse/view.aspx?dbid=7488&iid=NYM237_";
          vACTION += ROLL;
          vACTION += "-";
          vACTION += FRAME;
          vACTION = "../toancestry.html?url=" + escape(vACTION);

        } else if (Mode() == "sanfran") { // san franciso record
          vACTION = "http://content.ancestry.com/Browse/view.aspx?dbid=7949&iid=CAM1410_";
          vACTION += ROLL;
          vACTION += "-";
          vACTION += FRAME;
          vACTION = "../toancestry.html?url=" + escape(vACTION);

        } else if (Mode() == "ny") { // ny record
          vACTION = "http://content.ancestry.com/Browse/default.aspx?dbid=7488&iid=NY";
//          vACTION = "http://content.ancestry.com/Browse/view.aspx?dbid=7488&iid=NY";
          // which of the above should I use?  They appear to use both.

/* this is no longer needed -- they appear to have fixed this inconsistency on their site
          // for certain rolls they do not tack on the NY as part of the iid value ...
          // ... and for certain of those they actually repeat the series twice
          var duplicateSeries = false;
          if (SERIES == "T715") {
            if ((ROLL >= 1 && ROLL <= 46) ||
                (ROLL >= 48 && ROLL <= 178) ||
                (ROLL >= 180 && ROLL <= 218) ||
                (ROLL >= 220 && ROLL <= 241) ||
                (ROLL >= 243 && ROLL <= 246) ||
                (ROLL >= 253 && ROLL <= 257) ||
                (ROLL >= 259 && ROLL <= 260) ||
                (ROLL == 262) ||
                (ROLL >= 272 && ROLL <= 276) ||
                (ROLL >= 278 && ROLL <= 289) ||
                (ROLL >= 291 && ROLL <= 314) ||
                (ROLL >= 316 && ROLL <= 318) ||
                (ROLL >= 321 && ROLL <= 325) ||
                (ROLL >= 329 && ROLL <= 339) ||
                (ROLL >= 341 && ROLL <= 345) ||
                (ROLL >= 351 && ROLL <= 456) ||
                (ROLL >= 4218 && ROLL <= 4225) ||
                (ROLL == 5030)) {
              vACTION = vACTION.substr(0, (vACTION.length)-2); // remove NY
              if ((ROLL == 52) || (ROLL == 81) || (ROLL == 108) ||
                  (ROLL == 116) || (ROLL == 168) || (ROLL == 210) || 
                  (ROLL >= 226 && ROLL <= 228) ||
                  (ROLL >= 231 && ROLL <= 232) ||
                  (ROLL == 237) ||
                  (ROLL >= 243 && ROLL <= 246) ||
                  (ROLL >= 253 && ROLL <= 257) ||
                  (ROLL >= 259 && ROLL <= 260) ||
                  (ROLL == 262) || (ROLL == 273) || (ROLL == 285) || (ROLL == 287) ||
                  (ROLL >= 317 && ROLL <= 318) ||
                  (ROLL == 356)) {
                duplicateSeries = true;
              }
            }
          }
*/

          vACTION += SERIES;
/*
          if (duplicateSeries) {
            vACTION += SERIES;
          }
*/
          vACTION += "_";
          vACTION += ROLL;
          vACTION += "-";
          vACTION += FRAME;
          vACTION = "../toancestry.html?url=" + escape(vACTION);

        } else if (Mode() == "balt") { // baltimore record
          vACTION = "http://content.ancestry.com/Browse/view.aspx?dbid=8679&iid=MD";
          vACTION += SERIES;
          vACTION += "_";
          vACTION += ROLL;
          vACTION += "-";
          vACTION += FRAME;
          vACTION = "../toancestry.html?url=" + escape(vACTION);

        } else if (Mode() == "orleans") { // new orleans record
          vACTION = "http://content.ancestry.com/Browse/view.aspx?dbid=7484&iid=LA";
          vACTION += SERIES;
          vACTION += "_";
          vACTION += ROLL;
          vACTION += "-";
          vACTION += FRAME;
          vACTION = "../toancestry.html?url=" + escape(vACTION);

        } else if (Mode() == "bost") { // boston record
          vACTION = "http://content.ancestry.com/Browse/view.aspx?dbid=8745&iid=MA";
          vACTION += SERIES;
          vACTION += "_";
          vACTION += ROLL;
          vACTION += "-";
          vACTION += FRAME;
          vACTION = "../toancestry.html?url=" + escape(vACTION);

        } else if (Mode() == "galv") { // galveston record
          vACTION = "http://content.ancestry.com/Browse/view.aspx?dbid=8722&iid=TXM1359_";
          vACTION += ROLL;
          vACTION += "-";
          vACTION += FRAME;
          vACTION = "../toancestry.html?url=" + escape(vACTION);

        } else if (Mode() == "phil") { // philadelphia record
          vACTION = "http://content.ancestry.com/Browse/view.aspx?dbid=8769&iid=PA";
          vACTION += SERIES;
          vACTION += "_";
          vACTION += ROLL;
          vACTION += "-";
          vACTION += FRAME;
          vACTION = "../toancestry.html?url=" + escape(vACTION);

        } else { // ellis island record

//          vACTION = "http://www.ellisislandrecords.org/cgi-bin/tif2gif.exe?T=g:\\";
//          vACTION = "http://www.ellisislandrecords.org/cgi-bin/tif2gif.exe?T=\\\\192.168.4.229\\images\\"; // changed on 9-22-2006 to 227
//          vACTION = "http://www.ellisislandrecords.org/cgi-bin/tif2gif.exe?T=\\\\192.168.4.227\\images\\"; // changed on 9-22-2006 to 227
//          vACTION = "http://www.ellisisland.org/cgi-bin/tif2gif.exe?T=\\\\192.168.4.227\\images\\"; // changed on 9-22-2006 to 227
//          vACTION = "http://www.ellisisland.org/cgi-bin/tif2gif.exe?T=\\\\192.168.4.226\\images\\"; // changed on 5-4-2000 to 226
          vACTION = "http://www.ellisisland.org/cgi-bin/tif2gif.exe?T=\\\\192.168.100.11\\images\\"; // changed on 9-22-20095-4-2000 to 100.11
          vACTION += SERIES;
          vACTION += "-";
          if (ROLL == 1142) { // rolls 1142 and 1143 are reversed in the EIDB
            ROLL = 1143;
          } else if (ROLL == 1143) {
            ROLL = 1142;
          }
          if (ROLL == 1313) { // rolls 1313 and 1314 are reversed in the EIDB
            ROLL = 1314;
          } else if (ROLL == 1314) {
            ROLL = 1313;
          }
          if (ROLL == 1508) { // rolls 1508 and 1509 are reversed in the EIDB
            ROLL = 1509;
          } else if (ROLL == 1509) {
            ROLL = 1508;
          }
          if (ROLL >= 1519 && ROLL <= 1528) {
            ROLL--;
          } else if (ROLL == 1518) {
            ROLL = 1528;
          }
          if (ROLL == 1529) { // rolls 3088 and 3089 are reversed in the EIDB
            ROLL = 1530;
          } else if (ROLL == 1530) {
            ROLL = 1529;
          }
          if (ROLL == 3088) { // rolls 3088 and 3089 are reversed in the EIDB
            ROLL = 3089;
          } else if (ROLL == 3089) {
            ROLL = 3088;
          }
          if (ROLL == 3083) { // rolls 3083, 3149, and 3150 are mixed up in the EIDB
            ROLL = 3149;
          } else if (ROLL == 3149) {
            ROLL = 3150;
          } else if (ROLL == 3150) {
            ROLL = 3083;
          }
          if (ROLL == 3525) { // rolls 3525 has not been uploaded to the EIDB
            alert("Roll 3525 has not been uploaded to the EIDB");
            ROLL = 0;
          } else if (ROLL == 3526) { // roll 3526 was stored in the EIDB as 3525
            ROLL = 3525;
          }
          while (ROLL.length < 4) {
            ROLL = "0" + ROLL;
          }

          vACTION += ROLL;

          vACTION += "\\";
          vACTION += SERIES;
          vACTION += "-";

          index = formPROCESS.mSCALE.selectedIndex;
          SetCookie("mm_scale", index);
          var MAGNIFY = formPROCESS.mSCALE[index].value;

          vACTION += ROLL;
          vACTION += FRAME + ".TIF&S=";
          vACTION += MAGNIFY;

        }

        display = true;
        if (formPROCESS.nsSEPARATE.checked) {
          var windowFeatures =
            "resizable=yes,scrollbars=yes,toolbar=yes,menubar=yes";
          if (window.location.protocol == "file:") {
            windowFeatures = windowFeatures + ",location=yes";
          }
          OpenWindow(vACTION, "", "manifests");

        } else {
          if (!firstShow &&
            (navigator.userAgent.indexOf("Safari") != -1 ||
             navigator.userAgent.indexOf("Mac_PowerPC") != -1)) {
            // bug in safari and mac IE browsers
            // frame cannot be reloaded if it contains contents from another domain
            var s = (SERIES == "M237") ? 0 : 1;
            self.parent.location.replace
             ("mm.htm?series=" + s + "&roll=" + ROLL + "&frame=" + FRAME + "&display=true");
          } else {
            firstShow = false;
            self.parent.frames[ImageFrame].location.replace(vACTION);
          }
        }
      }

      function getURLToComputeEndFrame() {

        if (!DisplayEndFrame()) {
          return;
        }

        // check if value is already cached, in which case we don't need to compute it
        var index = GetIndexFromTable();
        var value = endFrameArray[index];
        var endFrame = self.parent.frames[EndFrame].document.endFrame;
        if (value != 9999) {
          // value is already cached
          endFrame.action = "";
          return;
        }

        // need to remove any previous query strings from location
        var location = self.parent.frames[EndFrame].document.location;
        var index = location.toString().indexOf("?");
        if (index != -1) {
          location = location.toString().substring(0,index);
        }

        // now generatate the URL
        var formPROCESS = self.parent.frames[HeadFrame].document.formPROCESS;
        var vACTION;
        vACTION = "http://stevemorse.org/goulnik/mm3.php?series=";
//        vACTION = "http://www.goulnik.com/eidb/mm3.php?series=";
        var SERIES ;
        if (Ellis() || Mode() == "bost" || Mode() == "balt" || Mode() == "orleans" || Mode() == "phil" || Mode() == "ny") {
          var index = formPROCESS.mSERIES.selectedIndex;
          SERIES = formPROCESS.mSERIES[index].value;
        } else if (Mode()=="castle") {
          SERIES = "M237";
        } else if (Mode() == "sanfran") {
          SERIES = "M1410";
        } else if (Mode() == "galv") {
          SERIES = "M1359";
        }
        vACTION += SERIES;
        vACTION += "&roll=";
        var ROLL = formPROCESS.mROLL.value;
        if (ROLL == 1142) { // rolls 1142 and 1143 are reversed in the EIDB
          ROLL = 1143;
        } else if (ROLL == 1143) {
          ROLL = 1142;
        }
        if (ROLL == 1313) { // rolls 1313 and 1314 are reversed in the EIDB
          ROLL = 1314;
        } else if (ROLL == 1314) {
          ROLL = 1313;
        }
        if (ROLL == 1508) { // rolls 1508 and 1509 are reversed in the EIDB
          ROLL = 1509;
        } else if (ROLL == 1509) {
          ROLL = 1508;
        }
        if (ROLL >= 1519 && ROLL <= 1528) {
          ROLL--;
        } else if (ROLL == 1518) {
          ROLL = 1528;
        }
        if (ROLL == 1529) { // rolls 3088 and 3089 are reversed in the EIDB
          ROLL = 1530;
        } else if (ROLL == 1530) {
          ROLL = 1529;
        }
        if (ROLL == 3088) { // rolls 3088 and 3089 are reversed in the EIDB
          ROLL = 3089;
        } else if (ROLL == 3089) {
          ROLL = 3088;
        }
        if (ROLL == 3083) { // rolls 3083, 3149, and 3150 are mixed up in the EIDB
          ROLL = 3149;
        } else if (ROLL == 3149) {
          ROLL = 3150;
        } else if (ROLL == 3150) {
          ROLL = 3083;
        }
        if (ROLL == 3525) { // rolls 3525 has not been uploaded to the EIDB
          ROLL = 0;
        } else if (ROLL == 3526) { // roll 3526 was stored in the EIDB as 3525
          ROLL = 3525;
        }
        while (ROLL.length < 4) {
          ROLL = "0" + ROLL;
        }
        vACTION += ROLL;
        vACTION += "&calledfrom=";
        vACTION += location;
        return vACTION;
      }

      function GetIndexFromTable() {
        var formPROCESS = self.parent.frames[HeadFrame].document.formPROCESS;
        var series;
        if (Ellis() || Mode() == "bost" || Mode() == "balt" || Mode() == "orleans" || Mode() == "phil" || Mode() == "ny") {
          series = formPROCESS.mSERIES[formPROCESS.mSERIES.selectedIndex].value;
        } else if (Mode() == "castle") {
          series = "M237";
        } else if (Mode() == "sanfran") {
          series = "M1410";
        } else if (Mode() == "galv") {
          series = "M1359";
        }
        var index = rollIndex(series, formPROCESS.mROLL.value, "");
        return index;

      }

      function resetEndFrameValue() {
        if (!DisplayEndFrame()) {
          return;
        }
        var endFrame = self.parent.frames[EndFrame].document.endFrame;
        var index = GetIndexFromTable();
        var startFrameValue = startFrameArray[index];
        var endFrameValue = endFrameArray[index];
        if (endFrameArray[index] != 9999) {
          endFrame.sFrame.value = startFrameArray[index];
          endFrame.eFrame.value = endFrameArray[index];
        } else {
          endFrame.sFrame.value = "wait...";
          endFrame.eFrame.value = "wait...";

          // Following line will fail on N6 when run locally.  Error message is
          //   The link to file:///d:/web/ellis/mm3.htm?... was blocked by security manager
          //   Remote content may not link to local content.
          self.parent.frames[EndFrame].document.location.replace(getURLToComputeEndFrame());
        }
      }

      var date;
      if (Mode() == "ellis") {
        date = "8970616"; // 1897 jun 16 for T series
      } else if (Mode() == "castle" || Mode() == "both") {
        date = "8501220"; // 1850 dec 20
      } else if (Mode() == "sanfran") {
        date = "8930501"; // 1893 may 1
      } else if (Mode() == "ny") {
        date = "8210107"; // 1821 jan 7
      } else if (Mode() == "balt") {
        date = "8920602"; // 1820 sep 2 for M series, 1892 jun 2 for T series
      } else if (Mode() == "orleans") {
        date = "9030108"; // 1820 jan 1 for M series, 1903 jan 8 for T series
      } else if (Mode() == "bost") {
        date = "820922"; // 1820 sep 22
      } else if (Mode() == "galv") {
        date = "8960114"; // 1896 jan 14
      } else if (Mode() == "phil") {
        date = "8830101"; // 1800 jan 1 for M series, 1883 jan 1 for T series
      } else if (Mode() == "postellis") {
        date = "9350101"; // 1935 jan 1
      }

      function getDateFromForm() {

        // dates are encoded as YYYMMDD where
        //    YYY is year-1000 (i.e., 1890 is 890)
        //    MM is month with January being 01 and December being 12
        //    DD is day of month, ranging from 1 to 31

        var formPROCESS = self.parent.frames[HeadFrame].document.formPROCESS;
        var index;

        index = formPROCESS.mYEAR.selectedIndex;
        date = formPROCESS.mYEAR[index].value;
        index = formPROCESS.mMONTH.selectedIndex;
        date += formPROCESS.mMONTH[index].value;
        index = formPROCESS.mDAY.selectedIndex;
        date += formPROCESS.mDAY[index].value;
      }

      var roll2date = [];
      var endFrameArray = [];
      var startFrameArray = [];

      function endFrameArrayInit(val, limit) {
        for (i=0; i< limit; i++) {
          endFrameArray[i] = val;
        }
      }

      function startFrameArrayInit(val, limit) {
        for (i=0; i< limit; i++) {
          startFrameArray[i] = val;
        }
      }

      function getRollFromDate() {
        var formPROCESS = self.parent.frames[HeadFrame].document.formPROCESS;
        getDateFromForm();
        var seriesIndex = -1;
        if (Ellis()) {
          seriesIndex = (date < "8970616") ? 0 : 1;
        } else if (Mode() == "bost") {
          seriesIndex = (date < "8910801") ? 0 : 1;
        } else if (Mode() == "balt") {
          seriesIndex = (date < "8920602") ? 0 : 1;
        } else if (Mode() == "orleans") {
          seriesIndex = (date < "9030108") ? 0 : 1;
        } else if (Mode() == "ny") {
          seriesIndex = (date < "8970616") ? 0 : 1;
        } else if (Mode() == "phil") {
          seriesIndex = (date < "8830101") ? 0 : 1;
        }
        if (seriesIndex != -1) {
          formPROCESS.mSERIES.selectedIndex = seriesIndex;
        }

        var series;
        if (Ellis() || Mode() == "bost" || Mode() == "balt" || Mode() == "orleans" || Mode() == "phil" || Mode() == "ny") {
          series = formPROCESS.mSERIES[formPROCESS.mSERIES.selectedIndex].value;
        } else if (Mode() == "castle") {
          series = "M237";
        } else if (Mode() == "sanfran") {
          series = "M1410";
        } else if (Mode() == "galv") {
          series = "M1359";
        }

        var index = rollIndex("", "", date);
        formPROCESS.mROLL.value = (roll2date[index].substring(1,5) - 0);
        // the "- 0" above converts the string to a number thereby stripping
        // out any leading zeroes
        formPROCESS.mFRAME.value = FirstFrame();
        resetEndFrameValue();
      }

      function getDateFromRoll() {
        var formPROCESS = self.parent.frames[HeadFrame].document.formPROCESS;
        getDateFromForm();
        var firstYear;
        if (Mode() == "ellis") {
          firstYear = 1892;
        } else if (Mode() == "castle" || Mode() == "both") {
          firstYear = 1850;
        } else if (Mode() == "ny") {
          firstYear = 1820;
        } else if (Mode() == "sanfran") {
          firstYear = 1893;
        } else if (Mode() == "balt") {
          firstYear = 1820;
        } else if (Mode() == "orleans") {
          firstYear = 1820;
        } else if (Mode() == "bost") {
          firstYear = 1820;
        } else if (Mode() == "galv") {
          firstYear = 1896;
        } else if (Mode() == "phil") {
          firstYear = 1800;
        }

        var series;
        if (Ellis() || Mode() == "bost" || Mode() == "balt" || Mode() == "orleans" || Mode() == "phil" || Mode() == "ny") {
          series = formPROCESS.mSERIES[formPROCESS.mSERIES.selectedIndex].value;
        } else if (Mode() == "castle") {
          series = "M237";
        } else if (Mode() == "sanfran") {
          series = "M1410";
        } else if (Mode() == "galv") {
          series = "M1359";
        }


        var index = rollIndex(series, formPROCESS.mROLL.value, "");
        formPROCESS.mYEAR.selectedIndex = roll2date[index+1].substring(0,3) - (firstYear - 1000);
        formPROCESS.mMONTH.selectedIndex = roll2date[index+1].substring(3,5) - 1;
        formPROCESS.mDAY.selectedIndex = roll2date[index+1].substring(5,7) - 1;

      }

      function getDate() {
        var formPROCESS = self.parent.frames[HeadFrame].document.formPROCESS;
        var firstYear;
        if (Mode() == "ellis") {
          firstYear = 1892;
        } else if (Mode() == "castle" || Mode() == "both") {
          firstYear = 1850;
        } else if (Mode() == "ny") {
          firstYear = 1820;
        } else if (Mode() == "sanfran") {
          firstYear = 1893;
        } else if (Mode() == "balt") {
          firstYear = 1820;
        } else if (Mode() == "orleans") {
          firstYear = 1820;
        } else if (Mode() == "bost") {
          firstYear = 1820;
        } else if (Mode() == "galv") {
          firstYear = 1896;
        } else if (Mode() == "phil") {
          firstYear = 1800;
        }

        var series;
        if (Ellis() || Mode() == "bost" || Mode() == "balt" || Mode() == "orleans" || Mode() == "phil" || Mode() == "ny") {
          series = formPROCESS.mSERIES[formPROCESS.mSERIES.selectedIndex].value;
        } else if (Mode() == "castle") {
          series = "M237";
        } else if (Mode() == "sanfran") {
          series = "M1410";
        } else if (Mode() == "galv") {
          series = "M1359";
        }

        var index = rollIndex(series, formPROCESS.mROLL.value, "");
        formPROCESS.mYEAR.selectedIndex = roll2date[index+1].substring(0,3) - (firstYear - 1000);
        formPROCESS.mMONTH.selectedIndex = roll2date[index+1].substring(3,5) - 1;
        formPROCESS.mDAY.selectedIndex = roll2date[index+1].substring(5,7) - 1;
        formPROCESS.mROLL.value = (roll2date[index].substring(1,5) - 0);
        // the "- 0" above converts the string to a number thereby stripping
        // out any leading zeroes
        formPROCESS.mFRAME.value = FirstFrame();
        resetEndFrameValue();
      }

      function rollIndex(series, roll, date) { // either date is null or series and roll are null
        if (roll != "") {
          if (roll.length > 4) { // prevent roll from getting to big
            roll = 9999;
          }
          while (roll.length < 4) {
            roll = "0" + roll;
          }
          var seriesRoll = series.charAt(0) + roll;
        }
        var first =0;
        var last = roll2date.length-2;
        while (true) {
          var delta = last-first;
          delta -= (delta%4); // get on a 4-element boundary so it is on a 2-element boundary after dividing by 2
          middle = first +(delta/2);
          var excess = 0;
          if (roll!="") {
            if (roll2date[middle]>seriesRoll) {
              excess = +1;
            } else if (roll2date[middle]<seriesRoll) {
              excess = -1;
            }
          } else {
            if (roll2date[middle+1]>date) {
              excess = +1;
            } else if (roll2date[middle+1]<date) {
              excess = -1;
            }
          }
          if (excess<0) {
            if (middle == first) {
              return first; // always return the one before
            }
            first = middle;
          } else if (excess>0) {
            if (middle == last) {
              return first; // always return the one before
            }
            last = middle;
          } else {
            return middle;
          }
        }
      }
