/********************************************************

Paypal Cart Helper

Original script and source from: 
    paypalhelper@aol.com
    http://members.aol.com/paypalhelper/

Modified/fixed 12/31/04 by Dave Cohen:
    dlcohen@alleycatsw.com
    http://www.alleycatsw.com
    
Very strange stuff with cookies - if close cart
window, or use Continue Shopping to close cart
window, then next time Add/View cart, cookies
no longer saved with that page. Only happens
when running locally (e:\dave\paypalcart\mystore.html)
and only if no other browser window is connected
to another site. Weird. Cookie bug somewhere.
********************************************************/

var ItemCategory = 0;             // item product category
var ItemQty = 0;
var ItemName = "";
var ItemCode = "";
var ItemHand = "";  // item handling charges
var ItemShip = "";  // item shipping charges
var MiscString = "";  // stuff not supported anywhere else.
var ItemOption1Name  = "";  // option name and value
var ItemOption1Value  = "";  // option name and value
var ItemOption2Name  = "";  // option name and value
var ItemOption2Value  = "";  // option name and value
var ItemPrice = 1;
var ItemImage  = "dummy.jpg";  // place for cart thumbnail image

var WindowParms = "scrollbars,location,resizable,status,menubar,toolbar";

var MaxItemsInCart = 16;  // max items in cart
var MaxCategories = 5;    // max number of categories allowed

var CategoryTotals = new Object (); // amt & qty totals by pcat

var TaxAmt = 0;
var ItemHandTotal = 0;      // item specific handling
var ItemShipTotal = 0;      // item specific shipping
var ItemQtyTotal = 0;
var ItemAmtTotal = 0;       // total price of items in cart

var HandTotal; 
var ShipTotal = 0;
var DiscAmt;

var Cook;                   // place for item cookie object

var GrandTotal;             // order grand total

var QtyPrcBkpts = new Array ();  // amount breakpoint
var QtyPrcPrcs  = new Array ();  // price at breakpoint

var MinQty = 0;             // minimum item quantity to order
var MaxQty = 1000000;       // maximum item quantity to order

var TotalItemQty = 0; // total number of items ordered

var CouponMatch = /drtp_([a-zA-Z]{4})_([0-9]{4})_([a|p])_([0-9]{2})?/;

function AddDesc(strn) 
{  // add to current description
  var c = "";
  if (strn.length <= 0 || strn == " ") 
  {
    return;
  }
  if (ItemName.length > 0) 
  {
    c = ", ";
  }
  ItemName += c + strn;
}

function AddMisc(strn) 
{  // add extra stuff to PayPal params
  var s = "&";
  if (strn.substring(0,1) == "&") 
  {
    s = "";
  }
  MiscString += s + escape(strn);
}

function SetItemOption1(nam, val) 
{  // set the value of 1st option
  ItemOption1Name = nam;
  ItemOption1Value = val;
}

function AddItemOption1(val) 
{  // add to the value in ItemOption1Value
  var c = "";
  if (val.length == 0 || val == " ") 
  {
    return;
  }
  if (ItemOption1Name.length == 0) 
  {
    ItemOption1Name = "opt1";
  }
  if (ItemOption1Value.length > 0) 
  {
    c = ", ";
  }
  ItemOption1Value += c + val;
}

function SetItemOption2(nam, val) 
{  // set the value of 2nd option
  ItemOption2Name = nam;
  ItemOption2Value = val;
}

function AddItemOption2(val) 
{  // add to the value in ItemOption2Value
  var c = "";
  if (val.length == 0 || val == " ") 
  {
    return;
  }
  if (ItemOption2Name.length == 0)
  {
    ItemOption2Name = "opt2";
  }
  if (ItemOption2Value.length > 0) 
  {
    c = ", ";
  }
  ItemOption2Value += c + val;
}

function SetItemPrice(strn) 
{  // set the current price
  ItemPrice = 0;
  if (DebugFlag)
  {
   strn /= DebugDivide;
  }
  AddItemPrice(strn);
}

function AddItemPrice(strn) 
{  // add to current price
  ItemPrice = Dollar(ItemPrice + strn*1.0);
}

function CalcInsurance(amt) 
{  // calculate insurance on an amount
//  it equals $2.20 + $1.00 per hundred
  if (amt == 0)
  {
    return 0;
  }      
  if (amt <= 50)
  {
    return 1.30;
  }
  return (2.20 + Math.floor (amt / 100.0));
}

function CallPaypalCart() 
{ // call the PayPal shopping cart
  var strn,cartwin;
  var blkcc = "";                  // check default settings
  if (MyCurrencyCode.length > 0)  // record currency entry 
    blkcc = blkcc + "&currency_code=" + MyCurrencyCode;
  if (MyCountryCode.length > 0)   // record user entry
    blkcc = blkcc + "&lc=" + MyCountryCode;
  if (MyPaypalCancelPath.length > 0)  // set cancel return path
    blkcc = blkcc + "&cancel_return=" + MyPaypalCancelPath;
  if (MyPaypalReturnPath.length > 0)  // set return path 
    blkcc = blkcc + "&return=" + MyPaypalReturnPath;
  if (MyPaypalPageStyle.length > 0)  // set display style
    blkcc = blkcc + "&page_style=" + MyPaypalPageStyle;
  strn = "https://www.paypal.com/cgi-bin/webscr?cmd=_cart&upload=1&business=";
  strn += GetBusiness() + blkcc + MiscString + BuildPaypalString();
  strn = strn.replace(/\%20/g, "+");
  ClearItem();
  if (WindowParms.search(/width/i) < 0)
  {
    GetWindowWidthHeight();
  }
  cartwin = window.open(strn, "paypal", WindowParms);
//  self.close();
}

function GetBusiness()
// just makes it a bit harder for spambots to get it...
{
 return(MyPPCId1 + MyPPCAt + MyPPCId2 + MyPPCDot + MyPPCType);   
}

