//
//   Support for ezi-merchant interface
//
//   V.B.McKee Mar 2006
//
//   Copyright � 2006 KeeTech Ltd. All rights reserved.
//

function setTaxButtonsHere()
{
  var domBtn = getDomesticButton(1);
  var intBtn = getInternationalButton(1);
  var strTgt = 'window.location = window.location.pathname;';
  var strRep = 'propagateIntoPID();';

  // swap string contents
  domBtn.replace(strTgt,strRep);
  intBtn.replace(strTgt,strRep);

  // write out to document
  document.write(domBtn);
  document.write(intBtn);
}

function simpleUpdatePID(blnPidList)
{
  // Read from form
  var pidtype = parseInt(document.form_1.pidtype.value);
  var pidvalue = (pidtype & 0xFFF);
  var discode = document.form_1.elements["discode"].value;
  
  // Pid may be in a list
  if(blnPidList)
  {
    // May be first time
    if(parseInt(document.form_1.pidtype.options[0].value) == -1)
    {
      // Remove the 'no selection' option from list
      document.form_1.pidtype.options[0] = null;
    }
  }
    
  // Read from database
  var a1 = getBaseProductDB(pidvalue);

  // Try to validate discount codes
  if(validateDiscountCode(a1[9],a1[10],a1[11],discode)) pidvalue = setProductDiscount(pidvalue);

  // Set values on form      
  document.form_1.pid.value = pidvalue;
  document.form_1.elements["DiscountCode"].value = discode;

  // Update displayed price value  
  /*var priceTag = document.getElementById("prodprice");
  priceTag.firstChild.nodeValue = getProductPrice("�","\,",2,".",false, true, document.form_1.pid.value,"inc VAT within United Kingdom","inc VAT within United Kingdom","International Orders",0,true);
*/
  // Update displayed price information  
/*  var priceTagInfo = document.getElementById("prodpriceinfo");
  priceTagInfo.firstChild.nodeValue = getPriceInfo(document.form_1.pid.value,"inc VAT within United Kingdom","inc VAT within United Kingdom","International Orders",0,true);*/
}

function propagateIntoPID()
{
  // Read from form
  var pidtype = parseInt(document.form_1.pidtype.value);
  var specfx = parseInt(document.form_1.specfx.value);
  var physfrm = parseInt(document.form_1.physfrm.value);
  var pidvalue = (pidtype & 0xFFF) + ((specfx & 0xF) << 14) + ((physfrm & 0xFFF) << 18);
  var discode = document.form_1.elements["discode"].value;

  // Read from database
  var a1 = getBaseProductDB(pidvalue);
  var a2 = getProcessingDB(pidvalue);
  var a3 = getPhysFormatDB(pidvalue);

  // Try to validate discount codes
  if(validateDiscountCode(a1[9],a1[10],a1[11],discode)) pidvalue = setProductDiscount(pidvalue);
  if(validateDiscountCode(a2[9],a2[10],a2[11],discode)) pidvalue = setProcessDiscount(pidvalue);
  if(validateDiscountCode(a3[9],a3[10],a3[11],discode)) pidvalue = setPhysicalDiscount(pidvalue);  

  // Set values on form      
  document.form_1.pid.value = pidvalue;
  document.form_1.elements["PhysicalForm"].value = getPhysicalForm(parseInt(document.form_1.elements["pid"].value))[1];
  document.form_1.elements["SpecialEffects"].value = getSpecialEffects(parseInt(document.form_1.elements["pid"].value))[1];
  document.form_1.elements["DiscountCode"].value = discode;

  // Update displayed price value  
  if(document.referrer == 'http://pics2posters.co.uk/upload_graphics.php')
  {
	   var priceTag = document.getElementById("prodprice");
  //priceTag.firstChild.nodeValue = getProductPrice("£","\,",2,".",false, true, document.form_1.pid.value,"inc VAT within United Kingdom","inc VAT within United Kingdom","International Orders",0,true);

  // Update displayed price information  
  var priceTagInfo = document.getElementById("prodpriceinfo");
  priceTagInfo.firstChild.nodeValue = getPriceInfo(document.form_1.pid.value,"inc VAT within United Kingdom","inc VAT within United Kingdom","International Orders",0,true);
  }
  else
  {
  var priceTag = document.getElementById("prodprice");
  priceTag.firstChild.nodeValue = getProductPrice("£","\,",2,".",false, true, document.form_1.pid.value,"inc VAT within United Kingdom","inc VAT within United Kingdom","International Orders",0,true);

  // Update displayed price information  
  var priceTagInfo = document.getElementById("prodpriceinfo");
  priceTagInfo.firstChild.nodeValue = getPriceInfo(document.form_1.pid.value,"inc VAT within United Kingdom","inc VAT within United Kingdom","International Orders",0,true);
  }
}

function aspectTests()
{
  // Do checks on aspect ratio, image size, resolution, etc in response to changes in physfrm1
  var thisEnum = getRankedIndex(parseInt(document.form_1.physfrm1.options[document.form_1.physfrm1.selectedIndex].value));
  var physWide = getSizeMM(thisEnum)[0];
  var physHigh = getSizeMM(thisEnum)[1];
  var pictWide = parseInt(document.form_1.photowide.value);
  var pictHigh = parseInt(document.form_1.photohigh.value);
  var pictSize = parseInt(document.form_1.photosize.value);
  var blnUnitsOK = true;
  var pictRotated = false;
  var pictLowRatio = false;
  var pictBadRatio = false;
  var pictLowDpi = false;
  var pictBadDpi = false;
  var pictLowMeg = false;
  var pictBadMeg = false;
  var testDpi = 0;
  var testMeg = 0;
  var strNote = Array("Please Note:-");
  var strWarn = Array("","","");

  // Tolerances on aspect
  var tolRatioLow = 1.041;
  var tolRatioBad = 1.081;

  // Tolerances on data size in bytes/square mm or Mbytes/sq metre
  var tolMegLow = 1; 
  var tolMegBad = 0.25; 
  
  // Tolerances on DPI
  var tolDpiLow = 32;
  var tolDpiBad = 16;

  // If original input dimensions are not available
  if((pictWide <= 1) || (pictHigh <= 1))
  {
    blnUnitsOK = false;
    pictWide = parseInt(document.form_1.thumbwide.value);
    pictHigh = parseInt(document.form_1.thumbhigh.value);
  }
  
  // if output dimensions are available
  if((physWide > 1) && (physHigh > 1))
  {
    // if input dimensions are available
    if((pictWide > 1) && (pictHigh > 1))
    {
      // Find output aspect ratio
      var physRatio = physHigh/physWide;
    
      // Find input aspect ratio, etc
      var pictRatio = pictHigh/pictWide;
      var fraction00 = (physRatio - pictRatio)/pictRatio;
      var fraction90 = ((1.0/physRatio) - pictRatio)/pictRatio;
      var aspectErr = fraction00;

      // Test ratios for other than best fit
      if((fraction00 * fraction00) > (fraction90 * fraction90))
      {
        // Best fit if rotated
        pictRotated=true;
        var pictTemp = pictWide;
        pictWide = pictHigh;
        pictHigh = pictTemp;
        pictRatio = pictHigh/pictWide;
        aspectErr = fraction90;
        
        // Append to warning
        strNote[strNote.length] = "";
        strNote[strNote.length] = "Image will be rotated 90 degrees at print time for best fit.";        
      }
      
      // Is the aspect ratio mismatched
      if((aspectErr * aspectErr) > ((tolRatioBad - 1) * (tolRatioBad - 1)))
      {
        // Note this for later
        pictBadRatio = true;

        // Add to warning
        strNote[strNote.length] = "";
        strNote[strNote.length] = "The aspect ratio of your image is not a good match to paper/canvas sizes.";      
        strNote[strNote.length] = "We need to 'fit' your image to the paper or canvas before printing it.";            
        strNote[strNote.length] = "This will involve your image being cropped at time of print.";
        strNote[strNote.length] = "Our graphics experts will use their judgement to do this for you.";            
        strNote[strNote.length] = "If you prefer, you may choose from these standard fitting methods :-";            
        strNote[strNote.length] = "";
        strNote[strNote.length] = "'Fit largest' expands the image until either width or height matches.";            
        strNote[strNote.length] = "This method works by allowing free space in the un-fitted direction.";            
        strNote[strNote.length] = "";
        strNote[strNote.length] = "'Fit smallest' expands the image until there is no free space.";            
        strNote[strNote.length] = "This method works by clipping the image in the un-fitted direction.";            
        strNote[strNote.length] = "";
        strNote[strNote.length] = "'Fit to paper' stretches the image and forces it to match the paper.";            
        strNote[strNote.length] = "This method scales the image height and width by different amounts.";            
        strNote[strNote.length] = "";
        strNote[strNote.length] = "You can specify your preferred method in the 'Additional Info' section.";            
      }
      else if((aspectErr * aspectErr) > ((tolRatioLow - 1) * (tolRatioLow - 1)))
      {
        // Note this for later
        pictLowRatio = true;

        // Add to warning
        strNote[strNote.length] = "";
        strNote[strNote.length] = "Some cropping is necessary to fit your image to the paper/canvas size.";      
        strNote[strNote.length] = "Our graphics experts use their judgement to do this for you.";
        strNote[strNote.length] = "If this compromises the quality of the print we will contact you before processing.";            
      }
      
      // Report any problems thus far
      if(pictRotated || pictBadRatio || pictLowRatio)
      {
        // Report disabled for now
        // popnow(strNote);
      }      

      // Find DPI according to aspect ratio
      if(pictRatio > 1)
      {
        testDpi = 25.4 * pictHigh/physHigh;
      }
      else
      {
        testDpi = 25.4 * pictWide/physWide;
      }
      
      // Test for bad or low dpi, if possible
      if((testDpi < tolDpiBad) && blnUnitsOK)
      {
        // Note this for later
        pictBadDpi = true;

        // Add to warning
        strWarn[strWarn.length] = "";
        strWarn[strWarn.length] = "Your image lacks the resolution to print it at the current size.";      
        strWarn[strWarn.length] = "Required image size " + parseInt(tolDpiLow * physWide / 25.4) + " x " + parseInt(tolDpiLow * physHigh / 25.4) + " (bigger is better).";        
        strWarn[strWarn.length] = "Your image size is  " + parseInt(pictWide) + " x " + parseInt(pictHigh) + " (seems far too small).";        
        strWarn[strWarn.length] = "We can still print your image but for better results please choose a larger image.";        
      }           
      else if((testDpi < tolDpiLow) && blnUnitsOK)
      {
        // Note this for later
        pictLowDpi = true;

        // Add to warning
        strWarn[strWarn.length] = "";
        strWarn[strWarn.length] = "Your image may lack the resolution to print it at the current size.";      
        strWarn[strWarn.length] = "Expected image size " + parseInt(tolDpiLow * physWide / 25.4) + " x " + parseInt(tolDpiLow * physHigh / 25.4) + " (bigger is better).";        
        strWarn[strWarn.length] = "Your image size is  " + parseInt(pictWide) + " x " + parseInt(pictHigh) + " (seems too small).";        
        strWarn[strWarn.length] = "We can still print your image but for better results please choose a larger image.";        
      }           
    }
    
    // if input size is available
    if((pictSize > 0) && blnUnitsOK)
    {
      // Can compute detail level (if done in mm)
      testMeg = pictSize/(physWide * physHigh);
      if(testMeg < tolMegBad)
      {
        // Note this for later
        pictBadMeg = true;

        // Add to warning
        strWarn[strWarn.length] = "";
        strWarn[strWarn.length] = "Your image lacks the file size to print it at the current size.";      
        strWarn[strWarn.length] = "Expected image data " + asmegs(tolMegLow * physWide * physHigh) + " Mbytes. (bigger is better)";                  
        strWarn[strWarn.length] = "Your image data is  " + asmegs(pictSize) + " Mbytes. (seems far too small)";
        strWarn[strWarn.length] = "We can still print your image but for better results please choose a larger image.";        
      }
      else if(testMeg < tolMegLow)
      {
        // Note this for later
        pictLowMeg = true;

        // Add to warning
        strWarn[strWarn.length] = "";
        strWarn[strWarn.length] = "Your image may lack the file size to print it at the current size.";      
        strWarn[strWarn.length] = "Expected image data " + asmegs(tolMegLow * physWide * physHigh) + " Mbytes. (bigger is better)";                  
        strWarn[strWarn.length] = "Your image data is  " + asmegs(pictSize) + " Mbytes. (seems too small)";
        strWarn[strWarn.length] = "We can still print your image but for better results please choose a larger image.";        
      }
    }
    
    // Set html page traffic lights
    setTrafficLight("dpicell", "dpicheck", pictBadDpi, pictLowDpi, "WEAK", "FAIR", "GOOD");
    setTrafficLight("megcell", "megcheck", pictBadMeg, pictLowMeg, "WEAK", "FAIR", "GOOD");
    setTrafficLight("aspcell", "aspcheck", pictBadRatio, pictLowRatio, "WEAK", "FAIR", "GOOD");

    // May have a major problem
    if(pictLowDpi || pictBadDpi || pictLowMeg || pictBadMeg)
    {    
      // Set header as required
      if(pictBadDpi || pictBadMeg)
      {
        strWarn[0] = "------ PROBLEM ------ PROBLEM ------ PROBLEM ------";
        strWarn[2] = "Your image will give POOR QUALITY RESULTS at the current print size.";               
      }
      else
      {
        strWarn[0] = "------ WARNING ------ WARNING ------ WARNING ------";
        strWarn[2] = "Your image will give FAIR QUALITY RESULTS at the current print size.";               
      }

      // Report
      // Disabled for now
      //popnow(strWarn);

    }      

    // Set explanatory table
    setTextTable("weaktabl","weaktext",(pictBadDpi || pictBadMeg || pictBadRatio));
  }
}