function ViewCart() 
{ // call the local shopping cart view
  var cartwin;
  if (!CheckBrowser())
  {
    return;
  }
  var host = location.hostname;
  if (host.length > 0)
  {
    if (host.indexOf("drtpress") >= 0 || host.indexOf("alleycatsw") >= 0 || host.indexOf("davepc") >= 0 || host.indexOf("jacob") >= 0)
    {
    } 
    else 
    {
      alert("Invalid host"); 
      return;
    }
  }

  if (WindowParms.search(/width/i) < 0)
  {
    GetWindowWidthHeight();
  }
  document.location.href = "PPCcart.html";
//  cartwin = window.open ("PPCcart.html", "PPCcartWindow", WindowParms);
//  cartwin.focus(); //WHY DOES THIS CAUSE AN ERROR??
}

function CheckCoupon (coupon) 
{  // check for a discount coupon
  if (VerifyCoupon(coupon))
  {
    document.location.reload();  // show the latest info...
  }
  else
  {
    alert ("'" + coupon + "'  is not a valid coupon code!");
  }
}

function SetCoupon(coupon, coupondisc, couponamt)
{
  if ((coupondisc > 50) || (couponamt > 10)) // too much!
  {
    alert ("'" + coupon + "'  is not a valid coupon code!");
    return;
  }
  root.coupval = coupon;      // remember entered value
  root.store();
  return;
}
      
function GetCoupon()
{
  return root.coupval;
}

function CheckFlagChar (temp) 
{     // check for special flag char
  var pos;
  pos  = temp.indexOf ("@"); // is there a initial value?  
  if (pos >= 0)
  {
    SetItemPrice(temp.substring (pos + 1));
  }
  pos  = temp.indexOf ("+"); // is there a price adjustment?  
  if (pos >= 0)
  {
    AddItemPrice(temp.substring (pos + 1));
  }
  pos  = temp.indexOf ("%"); // is there a percent adjustment?  
  if (pos >= 0)
  {
    AddPrcnt (temp.substring (pos + 1));
  }
}

function CheckOrderOptions() 
{  // check if user has selected everything
  if (ItemAmtTotal < MyMinimumAmount || ItemQtyTotal < MyMinimumQuantity) 
  {  // check minimums
    alert ("You have not yet met the minimum order requirements!");
    return false;
  }
  if (root.getagree && !root.agree)
  {  // agree checkbox
    alert ('You must agree to terms!');
    return false;
  }
  return true;
}

function ClearItem() 
{  // wipe out the last entry
  ItemQty = 0;  // quantity
  ItemName = "";  // name
  ItemPrice = 0; // price
  ItemCode = "";  // item number
  ItemHand = 0;  // item handling charges
  ItemShip = 0;  // item shipping charges
  MiscString = "";  // extra data
  ItemOption1Name  = "";  // clear options
  ItemOption1Value  = "";  // clear options
  ItemOption2Name  = "";  // clear options
  ItemOption2Value  = "";  // clear options
  ItemImage  = "dummy.jpg";
  ItemCategory  = 0;
  MinQty  = 0;        // minimum item quantity
  MaxQty  = 1000000;  // max item quantity
}

function ClearCart() 
{     // zap all the cookies
  var i;
  for (i=1; i<MaxItemsInCart; i++) 
  {  // the data cookies
    RemoveItemFromCart(i);
  }
//  ClearCoupon();
  InitRootCookie(); // clears shipping, coupon!
}

function ClearCoupon()
// 12/30/04 dave cohen added
{
  if (root.coupval == null)
  {
    root.coupval = "";
  }
  if (root.coupval.length > 0)
  {
    root.coupval = "";
    root.getcoup = 1;
    root.store();
    document.location.reload();  // show the latest info...
  }
}

function RemoveItemFromCart(i) 
{  // knock out a specific entry
  Cook = new Cookie (document, "paycart" + i);
  Cook.load();
  InitItemCookie();
}

function Cookie(document, name, hours, path, domain, secure) 
{
  this.$document = document;  // required
  this.$name = name;          // required
  if (hours)
  {
    this.$expiration = new Date((new Date()).getTime() + hours * 3600000);
  }
  else
  {
    this.$expiration = null;
  }
  this.$path = "/";  // force, for now
  if (domain)
  {
    this.$domain = domain; 
  }
  else 
  {
    this.$domain = null;
  }
  if (secure) 
  {
    this.$secure = true;
  }
  else
  {
    this.$secure = false;
  }
}

function _Cookie_store() 
{  // store method of cookie object
  var cookieval = "";  // clear actual cookie value
  for(var prop in this) 
  {  // Ignore "$" properties, and methods
    if ((prop.charAt(0) == '$') || ((typeof this[prop]) == 'function')) 
    {
      continue;
    }
    if (cookieval != "")
    { 
      cookieval += '&';
    }
    cookieval += prop + ':' + escape(this[prop]);
  }

  var cookie = this.$name + '=' + cookieval;
  if (this.$expiration)
  {
    cookie += '; expires=' + this.$expiration.toGMTString();
  }
  if (this.$path)
  {
    cookie += '; path=' + this.$path;
  }
  if (this.$domain)
  {
    cookie += '; domain=' + this.$domain;
  }
  if (this.$secure)
  {
    cookie += '; secure';
  }
  if (root.dump)
  {           // cookie diagnostic dump
    alert(cookie.length + " chars - " + cookie);
  }
  this.$document.cookie = cookie;  // store with magic property
}

function _Cookie_load() 
{  // cookie load function
  var i;
  var allcookies = this.$document.cookie;
  if (allcookies == "")
  {
    return false;
  }

  // Now extract just the named cookie from that list.
  var start = allcookies.indexOf(this.$name + '=');
  if (start == -1)
  {
    return false;   // Cookie not defined for this page.
  }
  start += this.$name.length + 1;  // Skip name and equals sign.
  var end = allcookies.indexOf(';', start);
  if (end == -1)
  {
    end = allcookies.length;
  }
  var cookieval = allcookies.substring(start, end);

  var a = cookieval.split('&');  // array of name/value pairs.
  for(i=0; i < a.length; i++)  // Break each pair into an array.
  {
    a[i] = a[i].split(':');
  }
  for(i=0; i<a.length; i++)
  {
    this[a[i][0]] = unescape(a[i][1]);
  }

  return true;     // We're done, so return the success code.
}