function asmegs(nBytes)
{
  var megs = nBytes/1000000;
  return megs.toFixed(2);  
}

function setTrafficLight(strCellName, strTextName, blnBad, blnLow, strBad, strLow, strGood)
{
  // Get the tag
  var cellTag = document.getElementById(strCellName);
  var textTag = document.getElementById(strTextName);

  // According to the conditions
  if(blnBad)
  {
    cellTag.setAttribute("bgColor","Red");
    textTag.firstChild.nodeValue = strBad;
  }
  else if(blnLow)
  {
    cellTag.setAttribute("bgColor","Yellow");
    textTag.firstChild.nodeValue = strLow;
  }      
  else
  {
    cellTag.setAttribute("bgColor","Lime");
    textTag.firstChild.nodeValue = strGood;
  }      
}

function setTextTable(strTablName, strTextName, blnOn)
{
  // Get the tag
  var tablTag = document.getElementById(strTablName);
  var textTag = document.getElementById(strTextName);

  // According to the conditions  
  if(tablTag)  
  {
    if(blnOn)
    {
      tablTag.setAttribute("border","1");
    }
    else
    {
      tablTag.setAttribute("border","0");
    }      
  }
  if(textTag)  
  {
    if(blnOn)
    {
      textTag.style.color ="#000000";
    }
    else
    {
      textTag.style.color ="#FFFFFF";
    }      
  }
}