function _Cookie_remove() 
{  // the remove method
  var cookie;
  cookie = this.$name + '=';
  if (this.$path)
  {
    cookie += '; path=' + this.$path;
  }
  if (this.$domain)
  {
    cookie += '; domain=' + this.$domain;
  }
  cookie += '; expires=Fri, 02-Jan-1970 00:00:00 GMT';

  this.$document.cookie = cookie;  // magic store
}

function Dollar(val) 
{  // force to valid dollar amount
  var str,pos,rnd=0;
  if (val < .995)
  {
    rnd = 1;  // for old Netscape browsers
  }
  str = escape (val*1.0 + 0.005001 + rnd);  // float, round, escape
  pos = str.indexOf (".");
  if (pos > 0)
  {
    str = str.substring(rnd, pos + 3);
  }
  return str;
}

function InitItemCookie() 
{  // zap a data cookie
  Cook.pcat = 0;
  Cook.qty  = 0;
  Cook.cod  = "";
  Cook.ihnd = 0;
  Cook.des  = "";
  Cook.op1n = "";  // option name and value
  Cook.op1v = "";
  Cook.op2n = "";
  Cook.op2v = "";
  Cook.prc  = 0;
  Cook.ozs  = 0;
  Cook.imgx = "dummy.jpg";
  Cook.store();    // stash it off
}

function InitRootCookie() 
{  // Build the base root cookie
  var i;
  root.taxpct  = 0; 
  root.taxtxt  = "";
  root.coupval = "";
  root.shiptxt = "";

  root.showcc = 1;
  root.dump = 0;
  root.getagree = 0;
  root.agree = 0;
  root.getcoup = 0;
  root.showimg = 0;
  root.showcat   = 0;
  root.getship = 0;
  root.gettax = 0;

  for (i=0; i<MaxCategories; i++) 
  {
    root["hn" + i] = 0;         // qty-based handling brkpts
    root["sn" + i] = 0;         // qty-based shipping brkpts
    root["pv" + 1] = 0;         // cart-quantity charges
    root["sv" + i] = 0;         // amt-based shipping bkpts
  }
  root.store();                 // record it all..
}

function PrintCart() 
{  // print out entire cart, and get cart totals
  var i,catix,tmp1,tmp2,s;
  var mytax, myb4tax;
  GrandTotal = 0;                   // Grand total
  TaxAmt = 0;                       // total cart tax
  ItemQtyTotal = 0;                 // total qty of items
  ItemHandTotal = 0;                // item specific handling
  ItemShipTotal = 0;                // item specific shipping
  ItemAmtTotal = 0;                 // total price of cart
  var thisdisc;

  for (i=0; i<MaxCategories; i++) 
  {  // init pcat totals
    CategoryTotals["a" + i] = 0;      // amount in this cat
    CategoryTotals["q" + i] = 0;      // quantity in this cat
    CategoryTotals["h" + i] = 0;      // handling in this cat
    CategoryTotals["s" + i] = 0;      // shipping in this cat
    CategoryTotals["d" + i] = 0;      // discount in this cat
  }

  for (i=1; i<MaxItemsInCart; i++) 
  {  // print all entries
    Cook = new Cookie (document, "paycart" + i);
    Cook.load();
    if (Cook.qty > 0) 
    {
      TotalItemQty += Cook.qty * 1.0;
      PrintItem(i);
    }
  }

  ItemAmtTotal = Dollar(ItemAmtTotal)*1.0;             // round, float

  HandTotal = 0;  // line display totals
  ShipTotal = 0;
  DiscAmt = 0;   

  var mynotax = 0;
  for (catix=0; catix<MaxCategories; catix++) 
  {                 // run product categories
    shiptot  = 0;                               // local pcat tots
    handtot  = 0;
    disctot  = 0;

    var qty = CategoryTotals["q" + catix]*1.0;             // quantity this category
    var amt = CategoryTotals["a" + catix]*1.0;             // amount this category
    if (!CatTaxable(catix))
    {
      mynotax += amt;
    }

    if (root["hn" + catix] > 0) 
    {
      tmp1 = root["hqty" + catix].split(",");
      tmp2 = root["hamt" + catix].split(",");
      for (i=root["hn" + catix]-1; i>=0; i--) 
      {  // run the table
        if (qty >= tmp1[i]*1.0) 
        {              // Check the quantity
          handtot = tmp2[i]*1.0;                  // yep, set it
          break;                             // a-dios
        }
      }
    }
    CategoryTotals["h" + catix] = handtot;
    HandTotal += handtot;

    if (root["sn" + catix] > 0) 
    {
      tmp1 = root["sqty" + catix].split(",");
      tmp2 = root["samt" + catix].split(",");
      // dave cohen - changed so charged per item shipping!
      if (tmp1[0] < 0)
      {
        shiptot = qty * tmp2;
      }
      else 
      {
        // in use now!!!
        for (i=root["sn" + catix]-1; i>=0; i--) 
        {  // run the table
          if (qty >= tmp1[i]*1.0) 
          {              // Check the price
            shiptot = tmp2[i]*1.0;                  // yep, set it
            break;
          }
        }
      }
    }
    if ((shiptot == 0) && root["sv" + catix] > 0) {   // one or the other
      tmp1 = root["sval" + catix].split(",");
      tmp2 = root["schg" + catix].split(",");
      for (i=root["sv" + catix]-1; i>=0; i--) 
      {  // run the table (if one)
        if (amt >= tmp1[i]*1.0) 
        {  // Check the price
          shiptot = tmp2[i]*1.0;      // yep, set it
          break;
        }
      }
    }
    if ((shiptot == 0) && root["pv" + catix] > 0) 
    { // only one shipping
      tmp1 = root["pval" + catix].split(",");
      tmp2 = root["pper" + catix].split(",");
      for (i=root["pv" + catix]-1; i>=0; i--) 
      {  // run the table (if one)
        if (amt >= tmp1[i]*1.0) 
        {      // Check the price
          shiptot = amt * tmp2[i]/100;      // yep, set it
          break;
        }
      }
    }
    CategoryTotals["s" + catix] = shiptot;
    ShipTotal += shiptot;

/*
    if (root.coupval == null)
    {
      root.coupval = "";
    }
    if ((root.coupval.length > 0) && IsCouponForThisCategory(root.coupval,catix))
    {
      thisdisc = 0;
      coupdisc = GetCouponDiscount(root.coupval);
      coupamt = GetCouponAmount(root.coupval);
      if (coupdisc > 0)
      {
        thisdisc = amt * coupdisc/100.0;  // percent discount
      }
      else if (coupamt > 0)
      {
        thisdisc = qty * coupamt;   // amount discount
      }
      if (thisdisc > amt)
      {
        thisdisc = amt;
      }
      disctot += thisdisc;
    }

    CategoryTotals["d" + catix] = disctot;
    DiscAmt += disctot;
*/    
    DiscAmt += CategoryTotals["d" + catix];
  }
//  DiscAmt = (Math.round(DiscAmt * 100))/100; // some rounding

  HandTotal += ItemHandTotal;
  ShipTotal += ItemShipTotal;

  myb4tax = ItemAmtTotal - DiscAmt; // - mynotax;
  mytax = (myb4tax - mynotax) * root.taxpct/100.0; // tax after discount applied

  TaxAmt = Dollar (mytax);
  GrandTotal = Dollar (myb4tax + mytax + HandTotal + ShipTotal); // - DiscAmt);
}