function popnow(strMsg)
{
	// Alert from string array
	var strSumm="";

	// Assemble the elements into a string with crlf
	for(i=0;(i < strMsg.length);i++)
	{
		strSumm = strSumm + strMsg[i] + "\r\n";
	}
	
	// Pop the alert now
  alert(strSumm);
}

function validateDiscountCode(dateS,dateF,codeOK,codeThis)
{
  // Create date objects
  var dateSt = new Date(usDateString(dateS));
  var dateFn = new Date(usDateString(dateF));
  var dateTd = new Date();

  // Allow 6hrs grace period on expiry
  dateFn.setHours(dateFn.getHours() + 6);

  var strSt = dateSt.toDateString();
  var strFn = dateFn.toDateString();
  var strNow = dateTd.toDateString();
  
  // May not have started yet
  if(dateTd < dateSt) return false;
  
  // May have expired 
  if(dateTd > dateFn) return false;

  // Create stripped, lowercase version
  codeOK = stripSpace(codeOK).toLowerCase();

  // Invalid if empty or space strings or none
  if(codeOK === "") return false;
  if(codeOK === "none") return false;

  // Create known hash codes, enforce lower case
  var hashNull = hex_md5("").toLowerCase();
  var hashNone = hex_md5("none").toLowerCase();

  // Invalid if hash code for empty or space strings or none  
  if(codeOK === hashNull) return false;
  if(codeOK === hashNone) return false;
  
  // Create a regexp to exclude non-(alpha-numeric or white space)
  var regSep = /[^a-zA-Z0-9\s]/g;

  // Substitute any stray characters for spaces
  codeThis = codeThis.replace(regSep," ");
  
  // Strip excess space from the supplied code(s)  
  codeThis = fullTrim(codeThis).toLowerCase();

  // Split supplied code by 'space' character
  var arrCode = codeThis.split(" ");
  
  // If any codes were found
  if(arrCode.length > 0)
  {
    // Scan through supplied codes
    for (var i = 0; i < arrCode.length; i++)
    {
      // Slight speedup
      codeThis = arrCode[i];
      
      // Ignore duff codes
      if(codeThis === "") continue;
      if(codeThis == "none") continue;
      if(codeThis === hashNull) continue;
      if(codeThis == hashNone) continue;
      
      // Correct discount code must match
      if(hex_md5(codeThis).toLowerCase() === codeOK) return true;
    }
  }
  
  // No matching codes
  return false;       
}