function CatTaxable(catix)
{
  if (catix > (MyCatTaxable.length-1))
  {
    return false;
  }
  return (MyCatTaxable[catix]);
}

function PrintItem(i) {  // make one entry in cart
  var tm,t1,t2;
  var coupamt, coupdisc, thisamt, thisprc, thisqty, thisdisc, prcdisc;
  document.writeln ('<tr valign = "top"');
  document.writeln ('    align = "right">');
  document.writeln ('  <td class="OrderDetailLine">');
  document.writeln ('    <input name="delete_item_' + i + '" type  = "checkbox" ');
  document.writeln ('           value = "DeleteFromCartBox"');
  document.writeln ('           onclick = "RemoveItemFromCart(', i, ');');
  document.writeln ('                      location.reload();" />');
  document.writeln ('  </td>');
  document.writeln ('  <td class="OrderDetailLine" align = "right">' + Cook.qty + '</td>');
  if (root.showcat) 
  {
    document.writeln ('  <td class="OrderDetailLine" align = "right">' + Cook.pcat + '</td>');
  }
  document.writeln ('  <td class="OrderDetailLine" align = "left">' + Cook.cod + '</td>');
  document.writeln ('  <td class="OrderDetailLine" align = "left">' + Cook.des);
  if (Cook.ihnd > 0) 
  {  // item-specific handling charges
    document.writeln (' (' + Dollar(Cook.ihnd) + ' hand each)');
    ItemHandTotal += Cook.ihnd*1.0;
  }
  if (Cook.ishp > 0) {  // item-specific shipping charges
    document.writeln (' (' + Dollar(Cook.ishp) + ' ship each)');
    ItemShipTotal += Cook.ishp * Cook.qty;
  }
  if (Cook.op1n.length > 0) 
  {  // see if we append stuff
    document.writeln (', ' + Cook.op1n + ' ' + Cook.op1v + ' ' + Cook.op2n + ' ' + Cook.op2v);
  }
  document.writeln ('</td>');
  tm = Dollar (Cook.prc);
  t1 = Cook.qty*1.0;
  t2 = Cook.pcat;
  document.writeln ('  <td class="OrderDetailLine">',
    tm,'</td>');
  tm = Dollar(t1*Cook.prc);
  ItemAmtTotal += tm*1.0;
  ItemQtyTotal += t1;
  CategoryTotals["a" + t2] = CategoryTotals["a" + t2] + tm*1.0;
  CategoryTotals["q" + t2] = CategoryTotals["q" + t2] + t1;
  document.writeln ('  <td class="OrderDetailLine">' + tm + '</td>');

  var imgstr = "";
  if (root.showimg) 
  {  // display images?
    imgstr = '<img src = "' + Cook.imgx + '" border="0"';
    if (root.showimgw) 
    {
      imgstr += ' width="80"';
    }
    if (root.showimgh) 
    {
      imgstr += ' height="60"';
    }
    imgstr += ' alt = "Image: Item" />';
    document.writeln ('  <td class="OrderDetailLine" align = "center">', imgstr, '  </td>');
  }
  document.writeln ('</tr>');

  // paypal gets details per item, so need to apply discount per item to avoid rounding issues
  if ((root.coupval != null) && (root.coupval.length > 0) && IsCouponForThisCategory(root.coupval,t2))
  {
    thisdisc = 0;
    coupdisc = GetCouponDiscount(root.coupval);
    coupamt = GetCouponAmount(root.coupval);
    thisprc = Cook.prc;
    thisqty = Cook.qty;
    thisamt = thisprc * thisqty;
    if (coupdisc > 0)
    {
      prcdisc = (Math.round(thisprc * coupdisc))/100;
      thisdisc = thisqty * prcdisc;
    }
    else if (coupamt > 0)
    {
      thisdisc = thisqty * coupamt;   // amount discount
    }
    if (thisdisc > thisamt)
    {
      thisdisc = thisamt;
    }
    CategoryTotals["d" + Cook.pcat] += thisdisc;
  }

}

function ReadForm(obj1) 
{ //get form data for PayPal
  var i,j,obj,temp,pos,val,nam3,nam4;
  var qty  = 0;              // default value
  var dis  = 0;              // quantity discount
  
  for (i=0; i<obj1.length; i++) 
  {     // run whole form
    obj = obj1.elements[i];           // ref particular element
    nam3 = obj.name.substring (0, 3); // 3-char name (maybe)
    nam4 = obj.name.substring (3, 4); // where to store it
    if (obj.type == "select-one") 
    {   // dropdowns
      pos = obj.selectedIndex;        // which option selected
      val = obj.options[pos].value;   // get selection
      CheckFlagChar(val);                   // check for flag char
      if (nam3 == "opt") 
      {            // user says where to store
        Where (val, nam4);            // stash it
      } 
      else 
      {
        AddDesc (val);                // add to data
      }
    } 
    else if (obj.type == "select-multiple") 
    {     // one or more
      for (j=0; j<obj.options.length; j++) 
      { // run all options
        if (obj.options[j].selected) 
        {
          val = obj.options[j].value;
          CheckFlagChar(val);                   // flag chars?
          if (nam3 == "opt") 
          {            // user says where to store
            Where (val, nam4);            // stash it
          } 
          else 
          {
            AddDesc (val);                // add to data
          }
        }
      }
    } 
    else if (obj.type == "checkbox" || obj.type == "radio") 
    {
      if (obj.checked) 
      {             // was selected
        val = obj.value;
        CheckFlagChar(val);                // flag chars?
        if (nam3 == "opt") 
        {         // user says where to store
          Where (val, nam4);         // stash it
        } 
        else if (val.length > 0) 
        {
          AddDesc (val);             // add to data
        }
      }
    } 
    else if (obj.type == "text" || obj.type == "textarea") 
    {  // user input fields
      val = obj.value;             // get input
      if (obj.name == "qty") 
      {     // this is the quantity
        qty = val;                 // get user input
        if (!IsANumber(qty))
        {  // test
          alert ("Enter a valid integer quantity!");
          return false;
        }
      } 
      else 
      {
        if (nam3 == "opt") 
        { // user says where to store
          Where (val, nam4); // stash it
        } 
        else 
        {
          AddDesc (val);     // add to data
        }
      }
    }
  }  // end of loop

  if (qty == 0)
  {
    qty = 1;     // make sure we have something
  }
  if (qty < MinQty) 
  {          // minimum items ordered?
    alert ("You must order at least " + MinQty + " of this item!");
    return false;
  }
  if (qty > MaxQty) 
  {          // maximum items that can be ordered
    alert ("You cannot order more than " + MaxQty + " of this item!");
    return false;
  }
  ItemQty = qty;               // record for posterity

  for (i=QtyPrcBkpts.length-1; i>=0; i--) 
  {  // qty amount?
    if (qty >= QtyPrcBkpts[i]) 
    {    // qty brkpt
      SetItemPrice(QtyPrcPrcs[i]);    // force it
      AddDesc("Amt");
      break;                 // get out, now
    }
  }

  StoreCart();
  if (!MyShowCartOnAdd) 
  {
//    alert("Item has been added to cart!");
    return false;            // hide cart display
  }
  return true;
}

function SetCartAmtShip(pcat, a1, c1) 
{   // set cart amt shp brkpts
  var i,sv;
  var sval = new Array ();
  var schg = new Array ();
  if (pcat >= MaxCategories) 
  {          // check him out
    alert ("SetCartAmtShip category too big!");
    return;
  }
  sv = 0;                      // count of breakpoints
  for (i=1; i<arguments.length; i=i+2) 
  {
    sval[sv] = arguments[i];   // price breakpoint
    schg[sv] = arguments[i+1]; // discount amount
    sv = sv + 1;               // number of bkpts
  }
  root["sv" + pcat]   = sv;    // stash that bad boy off
  root["sval" + pcat] = sval.toString();
  root["schg" + pcat] = schg.toString();
  root.store();                // remember forever...
}

function SetCartHand(pcat, q1, c1) 
{  // set cart hand breakpoints
  var i,hn;
  var hamt = new Array ();
  var hqty = new Array ();
  if (pcat >= MaxCategories) 
  {          // check him out
    alert ("SetCartHand category too big!");
    return;
  }
  hn = 0;                      // count of breakpoints
  for (i=1; i<arguments.length; i=i+2) 
  {
    hqty[hn] = arguments[i];   // price breakpoint
    hamt[hn] = arguments[i+1]; // discount amount
    hn = hn + 1;               // number of bkpts
  }
  root["hn" + pcat] = hn;      // stash that bad boy off
  root["hqty" + pcat] = hqty.toString();
  root["hamt" + pcat] = hamt.toString();
  root.store();                // remember forever...
}

function SetCartShip(pcat, q1, c1) 
// if qty < 0, shipping per item
{  // set cart shp qty breakpoints
  var i,sn;
  var sqty = new Array ();
  var samt = new Array ();
  if (pcat >= MaxCategories) 
  {          // check him out
    alert ("SetCartShip category arg too big!");
    return;
  }
  sn = 0;                      // count of breakpoints
  for (i=1; i<arguments.length; i=i+2) 
  {
    sqty[sn] = arguments[i];   // price breakpoint
    samt[sn] = arguments[i+1]; // handling charge
    sn = sn + 1;               // number of bkpts
  }
  root["sn" + pcat] = sn;      // stash that bad boy off
  root["sqty" + pcat] = sqty.toString();
  root["samt" + pcat] = samt.toString();
  root.store();                // remember forever...
}

function SetCartTaxNC (obj1) 
{    // set cart tax value
  if (obj1.checked)
  {
    root.taxpct = MyTaxRate;
    root.taxtxt = MyTaxText;
  }
  else
  {
    root.taxpct = "0.00";
    root.taxtxt = "0.00"; // not blank, so not asked to select
  }
  root.store();                // remember forever...
  document.location.reload();  // show the latest info...
}

function SetCartMsg (obj1) 
{    // set cart message
  root.msg = obj1.value;
  root.store();                // remember forever...
  document.location.reload();  // show the latest info...
}

function SetItemCode(cd) 
{ // set product code
  ItemCode = cd;
}

function SetItemDesc (strn) 
{  // set the desc field
  ItemName = strn;
}

function SetItemHand(amt) 
{  // set item-specific handling charges
  ItemHand = amt;    // set local variable
  AddItemPrice(amt); // add in the price
}

function SetItemImage (strn) 
{  // set the image for the cart
  ItemImage = strn;
}

function SetItemCategory(val) 
{
  if (val >= MaxCategories) 
  {
    alert ("Only " + MaxCategories + " product categories allowed!\n\nCorrect your HTML!");
    return;
  }
  ItemCategory = val;
}