function usDateString(strD)
{
  // Split to parts
  var aD = strD.split("-");  
  
  // Reassemble
  return aD[1]+ " " + aD[0] + ", " + aD[2];
}

function emptySelect(thisSel,blnWithNull)
{
  // load a specific state into select boxes
  while (thisSel.length > 0)
  {
    thisSel.options[0] = null;
  }

  // May need a null list item
  if(blnWithNull)
  {
     thisSel.options[0] = new Option("No Selection", -1);
  }  
}

function filterSelectAR()
{
  // Use available details
  var thisSel = document.form_1.physfrm1;
  var thisWide = parseInt(document.form_1.photowide.value);
  var thisHigh = parseInt(document.form_1.photohigh.value);
  var arTol = 1.08;
  
  // If original input dimensions are not available
  if((thisWide <= 1) || (thisHigh <= 1))
  {
    thisWide = parseInt(document.form_1.thumbwide.value);
    thisHigh = parseInt(document.form_1.thumbhigh.value);
  }
  
  // Test for duff values
  if(thisWide <= 0.0) return;
  if(thisHigh <= 0.0) return;
  if(thisWide/thisHigh > 10) return;
  if(thisHigh/thisWide > 10) return;  
  var arTarget = thisHigh/thisWide;
  
  // May need to force the aspect to < 1 i.e. landscape
  if(thisHigh > thisWide)
  {
    arTarget = thisWide/thisHigh;
  }  

  // Count how many pass the test
  var intPass = filterSelectCountAR(thisSel,arTarget,arTol,false);
  
  // Need at least one pass
  if(intPass > 0)
  {
    filterSelectCountAR(thisSel,arTarget,arTol,true);
  }
}

function filterSelectCountAR(thisSel,arTest,arTol,blnRemove)
{
  var listDims = Array(0,0,0);
  var intPos=0;
  var intPass=0;
  var arPos=0.0;

  // loop through the possibles
  for (var i = 0; i < thisSel.length; i++)
  {
    // Get list items
    intPos = parseInt(thisSel.options[i].value);
    
    // Check for null
    if(intPos > -1)
    {
      // Get index
      listDims = getSizeMM(getRankedIndex(intPos));

      // Make into a ratio
      if((listDims[0] > 0) && (listDims[1] > 0))
      {
        // get ratio
        arPos = listDims[1]/ listDims[0];

        // May need inverting
        if(arPos > 1)
        {
          arPos = 1.0/arPos;
        }
        
        // Now test vs target
        if((arPos-arTest) * (arPos-arTest) < (arTol-1) * (arTol-1) * arTest * arTest)
        {
          intPass ++;
        }
        else
        {
          if(blnRemove)
          {
            // remove and count-back
            thisSel.options[i] = null;
            i --;
          }
        }
      }
    }
    
    // May be none left to test
    if(i > thisSel.length - 1)
    {
      break;
    }
  }
  
  // done
  return intPass;
}

function filterSelectPhysDesc(strTest)
{
  // Use available details
  var thisSel = document.form_1.physfrm1;
  
  // Test for duff values
  strTest = trim(strTest);
  if(strTest === "") return;
  if(strTest.length < 2) return;
  
  // Count how many pass the test
  var intPass = filterSelectCountPhysDesc(thisSel,strTest,false);
  
  // Need at least one pass
  if(intPass > 0)
  {
    filterSelectCountPhysDesc(thisSel,strTest,true);
  }
}