function SetAmtPctShip(pcat, a1, p1) 
{   // % of amt-based shipping brkpts
  var i,pv;
  var pval = new Array ();
  var pper = new Array ();
  if (pcat >= MaxCategories) 
  {          // check him out
    alert ("SetAmtPctShip category too big!");
    return;
  }
  pv = 0;                      // count of breakpoints
  for (i=1; i<arguments.length; i=i+2) 
  {
    pval[pv] = arguments[i];   // price breakpoint
    pper[pv] = arguments[i+1]; // discount amount
    pv = pv + 1;               // number of bkpts
  }
  root["pv" + pcat]   = pv;    // stash that bad boy off
  root["pval" + pcat] = pval.toString();
  root["pper" + pcat] = pper.toString();
  root.store();                // remember forever...
}

function SetQtyAmt(q1, a1) 
{      // set qty amount breakpoints
  var i;
  var an = 0;                      // count of breakpoints
  for (i=0; i<arguments.length; i=i+2) 
  {
    QtyPrcBkpts[an] = arguments[i];   // quantity
    QtyPrcPrcs[an] = arguments[i+1]; // amount
    an = an + 1;               // number of discount bkpts
  }
}

function SetMinQty (q) 
{           // set minimum item quantity
  MinQty = q;
}

function SetMaxQty (q) 
{           // set maximum item quantity
  MaxQty = q;
}

function SetItemShip(amt) 
{  // set item specific shipping amount
  ItemShip = amt;    // set local variable
}

function StoreCart() 
{  // store data in local cart
  var i;
  for (i=1; i<MaxItemsInCart; i++) 
  {      //check for dup entry
    Cook = new Cookie (document, "paycart" + i);  // run
    Cook.load();                // get values
    if (Cook.qty*1.0 > 0) {     // check it out - combine dups
      if (Cook.cod == ItemCode &&  // check everything!!!
          Cook.des == ItemName &&
          Cook.prc*1.0 == ItemPrice*1.0 &&
          Cook.op1n == ItemOption1Name &&
          Cook.op1v == ItemOption1Value &&
          Cook.op2n == ItemOption2Name &&
          Cook.pcat == ItemCategory &&
          Cook.op2v == ItemOption2Value) 
      {
        Cook.qty = Cook.qty*1.0 + ItemQty*1.0;  // combine
        Cook.store();
        ClearItem();
        return;                 // th-th-thats all, folks
      }
    }
  }
  for (i=1; i<MaxItemsInCart; i++) 
  {  // find empty entry
    Cook = new Cookie (document, "paycart" + i);
    Cook.load();
    if (Cook.qty*1.0 == 0 || isNaN (Cook.qty)) 
    {
      Cook.pcat = ItemCategory
      Cook.qty  = ItemQty;
      Cook.cod  = ItemCode;
      Cook.des  = ItemName;
      Cook.ihnd = ItemHand;
      Cook.ishp = ItemShip;
      Cook.op1n = ItemOption1Name;
      Cook.op1v = ItemOption1Value;
      Cook.op2n = ItemOption2Name;
      Cook.op2v = ItemOption2Value;
      Cook.prc  = ItemPrice;
      Cook.imgx = ItemImage;
      Cook.store();
      ClearItem();
      if (i == (MaxItemsInCart - 1))
        alert ("Warning - that was your last cookie!");
      return;      
    }
  }
  alert ("Error 1 - out of cookies!");
}

function Where(val, loc) 
{  // store val at opt[loc]
  if (loc == 1)
  {
    AddOption1(val);
  }
  else
  {
    AddOption2(val);
  }
}

function BuildPaypalString() 
{         // build the PayPal string
  var i,j,pc,sx;
  var tot  = 0;               // price total
  var frst = 1;               //  1st time thru marker
  var str  = "";              // string to PayPal
  var disc = new Array ();    // price per item to subtract for discount
  var discamt;
  var tmps = ""; 
  tmps = AddLine(tmps, GetCouponText());

  if (TaxAmt > 0)
  {             // do we have a calculated tax
    str = "&tax_cart=" + Dollar(TaxAmt);  // yep - stick it in
    // Note: Paypal user needs to login before tax shows up in total!
  }
  
  for (i=0; i<MaxCategories; i++) 
  {  // set item discounts
    disc[i] = CategoryTotals["d" + i] / CategoryTotals["q" + i];  // discount per item
  }
  j = 0;       // starting suffix
  for (i=1; i<MaxItemsInCart; i++) 
  {  // run all the data cookies
    Cook = new Cookie (document, "paycart" + i);
    Cook.load();         // get contents
    if (Cook.qty > 0) {  // something here
      j = j + 1;         // bump suffix
      str += "&quantity_"    + j + "=" + Cook.qty;
      str += "&item_name_"   + j + "=" + escape (Cook.des);
      str += "&amount_"      + j + "=" + 
                   Dollar (Cook.prc*1.0 - disc[Cook.pcat]);
      if (Cook.op1n.length > 0) 
      {    // 1st option present
        str += "&on0_"       + j + "=" + escape(Cook.op1n);
        str += "&os0_"       + j + "=" + escape(Cook.op1v);
      } 
      if (Cook.op2n.length > 0) 
      {    // 2nd option present
        str += "&on1_"       + j + "=" + escape (Cook.op2n);
        str += "&os1_"       + j + "=" + escape (Cook.op2v);
      }
      if (tmps.length > 0) // only show ship, tax, coupon if not have both options
      {
        if (Cook.op1n.length <= 0)
        {
          str += "&on0_"       + j + "=Details\n";
          str += "&os0_"       + j + "=" + escape(tmps);
        }
        else if (Cook.op2n.length <= 0)
        {
          str += "&on1_"       + j + "=Details\n";
          str += "&os1_"       + j + "=" + escape(tmps);
        }
      }
      if (Cook.cod != "")
      {
        str += "&item_number_" + j + "=" + escape (Cook.cod);
      }
      if (frst > 0 && (HandTotal > 0)) 
      {
        str += "&handling_" + j + "=" + Dollar (HandTotal*1.0);
      }
      if (frst > 0 && ShipTotal > 0) 
      {
        str += "&shipping_"  + j + "=" + Dollar (ShipTotal);
      }
      else
      {
        str += "&shipping_"  + j + "=0";
      }

      frst = 0;  // set to false - true only on 1st item
    }    
  }
//alert(str);  
  return str;
}