function filterSelectCountPhysDesc(thisSel,strTest,blnRemove)
{
  var strD=Array(""); 
  var strDesc="";
  var intPos=0;
  var intPass=0;

  // use lower case
  strTest = strTest.toLowerCase();
      
  // loop through the possibles
  for (var i = 0; i < thisSel.length; i++)
  {
    // Get list items
    intPos = parseInt(thisSel.options[i].value);
    
    // Check for null
    if(intPos > -1)
    {
      // Get descriptive array based on index 
      strD = getPhysicalForm(getPhysFormatProdID(getPhysFormatIndex(getRankedIndex(intPos))));

      // Pick out descriptive string, use lower case
      strDesc = strD[1].toLowerCase();
        
      // Now test vs target
      if((strDesc.indexOf(strTest) > -1))
      {
        intPass ++;
      }
      else
      {
        if(blnRemove)
        {
          // remove and count-back
          thisSel.options[i] = null;
          i --;
        }
      }
    }
    
    // May be none left to test
    if(i > thisSel.length - 1)
    {
      break;
    }
  }
  
  // done
  return intPass;
}

function loadPhotoCartDefaults(blnParty)
{
  // regexp for white space
  var whtspc = /\s/g;
  
  // test current pid
  var testPid = parseInt(document.form_1.pidtype.value);
  if(testPid === 0)
  {
    // Try to get an image specifier, weed out white space
    var strSpec = document.form_1.elements["ImageSpecifier"].value;
    strSpec = strSpec.replace(whtspc,"");
    
    // must not be empty or pitifully short
    if(strSpec.length > 2)
    {
      // use lower case
      strSpec = strSpec.toLowerCase();
  
      // test for known types
      if((strSpec.indexOf("fixed/") > -1) || (strSpec.indexOf("unique/") > -1))
      {
        // try to get a PID based on name
        loadPidFromName();
      }
    }
  }
  
  // Strip prefix from specifier
  strSpec = document.form_1.elements["ImageSpecifier"].value;
  strSpec = strSpec.replace("/upthumbs/thm_","");
  document.form_1.elements["ImageSpecifier"].value = strSpec;
          
  // if this is not for party posters
  if(blnParty == false)
  {
    fillProcessSelect(0);
  }
  
  // load state from root of tree
  loadState1(1);
  
  // if this is not for party posters
  if(blnParty)
  {
    filterSelectPhysDesc("Party");
  }
  else
  {
    // Filter out inappropriate aspect ratios
    filterSelectAR();
  }
  
  // Deliberately select this
  document.form_1.physfrm1.selectedIndex = 1;
  stateChange1();
}

function loadBaseCartDefaults(pidS,pidF,selThis)
{
  // load base products into pidtype select box
  fillSelectBoxRange(document.form_1.pidtype,pidS,pidF,selThis,false);
  
  // Now update based on selected item
  simpleUpdatePID(true);
}

function loadFixedCartDefaults()
{
  // load pidtype
  loadPidFromName();
  
  // adjust price, etc
  simpleUpdatePID(false);
}

function loadPidFromName()
{
  // regexp for white space
  var whtspc = /\s/g;

  // get the partial name
  var strSpec = document.form_1.elements["ImageSpecifier"].value;
  var strTest = "";
  
  // use lower case, minus white space
  strSpec = unescape(strSpec);
  strSpec = strSpec.toLowerCase();
  strSpec = strSpec.replace(whtspc,"");
 
  // loop through the possibles
  for (var i = 1; i < 32768; i++)
  {
    // Get index
    var intID = getBaseProductIndex(i);
   
    // May have reached the end
    if(intID == -1)
    {
      // bale out of loop
      break;
    }
    else
    {
      // Get test strings
      strTest = getBaseProductDesc(intID);
      
      // use lower case and shortened version
      strTest[2] = unescape(strTest[2]);
      strTest[2] = strTest[2].toLowerCase();
      strTest[2] = strTest[2].replace(".jpg","");
      strTest[2] = strTest[2].replace(whtspc,"");
      
      // must not be empty or pitifully short
      if(strTest[2].length > 2)
      {
        if(strSpec.indexOf(strTest[2]) > -1)
        {      
          // set pidtype
          document.form_1.pidtype.value = intID;
         
          // also set proddesc
          var elemDesc = document.getElementById("proddesc");
          elemDesc.firstChild.nodeValue = strTest[1];
          
          // skip out of loop
          i=32768;
        }
      }
    }
  }    
}