function Shipper(obj1) 
{  // use either amt or qty based shipping1
  /* Note - when using something other than SetCartAmtShip you must include
  SetAmtSH (0,0,0); within every position to kill shipping question. 
  AND, every call used here must have a zero call under the worst area.*/
  var pos;
  var amt = -1;
  var peritem = -1;
  var amtdiv = 1;
  var amtarr = [];

  if (DebugFlag)
  {
   amtdiv = DebugDivide;
  }

  SetCartAmtShip(0);          // assume the worst
  SetCartShip(0);
  SetAmtPctShip(0);
  SetCartAmtShip(1);          // assume the worst
  SetCartShip(1);
  SetAmtPctShip(1);
  SetCartAmtShip(2);          // assume the worst
  SetCartShip(2);
  SetAmtPctShip(2);
  SetCartAmtShip(3);          // assume the worst
  SetCartShip(3);
  SetAmtPctShip(3);
  SetCartAmtShip(4);          // assume the worst
  SetCartShip(4);
  SetAmtPctShip(4);
  pos = obj1.selectedIndex;  // option selected
  root.shiptxt = obj1.options[pos].text; 

  if      (pos == 0) 
  { // media mail shipping
    amtarr = MyShippingMedia;
  } 
  else if (pos == 1) 
  { // next day shipping
    amtarr = MyShippingPriority;
  } 
  else if (pos == 2) 
  { // canada shipping
    amtarr = MyShippingCanada;
  } 
  else if (pos == 3) 
  { // international shipping
    amtarr = MyShippingInternational;
  } 
  else if (pos == 4) 
  { // specify shipping per item
    amt = window.prompt("Specify custom shipping amount for each item", MyShippingMedia[0]);
    if (!IsANumber(amt))
    {
      amt = MyShippingMedia[0];
    }
    SetCartShip(1, 1, amt/amtdiv, 2, 2*amt/amtdiv, 3, 3*amt/amtdiv, 4, 4*amt/amtdiv, 5, 5*amt/amtdiv, 6, 6*amt/amtdiv);
    SetCartShip(4, 1, amt/amtdiv, 2, 2*amt/amtdiv, 3, 3*amt/amtdiv, 4, 4*amt/amtdiv, 5, 5*amt/amtdiv, 6, 6*amt/amtdiv);
  } 
  else if (pos == 5) 
  { // specify shipping total
    amt = window.prompt("Specify custom shipping amount total", MyShippingMedia[0]);
    if (!IsANumber(amt))
    {
      amt = MyShippingMedia[0];
    }
    SetCartShip(1, 1, amt/amtdiv); 
    SetCartShip(4, 1, amt/amtdiv); 
  } 
  else
  {
      amtarr = MyShippingMedia;
  }
  if (amt < 0)
  {
    SetCartShip(1, 1, amtarr[0]/amtdiv, 2, amtarr[1]/amtdiv, 3, amtarr[2]/amtdiv, 4, amtarr[3]/amtdiv, 5, amtarr[4]/amtdiv, 6, amtarr[5]/amtdiv);
    SetCartShip(4, 1, amtarr[0]/amtdiv, 2, amtarr[1]/amtdiv, 3, amtarr[2]/amtdiv, 4, amtarr[3]/amtdiv, 5, amtarr[4]/amtdiv, 6, amtarr[5]/amtdiv);
  }
  
//  CheckFreeShipping();
  document.location.reload();  // show the latest info...
}

function LoadIt() 
{
// executed at load time
  Cookie.prototype.store  = _Cookie_store;   // load proto methods
  Cookie.prototype.load   = _Cookie_load;
  Cookie.prototype.remove = _Cookie_remove;
  
  Cook = new Cookie (document, "paycart1");
  Cook.load();
  if (!Cook.qty) 
  {  //create the structure
    root = new Cookie (document, "paycart0");  // root cookie
    root.load();
    InitRootCookie();
    for (var i=1; i<MaxItemsInCart; i++) 
    {  // load or init data cookies
      Cook = new Cookie (document, "paycart" + i);
      InitItemCookie();              // create it
    }
  }
  root = new Cookie(document, "paycart0");  // root cookie
  root.load();
}

function GetWindowWidthHeight() 
{
  var myWidth = 0, myHeight = 0;
  if( typeof( window.innerWidth ) == 'number' ) {
    //Non-IE
    myWidth = window.innerWidth;
    myHeight = window.innerHeight;
  } else if( document.documentElement &&
      ( document.documentElement.clientWidth || document.documentElement.clientHeight ) ) {
    //IE 6+ in 'standards compliant mode'
    myWidth = document.documentElement.clientWidth;
    myHeight = document.documentElement.clientHeight;
  } else if( document.body && ( document.body.clientWidth || document.body.clientHeight ) ) {
    //IE 4 compatible
    myWidth = document.body.clientWidth;
    myHeight = document.body.clientHeight;
  }
  WindowParms += ",width=" + myWidth + ",height=" + myHeight;
}

var BrowserString;
var BrowserUserAgent;
var BrowserName;
var BrowserVersion;
var BrowserOS;
var BrowserStringIndex;

var BROWSER_UNKNOWN   = 0;
var BROWSER_MSIE      = 1;
var BROWSER_NETSCAPE  = 2;
var BROWSER_OPERA     = 3;
var BROWSER_KONQUEROR = 4;
var BROWSER_OMNIWEB   = 5;
var BROWSER_WEBTV     = 6;
var BROWSER_ICAB      = 7;
var BROWSER_SAFARI    = 8;

var BROWSEROK_UNKNOWN = 0;
var BROWSEROS_WINDOWS = 1;
var BROWSEROS_LINUX   = 2;
var BROWSEROS_UNIX    = 3;
var BROWSEROS_MAC     = 4;