function stateChange1()
{
  var thisState = parseInt(document.form_1.physfrm1.options[document.form_1.physfrm1.selectedIndex].value);

  // update rest of chain, if required
  if(thisState > -1)
  {
    // May be first time
    if(parseInt(document.form_1.physfrm1.options[0].value) == -1)
    {
      // Remove the 'no selection' option from list
      document.form_1.physfrm1.options[0] = null;
    }
    
    // Carry this into next select box
    loadState2(thisState);

    // Check aspect ratio etc, if possible
    aspectTests();
  } 
}

function stateChange2()
{
  var thisState = parseInt(document.form_1.physfrm2.options[document.form_1.physfrm2.selectedIndex].value);

  // update rest of chain, if required
  if(thisState > -1) loadState3(thisState);
}

function stateChange3()
{
  var thisState = parseInt(document.form_1.physfrm3.options[document.form_1.physfrm3.selectedIndex].value);

  // update rest of chain, if required
  if(thisState > -1) 
  {
    // update next in chain
    document.form_1.physfrm.value = getPhysFormatIndex(getRankedIndex(thisState));
    
    // propagate
    propagateIntoPID();  
  }
}

function loadState1(intState)
{
  // load a specific state into select boxes
  var arrNodes1 = getSelTree1(intState);
  fillFormatSelect(document.form_1.physfrm1,arrNodes1, 0, 0, true);
  stateChange1();
}

function loadState2(intState)
{
  // load a specific state into select boxes
  var arrNodes2 = getSelTree2(intState);
  fillFormatSelect(document.form_1.physfrm2,arrNodes2, 1, 0, false);
  stateChange2();
}

function loadState3(intState)
{
  // load a specific state into select boxes
  var arrNodes3 = getSelTree3(intState);
  fillFormatSelect(document.form_1.physfrm3,arrNodes3, 2, 0, false);
  stateChange3();
}

function fillFormatSelect(thisSel, arrNode, ofsText, selThis, blnWithNull)
{    
  // Empty first
  emptySelect(thisSel, blnWithNull);
  
  // load a specific state into select boxes
  for (var i = 0; i < arrNode.length ; i++)
  {
    // Get index
    var intID = getPhysFormatProdID(getPhysFormatIndex(getRankedIndex(arrNode[i])));
    
    // Add item
     thisSel.options[thisSel.length] = new Option(getPhysFormatDesc(intID)[ofsText],arrNode[i]);
  }
  
  // May need to select item
  if((selThis > -1) && (selThis < thisSel.length )) 
  {
    thisSel.selectedIndex = selThis;
  }
}

function fillProcessSelect(selThis)
{    
  var thisSel = document.form_1.specfx;
  
  // Empty first
  emptySelect(thisSel,false);

  // load a specific set into select boxes
  for (var i = 1; i < 32768; i++)
  {
    // Get index
    var intID = getProcessingIndex(i);
   
    // May have reached the end
    if(intID == -1)
    {
      // bale out of loop
      break;
    }
    else
    {
      // Add item
      thisSel.options[thisSel.length] = new Option(getSpecialEffects(getProcessingProdID(intID))[1],intID);
    }
  }
  
  // May need to select item
  if((selThis > -1) && (selThis < thisSel.length )) 
  {
    thisSel.selectedIndex = selThis;
  }
}

function fillSelectBoxRange(thisSel,pidS,pidF,selThis,withNul)
{    
  // Empty first
  emptySelect(thisSel,withNul);

  // load a specific base product pid range into select boxes
  for (var i = 1; i < 32768; i++)
  {
    // Get index
    var intID = getBaseProductIndex(i);
   
    // May have reached the end
    if(intID == -1)
    {
      // bale out of loop
      break;
    }
    else
    {
      // If this is in the specified range
      if((intID >= pidS) && (intID <= pidF))
      {
        // Add item
        thisSel.options[thisSel.length] = new Option(getProductInfo(getBaseProductProdID(intID))[1],intID);
      }
    }
  }
  
  // May need to select item
  if((selThis > -1) && (selThis < thisSel.length )) 
  {
    thisSel.selectedIndex = selThis;
  }
}