function CheckBrowser()
{
  GetBrowserAndVersion();
  if      (BrowserName == BROWSER_MSIE)
  {
    if (BrowserVersion >= 4)
    {
      return 1;
    }
  }
  else if (BrowserName == BROWSER_NETSCAPE)
  {
    if (BrowserVersion >= 5)
    {
      return 1;
    }
  }
  else if (BrowserName == BROWSER_KONQUEROR)
  {
    return 1;
  }
  else if (BrowserName == BROWSER_SAFARI)
  {
    return 1;
  }
  else if (BrowserName == BROWSER_OPERA)
  {
    if (version >= 7)
    {
      return 1;
    }
  }
  alert("This browser/version will not correctly display the order form.\n\nPlease contact us at " + MyEmail + " for orders.");
  return 0;  
}

function GetBrowserAndVersion()
{
  BrowserUserAgent = navigator.userAgent.toLowerCase();
  var os,browser,version;

  if (GetBrowserIndex('konqueror'))
  {
    browser = BROWSER_KONQUEROR;
    os = BROWSEROS_LINUX;
  }
  else if (GetBrowserIndex('safari'))
  {
    browser = BROWSER_SAFARI;
  }
  else if (GetBrowserIndex('omniweb'))
  {
    browser = BROWSER_OMNIWEB;
  }
  else if (GetBrowserIndex('opera'))
  {
    browser = BROWSER_OPERA;
  }
  else if (GetBrowserIndex('webtv'))
  {
    browser = BROWSER_WEBTV;
  }
  else if (GetBrowserIndex('icab'))
  {
    browser = BROWSER_ICAB;
  }
  else if (GetBrowserIndex('msie'))
  {
    browser = BROWSER_MSIE;
  }
  else if (!GetBrowserIndex('compatible'))
  {
    browser = BROWSER_NETSCAPE;
	version = BrowserUserAgent.charAt('Mozilla'.length+1);
  }
  else 
  {
    browser = BROWSER_UNKNOWN;
  }

  if (!version) 
  {
    version = BrowserUserAgent.charAt(BrowserStringIndex + BrowserString.length);
  }

  if (!os)
  {
	if (GetBrowserIndex('linux'))
    {
      os = BROWSEROS_LINUX;
    }
	else if (GetBrowserIndex('x11'))
    {
      os = BROWSEROS_UNIX;
    }
	else if (GetBrowserIndex('mac'))
    { 
      os = BROWSEROS_MAC;
    }
	else if (GetBrowserIndex('win'))
    {
      os = BROWSEROS_WINDOWS;
    }
	else 
    {
      os = BROWSEROS_UNKNOWN;
    }
  }
  BrowserName = browser;
  BrowserOS = os;
  BrowserVersion = version;
}

function GetBrowserIndex(string)
{
  BrowserStringIndex = BrowserUserAgent.indexOf(string) + 1;
  BrowserString = string;
  return BrowserStringIndex;
}

function SetAgree()
{
  root.agree=1;
  root.store();
  document.location.reload();
}

function IsANumber(val)
{
  if ((val == "") || (val < .00) || (isNaN (val))) 
  {
    return 0;
  }
  return 1;
}

function GetCouponText()
{
  var val;
  if (root.coupval.length)
  {
    val = GetCouponAmount(root.coupval);
    if (val <= 0) val = GetCouponDiscount(root.coupval) + "%";
    return "Coupon=" + root.coupval + ":" + val;
  }
  return "";
}

function GetTaxText()
{
  if (root.taxtxt.length > 0)
  {
    return "Tax=" + root.taxtxt;
  }
  return "";
}

function GetShipText()
{
  if (root.shiptxt.length > 0)
  {
    return "Ship=" + root.shiptxt;
  }
  return "";
}

function AddLine(currtext, newtext)
{
  if (newtext.length <= 0)
  {
    return currtext;
  }
  if (currtext.length > 0)
  {
    currtext += "\n"; // would like to have newline here
  }
  return currtext + newtext;
}

function VerifyCoupon(coupon,dontoverwrite)
// Verify coupon format, return true if valid
{
  if (coupon == null) return 0;
  coupon = coupon.replace(/\s/g,"");
  if (coupon.length <= 0)
  {
    return 0;
  }
  // format: drtp_xxxx_nnnn_z_cc
  //   drtp = fixed
  //   xxxx = some identifier
  //   nnnn = value * 100
  //   z = a for amount, p for percent
  //   cc = category
  if (coupon == "clear") 
  {
    SetCoupon("", 0, 0);
    return 1;
  }
  var carr = coupon.match(CouponMatch);
  if (carr)
  {
    if (IsANumber(carr[2]))
    {
      if (carr[3] == "a")
      {
        SetCoupon(coupon, 0, carr[2]/100);
        return 1;
      }
      else
      {
        SetCoupon(coupon, carr[2]/100, 0);
        return 1;
      }
    }
  }
  return 0;
}

function IsCouponForThisCategory(coupon, category)
{
  var carr = coupon.match(CouponMatch);
  if (carr.length < 4) return 0; 
  if (carr[4].length == 0) return 1; // not specified for category
  couponcategory = parseInt(carr[4]);
  category = parseInt(category);
  if ((couponcategory == 0) || (couponcategory == category)) return 1;
  return 0;
}

function GetCouponDiscount(coupon)
{
  var carr = coupon.match(CouponMatch);
  if (carr.length < 4) return 0; 
  if (IsANumber(carr[2]))
  {
    if (carr[3] == "p")
    {
      return(carr[2]/100);
    }
  }
  return 0;
}

function GetCouponAmount(coupon)
{
  var carr = coupon.match(CouponMatch);
  if (carr.length < 4) return 0; 
  if (IsANumber(carr[2]))
  {
    if (carr[3] == "a")
    {
      return(carr[2]/100);
    }
  }
  return 0;
}

function GetQueryString()
// Parse querystring, store the name/value pairs in properties of an object, return that object.
{
  var argname, argvalue, pos, ix;
  var args = new Object();
  var query = location.search.substring(1); 
  var pairs = query.split("&");
  var str = "";
  for (ix = 0; ix < pairs.length; ix++)
  {
    pos = pairs[ix].indexOf('=');
    if (pos < 0)
    {
      continue;
    }
    argname = pairs[ix].substring(0,pos);
    argvalue = (pairs[ix].substring(pos+1)).replace(/\+/g, " ");
    args[argname] = unescape(argvalue);
    str = str + " " + argname + "=" + argvalue;
  }
  return args;
}

