<!------- hide the script from old browsers

function dhtml_check() {
  W3C = (document.getElementById) ? 1 : 0; 
  IE4 = (document.all) ? 1 : 0; 
  NS4 = (document.layers) ? 1 : 0; 
  // set browser specific items for javascript using layers
  if (W3C) { // netscape 6 (gecko) or greater - DOM specific object variables
    layerRef = "document.getElementById('";
    layerEnd = "')";
    layerStyle = "').style";
    layerText = "').innerHTML";
    visible = '.visibility = "visible"';
    hidden = '.visibility = "hidden"';
    zlevel = '.zindex';
    pxunits = 'px';
    okMouse = okMenu = true;
  }
  else if (NS4) { // netscape 4 - DOM specific object variables
    window.onResize = reloadIt;// patch for netscape window resizing problem
    layerRef = "document.layers['";
    layerEnd = "']";
    layerStyle = "']";
    visible = '.visibility = "show"';
    hidden = '.visibility = "hide"';
    zlevel = '.zIndex';
    pxunits = 'px';
    okMouse = okMenu = true;
  }
  else if (IE4) { // msie 4 or greater - DOM specific object variables
    layerRef = "document.all['";
    layerEnd = "']";
    layerStyle = "'].style";
    //layerText = "'].innerHTML";
    layerText = "').innerText";
    visible = '.visibility = "visible"';
    hidden = '.visibility = "hidden"';
    zlevel = '.zindex';
    pxunits = 'px';
    okMouse = okMenu = true;
  }
  else { okMouse = okMenu = false; }
}
function reloadIt() { document.location = document.location; }
dhtml_check();

function myBrowser() {
  // added to allow script code that works for all browsers but safari (saf)
  // http://techpatterns.com/downloads/javascript_browser_detection.php#simple
  var d, dom, ie, ie4, ie5x, moz, mac, win, lin, old, ie5mac, ie5xwin, op;
  var n, na, nua, dom; // dj added
  d = document;
  n = navigator;
  na = n.appVersion;
  nua = n.userAgent;
  win = ( na.indexOf( 'Win' ) != -1 );
  mac = ( na.indexOf( 'Mac' ) != -1 );
  lin = ( nua.indexOf( 'Linux' ) != -1 );
  
  if ( !d.layers ){
    dom = ( d.getElementById );
    op = ( nua.indexOf( 'Opera' ) != -1 );
    konq = ( nua.indexOf( 'Konqueror' ) != -1 );
    saf = ( nua.indexOf( 'Safari' ) != -1 );
    moz = ( nua.indexOf( 'Gecko' ) != -1 && !saf && !konq);
    ie = ( d.all && !op );
    ie4 = ( ie && !dom );
  
    /*
    ie5x tests only for functionality. ( dom||ie5x ) would be default settings. 
    Opera will register true in this test if set to identify as IE 5
    */
  
    ie5x = ( d.all && dom );
    ie5mac = ( mac && ie5x );
    ie5xwin = ( win && ie5x );
  }
}
myBrowser();

function preload_img(image_array,flag) { // preload images
  // image file names stored in image_array (defined above)
  // called below (or can use with BODY onLoad
  if (okMenu || okMouse) {
    for (var loop in image_array) {
      var t = eval('preload_' + flag);
      t[loop] = new Image();
      t[loop].src = image_array[loop];
    }
  }
}

function msover(img,ref) { // mouse rollover function
  // img - name of the IMG statement
  // ref - new_imgs array name 
  if (!ref) { ref = img; } 
  if (okMenu || okMouse) {
    document.images[img].src = preload_on[ref].src;
    lastimg = img;  
    lastref = base_imgs[lastimg]; 
  }
}

function msout(img,ref) { // mouse rollout function
  // img - name of the IMG statement
  // ref - new_imgs array name 
  if (!ref) { ref = img; }
  if (okMenu || okMouse) { document.images[img].src = preload_off[ref].src;}
}

function on_msover(string,img,ref) {
  if (okMouse) {
    if (!ref) { ref = img; }
    if (img) { msover(img,ref); }
    if (leader) { window.status = leader + string; }
    else { window.status = string; }
  }
}

function on_msout(img,string) {
  if (okMouse) {
    if (img) { msout(img); }
    if (string) { window.status = string; }
    else { window.status = 'Maryland Sea Grant'; }
  }
}

function show_layer(layerid,num_layer) {
  if (num_layer) { n_layer = num_layer; }
  for (i=1; i<=n_layer; i++) {
    var this_layer = "m" + i;
    if (i==layerid) {
      eval(layerRef + this_layer + layerStyle + visible);
    }
    else {
      eval(layerRef + this_layer + layerStyle + hidden);
    }
  }
}

function hide_layer(layerid,num_layer) {
  if (num_layer) { n_layer = num_layer; }
  for (i=1; i<=n_layer; i++) {
    var this_layer = "m" + i;
    if (layerid == 'all') { 
      eval(layerRef + this_layer + layerStyle + hidden);
    }
    else if (i==layerid) { 
      eval(layerRef + this_layer + layerStyle + visible);
    }
    else { 
      eval(layerRef + this_layer + layerStyle + hidden);
    }
  }
}

function set_layer_location(n_layer,pxleft,pxtop) {  
  if (!pxleft) { pxleft = 25; }
  if (!pxtop) { pxtop = 105; }
  if (!n_layer) { n_layer = 1; }
  //if (document.all) { pxtop = 0; }
  var this_layer = "m" + n_layer; 
  var thisObj = layerRef + this_layer + layerStyle;  
  eval(thisObj).left = pxleft + pxunits; 
  eval(thisObj).top  = pxtop + pxunits; 
}

function ChangeText(txt_tag,this_txt,id) {
  // txt_tag - id of div and ilayer (layer name is txt_tag + _a) 
  // this_txt - what is to be displayed or array name
  // id - array id if this_txt is array name
  if (id) { this_txt =  eval(this_txt)[id]; }
  if (W3C) { eval(layerRef + txt_tag + "')").innerHTML  = this_txt; }
  else if (IE4) { eval(layerRef + txt_tag + "']").innerText  = this_txt; }
  else if (NS4) { 
    var txt_tag2 = txt_tag + '_a';  
    document.eval(txt_tag).document.eval(txt_tag2).document.open();
    document.eval(txt_tag).document.eval(txt_tag2).document.write(this_txt); 
    document.eval(txt_tag).document.eval(txt_tag2).document.close();
  }
  else { alert("Don't recognize this browser"); }
}

function check_required(which,req_fields,req_fields_txt) { 
  // which - values from form
  if (req_fields) { required = req_fields; required_text = req_fields_txt; }
  var ok;
  ok = required_fields(which);
  return ok;
}  

function check_it(which,req_fields,req_fields_txt,req_email,req_email_txt,pattern_v,pattern_t,pattern_n) { 
  // which - values from form
  var ok = true; // true/false flag if pass check(s)
  if (req_fields) { required = req_fields; required_text = req_fields_txt; }
  if (req_email) { email_var = req_email; email_label = req_email_txt}
  if (pattern_v) { 
    pattern_var = pattern_v; pattern_text = pattern_t; pattern_name = pattern_n; 
  }
 
  // check required fields
  if (required.length > 0) { ok = required_fields(which); }

  // have all required fields, now check email
  if (ok && email_var.length > 0) { ok = check_email(which,form_name); } 

  // have all required fields & email, now double check patterns 
  if (ok && pattern_v) { ok = check_patterns(which); }

  return ok;
}  

function required_fields(which) {
  // checks if all required fields are filled in
  // do not change the rest of this function
  // adapted from script by wsabstract.com posted at 
  // The JavaScript Source!! http://javascript.internet.com

  var pass = true;
  var msg = "Please make sure that entries for \n";
  var num = 0; 
 
  if (document.images) {
    for (i="0"; i<which.length; i++) {
      var tempobj=which.elements[i];
      for (j = 0; j < required.length; j++) {
        if (tempobj.name==required[j]) {
          if (((tempobj.type=="password" ||
            tempobj.type=="text" ||
            tempobj.type=="file" ||
            tempobj.type=="textarea") && 
            tempobj.value=='') ||
            (tempobj.type.toString().charAt(0)=="s" && 
             tempobj.selectedIndex=="0")) {
            pass=false;
            num += 1;
            msg += "  * " + required_text[j] + "\n";
          }
        } 
      }
    }
  }  
 
  if (!pass) {
    if (num > 1) { msg += "are entered correctly.\n"; }
    else { msg += "is entered correctly.\n"; }
    alert(msg);
    return false;
  }
  else { return true; }
}

function check_email(which) { //make sure emails are valid
  // written by Dan Jacobs
  var pass = true;
  var this_pass = true;
  var msg = "";
  var num = 0; 

  if (document.images) {
    for (i=0; i<which.length; i++) {
      var tempobj=which.elements[i];
      for (j = 0; j < email_var.length; j++) {
        if (tempobj.name == email_var[j]) { 
          this_email = tempobj.value;
          this_pass = emailCheck(this_email.toLowerCase());
          if (!this_pass) { 
            num += 1;
            //msg += "  * " + email_name + "'s email = " + this_email + "\n";
            msg += "  * " + email_label[j] + " = " + this_email + "\n";
            pass = false;
          }
        }
      } 
    } 
  }
 

  if (!pass) {
    if (num > 1) { 
      alert("The following do not appear to be valid:\n" + msg);
    }
    else { 
      alert("The following does not appear to be valid:\n" + msg);
    }
    return false;
  }
  else { return true; }
}

function emailCheck(emailStr) {
  // V1.1.3: Sandeep V. Tamhankar (stamhankar@hotmail.com) 
  // The JavaScript Source!! http://javascript.internet.com

  // Modified by Dan Jacobs 
  // comment out alerts - use return true/false only

  /* The following variable tells the rest of the function whether or not to
   verify that the address ends in a two-letter country   or well-known TLD. 
   1 means check it, 0 means don't. */

  var checkTLD=1;

  /* List of known TLDs that an e-mail address must end with. */

  var knownDomsPat = 
    /^(com|net|org|edu|int|mil|gov|arpa|biz|aero|name|coop|info|pro|museum)$/;

  /* The following pattern is used to check if the entered e-mail address fits the 
   user@domain format. Also used to separate the username from the domain. */

  var emailPat=/^(.+)@(.+)$/;

  /* This string represents the pattern for matching all special characters.  
   We don't want to allow special characters in the address, such as
   ( ) < > @ , ; : \ " . [ ] */

  var specialChars="\\(\\)><@,;:\\\\\\\"\\.\\[\\]";

  /* The following string represents the range of characters allowed in a
   user name or domain name. It really states which chars aren't allowed.*/

  var validChars="\[^\\s" + specialChars + "\]";

  /* The following pattern applies if the "user" is a quoted string (in which 
   case, there are no rules about which  characters are allowed and which aren't; 
   anything goes).  E.g. "jiminy cricket"@disney.com is a legal e-mail address. */

  var quotedUser="(\"[^\"]*\")";

  /* The following pattern applies for domains that are IP addresses, rather than 
   symbolic names - e.g. joe@[123.124.233.4] is a legal e-mail address. NOTE: The 
   square brackets are required. */

  var ipDomainPat=/^\[(\d{1,3})\.(\d{1,3})\.(\d{1,3})\.(\d{1,3})\]$/;

  /* The following string represents an atom
   (basically a series of non-special characters.) */

  var atom=validChars + '+';

  /* The following string represents one word in the typical username.
   For example, in john.doe@somewhere.com, john and doe are words.
   Basically, a word is either an atom or quoted string. */

  var word="(" + atom + "|" + quotedUser + ")";

  // The following pattern describes the structure of the user

  var userPat=new RegExp("^" + word + "(\\." + word + ")*$");

  /* The following pattern describes the structure of a normal symbolic domain, 
    as opposed to ipDomainPat, shown above. */

  var domainPat=new RegExp("^" + atom + "(\\." + atom +")*$");

  /* Finally, start to figure out if the supplied address is valid. */

  /* Begin with the coarse pattern to simply break up user@domain into
   different pieces that are easy to analyze. */

  var matchArray=emailStr.match(emailPat);

  if (matchArray==null) {
    /* Too many/few @'s or something; basically, this address doesn't even fit the
     general mold of a valid e-mail address. */
    //alert("Email address seems incorrect (check @ and .'s)");
    return false;
  }

  var user=matchArray[1];
  var domain=matchArray[2];

  // Start by checking if only basic ASCII characters are in the strings (0-127).

  for (i="0"; i<user.length; i++) {
    if (user.charCodeAt(i)>127) {
      //alert("The username contains invalid characters.");  
      return false;
    }
  }
  for (i="0"; i<domain.length; i++) {
    if (domain.charCodeAt(i)>127) {
      //alert("The domain name contains invalid characters.");
      return false;
    }
  }

  // See if "user" is valid 

  if (user.match(userPat)==null) {
    // user is not valid
    //alert("The username doesn't seem to be valid.");
    return false;
  }

  /* if the e-mail address is at an IP address (as opposed to a symbolic host
   name) make sure the IP address is valid. */

  var IPArray=domain.match(ipDomainPat);
  if (IPArray!=null) {
    // this is an IP address
    for (var i=1;i<=4;i++) {
      if (IPArray[i]>255) {
        //alert("Destination IP address is invalid!");
        return false;
      }
    }
    return true;
  }

  // Domain is symbolic name.  Check if it's valid.
 
  var atomPat=new RegExp("^" + atom + "$");
  var domArr=domain.split(".");
  var len=domArr.length;
  for (i="0";i<len;i++) {
    if (domArr[i].search(atomPat)==-1) {
      //alert("The domain name does not seem to be valid.");
      return false;
    }
  }

  /* domain name seems valid, but now make sure that it ends in a known
   top-level domain (like com, edu, gov) or a two-letter word, representing 
   country (uk, nl), and a hostname precedes the domain or country. */

  if (checkTLD && domArr[domArr.length-1].length!=2 && 
    domArr[domArr.length-1].search(knownDomsPat)==-1) {
    //alert("The address must end in a well-known domain or two letter country.");
    return false;
  }

  // Make sure there's a host name preceding the domain.

  if (len<2) { 
    //alert("This address is missing a hostname!");
    return false;
  }

  // If we've gotten this far, everything's valid!
  return true;
}

function noCR(thisEvent) {
  var key = window.event ? thisEvent.keyCode : thisEvent.which;
  var keychar = String.fromCharCode(key);
  var reg = /\r/; // key = 13 
  // reg.test is true if \r and false otherwise 
  // return the opposite of the reg.test value (true --> false, false --> true)
  return !reg.test(keychar);
}

function open_window(what,h,w) { // for html
  var winopt;
  if (!h) { h = 300; }
  if (!w) { w = 500; }
  winopt = "toolbar=no,location=no,directories=no,menubar=yes,resizable=no";
  winopt = "scrollbars=yes,width=" + w + ",height=" + h + "," + winopt;   
  newWin=window.open(what,"dummy",winopt); 
  newWin.document.close();
  return;
}

function create_window(what,alt,h,w,caption) { // for images
  var html, winopt;
 
  html = "<!DOCTYPE HTML PUBLIC \"-//W3C//DTD HTML 4.01 Transitional//EN\"\n";
  html += "\"http://www.w3.org/TR/1999/REC-html401-19991224/loose.dtd\">\n";
  html += "<HTML LANG=\"EN-US\">\n";
  html += "<HEAD>\n";
  html += "<TITLE>Maryland Sea Grant Book & Video Store<\/TITLE>\n";
  html += "<LINK REL=\"STYLESHEET\" TYPE=\"text/css\" ";
  html += "HREF=\"http://www.mdsg.umd.edu/includes/dj/store/store.css\">\n";
  html += "<\/HEAD>\n";
  html += "<BODY BGCOLOR=\"#FFFFFF\" onblur=window.close()>\n";
  html += "<DIV ALIGN=\"CENTER\">\n";
  html += "<IMG SRC=\"" + what + "\" ALT=\"" + alt + "\" ";
  html += "height=" + h + " width=" + w + ">\n";
  html += "<\/DIV>\n";
  if (caption) { html += "<P CLASS=\"STD\">\n" + caption + "\n<P>\n"; }
  html += "<P CLASS=\"FOOTER\" ALIGN=RIGHT>\n";
  html += "<A HREF=\"javascript:window.close()\">close window<\/A>\n";
  html += "<\/P>\n";
  html += "<\/BODY>\n";
  html += "<\/HTML>\n";
 
   h = h*1 + 50; 
   //if (h > 500) { h = 500; }
   w = w*1 + 30;
   //if (w > 500) { w = 500; }

  winopt = "toolbar=no,location=no,directories=no,menubar=yes,resizable=no";
  winopt = "scrollbars=yes,width=" + w + ",height=" + h + "," + winopt;   
  newWin=window.open("","dummy",winopt);
  newWin.document.write(html);
  newWin.document.close();
  return;
} 

function change_field(form,item,val) {
  if (item && val) { eval('document.' + form + '.' + item).value = val; }
}

function checkBilling(form,item,val) {
  // check value of resident (make sure it isn't ?)
  // if ok, submit form request from button (update, go to checkout)
  // item - form field name
  // val - value for item
  var aa = eval('document.' + form + '.resident').value; 
  if (aa == "?") { // no billing location set
    var msg = "You must select your billing location before you can continue with this order.\n";
    msg += "\nMaryland residents who are tax exempt should choose Maryland (MD) Tax Exempt. ";
    msg += "You will need a valid tax-exempt number at checkout.\n";
    msg += "\nPlease select your shipping location if it is different from your billing location.";
    alert(msg);
    return false;
  }
  submit_form(form,item,val);
}

function submit_form(form,item,val,flag) {
  // item - form field name
  // val - value for item
  // flag - set if target is _blank (not _self)
  if (item && val) { change_field(form,item,val); }
  if (flag) { eval('document.' + form).target = '_blank'; }
  else { eval('document.' + form).target = '_self'; }
  eval('document.' + form).submit();
}

function checkValue(form,name,numtype,value,max)  {  
  // check if positive number or integer
  // name - name of the field
  // input - value to check
  // numtype - no or int (default no - positive number, int - integer)
  // value - original (default) value of the field (optional) 
  // max - maximum value for the field (optional)
  if (!numtype) { numtype = "no"; }
  if (!value) { value = ""; }
  var oneDecimal = false;
  var commaFlag = false;
  var spaceFlag = false;
  var msg = "This must be a positive number.";
  var goodNumber = true;
  if (numtype != "no") { 
    oneDecimal = true; 
    msg = "This must be a positive whole number.";
  }
  var thisObj = eval('document.' + form + '.' + name);
  var str = thisObj.value; // input value
  if (!str || !goodNumber) { 
    return false; 
  } 
  for (var i = 0; i < str.length; i++) {
    var ch = str.substring(i, i + 1)
    if (ch < "0" || "9" < ch) { 
      if (ch == "." && !oneDecimal) {
        oneDecimal = true;
      }
      else { 
        goodNumber = false; 
        if (ch == ",") { commaFlag = true; }
        if (ch == " ") { spaceFlag = true; }
      }
    }
  }
  if (!goodNumber) { 
    msg += "\nDo not include non-numeric characters";
    
    if (commaFlag || spaceFlag) { msg += " such as"; }
    if (commaFlag) { 
      msg += " commas(,)"; 
      if (spaceFlag) { msg += " or"; }
    }
    if (spaceFlag) { msg += " spaces ( )"; }
    msg += ".";
    alert(msg + "\n\nPlease correct the entry.");
    thisObj.focus();
    thisObj.select();
    //thisObj.value = "";
    thisObj.value = value;
    return false;
  }
  if (max) { // check if more than maximum amount
    var vv = str * 1; // convert to numeric
    if (vv > max) {
      msg = "This number must be no more than " + max + ".";
      alert(msg);
      thisObj.focus();
      thisObj.select();
      //thisObj.value = "";
      thisObj.value = value; 
      return false;
    }
  }
  if (numtype == "no") { // decimal to 2 places
    thisObj.value = parseFloat(thisObj.value).toFixed(2);
  }
}

function addCommas(nStr) {
  nStr += '';
  x = nStr.split('.'); // x[0] whole number(s), x[1] decimal part
  x1 = x[0];
  x2 = x.length > 1 ? '.' + x[1] : '';
  var rgx = /(\d+)(\d{3})/;
  while (rgx.test(x1)) {
    x1 = x1.replace(rgx, '$1' + ',' + '$2');
  }
  return x1 + x2;
}

function CurrencyFormatted(amount) {
  var i = parseFloat(amount);
  if(isNaN(i)) { i = 0.00; }
  var minus = '';
  if(i < 0) { minus = '-'; }
  i = Math.abs(i);
  i = parseInt((i + .005) * 100);
  i = i / 100;
  s = new String(i);
  if(s.indexOf('.') < 0) { s += '.00'; }
  if(s.indexOf('.') == (s.length - 2)) { s += '0'; }
  s = minus + s;
  s = addCommas(s);
  return s;
}

special_n = 0;
special_cost = 0;
special_shipping = 0;
special_message = '';

function changeOrder(form,item) { 
  // form originally read in using this.form with obj = form.eval(item)
  // worked for Firefox & Netscape but not Safari
  // changed to form read in using form name (e.g., 'bookstore') and
  // obj =  eval('document.' + form + '.' + item)
  var obj = eval('document.' + form + '.' + item); 
  var q = obj.value * price[item]; // quantity * price/unit
  var c = CurrencyFormatted(q);  
  n = 0;  // total quantity ordered
  ChangeText('l_'  + item,'$' +  s);  
  var subtotal = new Array(); // array of costs before tax and s&h
  subtotal['all'] = 0;  // total cost before tax and s&h
  for (var jj in section) {  
    subtotal[section[jj]] = 0; // cost before tax and s&h for each section
  }
  var x = new Array(); // stores item id split into parts (type_orde, type, . . .)
  
  for (var ff in price) {  
    obj = eval('document.' + form + '.' + ff); // this item in the order form
    n += obj.value*1; // add number ordered for this item to running total (n)
    var v = obj.value * price[ff] * 1; // cost for number ordered for this item  
    x = ff.split("QQ");
    for (var jj in section) {  
      if (x[1] == section[jj]) { 
        subtotal[section[jj]] += v;
      } 
    }
  } 
  update['subtotal all'] = 0; // updated total cost before tax and s&h
  for (var jj in section) {  
    aa = 'subtotal ' + section[jj]; 
    update[aa] = subtotal[section[jj]];
    update['subtotal all'] += subtotal[section[jj]];
  }
  //update['subtotal'] = subtotal; 
  if (offer['discount']) { // have discount available
    // update special offer discount amount
    getSpecialOffer(form);
  }
  aa = eval('document.' + form + '.resident').value; 
  setResident(form,aa); 
  if (special_shipping) {
    aa = special_shipping;
  }
  else { 
    aa = eval('document.' + form + '.ship_to').value; 
  }
  setShipping(form,aa);
  ChangeText('l_total_n', n);
}
  
function getSpecialOffer(form) {
  special_n = 0;
  special_cost = 0;
  special_shipping = 0;
  special_message = '';

  var t = offer['discount']; 
  var ss = new Array(); // stores special offer in parts 
   
  if (offer['discount'].match('/')) {
    // 1/1 buy one get one free
    // 1/code  buy one and get another item for free (ss[1] = id of 2nd item)
    // $/$ discount price for 1st and 2nd item  
    ss = offer['discount'].split("\/"); // ss[0] = cost 1st item, ss[1] = cost of 2nd item
  }
  
  // make sure the controlling item in the offer is ordered 
  var offer_n = 0; // number of this item ordered
  var offer_code; // complete code for this item
  for (var ff in price) {
    if (ff.match(offer['id']) ){ // have item in orig order
      if (offer['discount_quantity'] == 'all') {
        offer_n += eval('document.' + form + '.' + ff).value * 1; // get updated number ordered
      }
      else {
        offer_n += offer['discount_quantity'] * 1; // get updated number ordered
      }
      offer_code = ff;
    }
  }
  
  if (!offer_n) { // did not order the controlling item
    eval('document.' + form + '.offer_no').value = "";
    special_order = 0;   
    special_shipping = 0;
    s = CurrencyFormatted(special_cost);
    ChangeText('l_special_offer', '($' + s + ')');
    t = "<SPAN STYLE=\"font-weight:bold\">Special Offer Discount:</SPAN> ";
    t += offer['discount_txt'] + special_message;
    alert('Speical offer discount contitions are no longer met.');
    //t += ' -- Conditions not met';
    ChangeText('l_discount_txt', t);
    update['special_offer'] = special_cost;  
    return true;
  }
  var total_n = 0;
  for (var ff in price) {  
    obj = eval('document.' + form + '.' + ff); // this item in the order form
    var v = obj.value * price[ff] * 1; // cost for number ordered for this item 
    if (offer['discount'].match('1/1')) { // buy one get one free 
      if (ff.match(offer['id'])) { // matches special offer item(s)
        special_n += obj.value*1;  
        special_cost += v;
      }
    }
    else if (offer['discount'].match('1/')) { // buy one and get another item for free 
      if (ff.match(ss[1])) { // have 2nd item in the offer          
        var n = obj.value; // number ordered for 2nd item 
        if (offer_n >=  n) { // more 1st ordered than 2nd 
          // comment out to allow different number of 2nd item (9/22/2008)
          //obj.value = offer_n;
        } 
        var q = obj.value * price[ff]; // quantity * price/unit
        var s = CurrencyFormatted(q);  
        ChangeText('l_'  + ff,'$' +  s);  
        special_n += offer_n*1; // number ordered for 1st item
        special_cost += price[ff] * offer_n*1;  // discount - n of 1st * cost of 2nd 
      }
      else if (ff.match(offer['id'])) { 
        special_n += offer_n*1; // add number ordered for 1st item
      }
    }
    else if (offer['discount'].match('all items')) { // special offer for all items
      special_n += obj.value*1;  
      special_cost += v; 
    } 
    else { // % off, $ off or special price for one or more items such as DVDs (not all items)  
      if (ff.match(offer['id'])) { // matches special offer item(s)
        special_n += obj.value*1;  
        special_cost += v; 
      }
    }
    total_n += obj.value*1; // add number ordered for this item to running total 
  }
  
  // figure out the discount and special shipping (if available) 
  if (offer['discount'].match('%')) { // percent discount
    var t = offer['discount'].replace('%','');
    special_offer = t/100 * special_cost;
    if (offer['shipping']) { // have special shipping offer
      if (special_n >= total_n) { // set shipping to special rate 
        special_shipping = CurrencyFormatted(offer['shipping']);
        special_message = " (S&amp;H \$" + special_shipping + ")";
      }
    }
  }
  if (offer['discount'].match('$')) { // dollar discount 
    t.replace('$',''); 
    special_offer = t*1; 
    if (offer['shipping']) { // have special shipping offer
      if (special_n >= total_n) { // set shipping to special rate 
        special_shipping = CurrencyFormatted(offer['shipping']);
        special_message = " (S&amp;H \$" + special_shipping + ")";
      }
    }
  }
  //if (offer['discount'].match('1/1')) { 
  if (ss[0] == "1" && ss[1] == "1") { // buy one get on free
    // compute 1/2 of quantity ordered to ceil integer -- the number to be paid for
    special_offer = special_n - Math.ceil(special_n/2); // no. free (no charge)
    for (var ff in price) {  
      if (ff.match(offer['id'])) {
        special_cost = special_offer * price[ff];
      }
    }
    if (offer['shipping']) { // have special shipping offer
      if (special_n >= total_n) { // set shipping to special rate 
        special_shipping = CurrencyFormatted(offer['shipping']);
        special_message = " (S&amp;H \$" + special_shipping + ")";
      }
    }
  }
  //if (offer['discount'].match('1/')) { 
  if (ss[0] == "1" && ss[1] != "1") { // buy 1 get another free  
    special_offer = special_cost;
    if (offer['shipping']) { // have special shipping offer
      if (special_n >= total_n) { // set shipping to special rate 
        special_shipping = CurrencyFormatted(offer['shipping']);
        special_message = " (S&amp;H \$" + special_shipping + ")";
      }
    }
  }
  //if (offer['discount'].match('/')) { 
  if (ss[0] != "1") { // discount price for 1st and 2nd item  
    ss[0] = ss[0] * Math.ceil(special_n/2); // cost for 1st item in pair
    ss[1] = ss[1] * (special_n - Math.ceil(special_n/2)); // cost of 2nd item in pair 
    special_offer = special_cost - ss[0] - ss[1]; 
    if (offer['shipping']) { // have special shipping offer
      if (special_n >= total_n) { // set shipping to special rate 
        special_shipping = CurrencyFormatted(offer['shipping']);
        special_message = " (S&amp;H \$" + special_shipping + ")";
      }
    } 
    special_cost = special_offer;
  } 
  s = CurrencyFormatted(special_cost);
  ChangeText('l_special_offer', '($' + s + ')');
  t = "<SPAN STYLE=\"font-weight:bold\">Special Offer Discount:</SPAN> ";
  t += offer['discount_txt'] + "" + special_message;
  ChangeText('l_discount_txt', t);
  update['special_offer'] = special_cost; 
  //alert(special_cost);
}

function setResident(form,str) {
  // string - state|fedex overnight|fedex 2-day
  var aa = new Array();
  aa = str.split("|"); // state, overnight, 2-day 
  if (aa[0] == "") { aa[1] = aa[2] = ""; }
  else {
    aa[1] = '$' +  aa[1];
    aa[2] = '$' +  aa[2];
  }  
  changeTax(aa[0]); 
  if (aa[0] == "XW" || aa[0] == "YW") {
    eval('document.' + form + '.ship_to').value = "BB"; 
  }
  // check if ship_to same as resident
  var v = eval('document.' + form + '.ship_to').value;
  if (v.substring(0,2) == "BB") {
    setShipping(form,str);
  }
}

function changeTax(state) {
  // flag - if show alert for tax exempt
  var v = 0.00;  
  if (state == "Y" || state == "YW") { 
    v = (update['subtotal all'] - update['special_offer']*1) * mdtax;
    //v = update['subtotal'] * mdtax; 
    v = Math.round(v*100)/100;
  } 
  else if (state == "X" || state == "XW") { 
    alert("You will need your tax exempt number when you place your order.");
  }
  update['statetax'] = v;
  s = CurrencyFormatted(v); 
  ChangeText('l_statetax','$' +  s);
  // add orig cost + shippping - special offer discount
  v += update['subtotal all']*1 + update['shipping']*1 - update['special_offer']*1;
  v = CurrencyFormatted(v); 
  ChangeText('l_total_cost','$' +  v);
}

function setShipping(form,str) {
  var obj = eval('document.' + form + '.how_shipped');
  var v = update['subtotal all']*1;
  var sh = vf = 0;
  var ss, ff; 
  if (update['special_offer'] && offer['shipping']) {
    update['shipping'] = offer['shipping']; 
    sh = offer['shipping']*1;
    s = CurrencyFormatted(sh);  
    ChangeText('l_shipping','$' +  s);
    // add orig cost + sales tax - special offer discount
    sh += update['subtotal all']*1 + update['statetax']*1 - update['special_offer']*1;
    sh = CurrencyFormatted(sh); 
    ChangeText('l_total_cost','$' + sh);
    //if (!saf) { // the for (var j in obj) not work in safari
    //  for (var j in obj) { obj[j].checked = false; }
    //}
    return true;
  }
  
  // walk-in/pick-up (9/19/2008) 
  var pv = eval('document.' + form + '.resident').value;
  var pp = new Array(); 
  pp = pv.split("|"); // state, overnight, 2-day 
  if (pp[0] == "XW" || pp[0] == "YW") {
    if (eval('document.' + form + '.ship_to').value != "BB") {
      eval('document.' + form + '.ship_to').value = "BB";
      str = "BB";
      alert("The shipping location must be the same as the billing location since the item(s) will be picked up at our office.");
    }
  } 

  // moved to perl output js - based on shipping data file
  //var section = new Array ('store', 'stuff');
  if (str == 'how_shipped') { // from shipping radio buttons 
    str = eval('document.' + form + '.ship_to').value;
  } 
  if (str.substring(0,2) == "BB") { // same as resident
    str = eval('document.' + form + '.resident').value;
  } 
  if (eval('document.' + form + '.resident').value == "?" && eval('document.' + form + '.ship_to').value != "BB") {
    eval('document.' + form + '.resident').value = eval('document.' + form + '.ship_to').value;
  }
  if (str == "?") { // no shipping location set
    var msg = "You must select your billing location before you can continue with this order.\n";
    msg += "\nMaryland residents who are tax exempt should choose Maryland (MD) Tax Exempt. ";
    msg += "You will need a valid tax-exempt number at checkout.\n";
    msg += "\nPlease select your shipping location if it is different from your billing location.";
    // set to nothing for shipping since no billing location selected 
    //sh = Math.round(sh*100)/100; 
    sh = 0;
    update['shipping'] = sh; 
    s = CurrencyFormatted(sh);  
    ChangeText('l_shipping','$' +  s);
    // add orig cost + sales tax - special offer discount
    sh += update['subtotal all']*1 + update['statetax']*1 - update['special_offer']*1;
    sh = CurrencyFormatted(sh); 
    ChangeText('l_total_cost','$' + sh);
    alert(msg);
    return false;
  }
   
  var aa = new Array(); 
  aa = str.split("|"); // state, overnight, 2-day 
 
  
  // set default shipping to be the first radio button (least expensive)
  //if (!saf) { // the for (var j in obj) not work in safari
  //  var k = 0;
  //  for (var j in obj) {
  //    if (obj[j].checked == true) { k += 1; }
  //  }
  //  if (!k) { obj[0].checked = true; }
  //}
  
  if (aa[0] == "F") {  
    alert('Please contact us about shipping and handling.');
    obj[0].checked = true;
    sh = 0;
  }    
  else if (pp[0] == "XW" || pp[0] == "YW") { // walk-in/pick-up (9/19/2008)
    sh = 0;
  }
  else {
    if (obj[0].checked) { 
      for (var kk in section) { // calculate shipping for stuff and store 
        var subv = update['subtotal ' + section[kk]]*1;
        if (!subv) { continue; }
        var subsh = 0;
        if (aa[0] == "AK" || aa[0] == "HI") {
          ss = section[kk] + " hi_ak";
        }
        else {
          ss = section[kk] + " us";
        }
        for (var jj in shipping) {  
          if (!jj.match(ss)) { continue; }
          ff = jj.replace(ss+" ",""); // max dollar for this shipping rate 
          vf = ff*1; // max dollar for this shipping rate as floating point number
          if (subv >= vf) {   
            subsh = shipping[jj]*1; // shipping as floating point number
          }
        }
        // check if over max and add surcharge  
        if (subv >= max_shipping[ss + ' max']) { 
          vf = Math.round((v - max_shipping[ss + ' max'])/max_shipping[ss + ' inc']) + 1;
          subsh += vf * max_shipping[ss + ' rate'];  
        }
      sh += subsh;
      }
    }
    else { // fedex 
      if (v > 150) { 
        //vf  =  'Your order before taxes and shipping is $' + CurrencyFormatted(update['subtotal']);
        vf = 'Your order before adding in ';
        if (update['special_offer']) {
          vf += 'the special offer, ';
        }
        vf += 'taxes and shipping is $';
        vf += CurrencyFormatted(update['subtotal all']);    
        vf += '.\n\nWe cannot send it by Fedex since it is over $150.00.';
        alert(vf);
        obj[0].checked = true;
        setShipping(form,str);
      }
      else if (obj[1].checked) { 
        sh = aa[1]*1;
      }
      else if (obj[2].checked) { 
        sh = aa[2]*1;
      } 
    }
  }
  sh = Math.round(sh*100)/100; 
  update['shipping'] = sh; 
  s = CurrencyFormatted(sh);  
  ChangeText('l_shipping','$' +  s);
  // add orig cost + sales tax - special offer discount
  sh += update['subtotal all']*1 + update['statetax']*1 - update['special_offer']*1;
  sh = CurrencyFormatted(sh); 
  ChangeText('l_total_cost','$' + sh);
}

function formReset(form) { 
  var n = 0; // quantity of items ordered
  // reset layer elements
  var subtotal = new Array(); // array of costs before tax and s&h
  subtotal['all'] = 0;  // total cost before tax and s&h
  for (var jj in section) {  
    subtotal[section[jj]] = 0; // cost before tax and s&h for each section
  }
  //var subtotal = 0; // cost before tax and s&h
  var x = new Array(); // stores item id split into parts (type_orde, type, . . .)
  for (var ff in price) { 
    n += quant[ff]*1; 
    eval('document.' + form + '.' + ff).value = quant[ff];
    var v = quant[ff] * price[ff] * 1;  
    var s = CurrencyFormatted(v); 
    ChangeText('l_' + ff,'$' +  s);
    x = ff.split("QQ");
    for (var jj in section) {  
      if (x[1] == section[jj]) { 
        subtotal[section[jj]] += v;
      } 
    } 
  } 
  
  update['subtotal all'] = 0; // updated total cost before tax and s&h
  for (var jj in section) {  
    aa = 'subtotal ' + section[jj]; 
    update[aa] = subtotal[section[jj]];
    update['subtotal all'] += subtotal[section[jj]];
  }
  var total_cost = 0;
  for (var ff in orig) {  
    if (ff.match('special_offer')) {
      total_cost -= orig[ff]*1;
    }
    else {
      total_cost += orig[ff]*1;
    }
    if (ff.match('subtotal')) {
      if (ff.match(' all')) { // remove double added subtotal for all items
        total_cost -= orig[ff]*1;
      }
      continue;
    }
    update[ff] = orig[ff];
    var v = CurrencyFormatted(eval(orig[ff]));  
    if (ff.match('special_offer')) {
      if (offer['discount'] > 0) {
        ChangeText('l_' + ff,'($' +  v + ')'); 
        if (offer['shipping']) {
          sh = offer['shipping']*1;
          aa = CurrencyFormatted(sh);  
          ChangeText('l_shipping','$' +  aa);
          aa = offer['discount_txt'] +' (S&amp;H \$' + aa + ')'; 
        }
        else {
          aa = offer['discount_txt'];
        } 
        aa = "<SPAN STYLE=\"font-weight:bold\">Special Offer Discount:</SPAN> " + aa;
        ChangeText('l_discount_txt', aa); 
      }
    }
    else {
      ChangeText('l_' + ff,'$' +  v);
    }
  }
  var s = CurrencyFormatted(total_cost); 
  ChangeText('l_total_cost', '$' + s);
  ChangeText('l_total_n', n);
}

function showFedex(str) {
  var aa = new Array();
  aa = str.split("|"); // state, overnight, 2-day 
  if (aa[0] == "") { aa[1] = aa[2] = ""; }
  else {
    aa[1] = '$' +  aa[1];
    aa[2] = '$' +  aa[2];
  }
  ChangeText('l_overnight',aa[1]);
  ChangeText('l_2-day',aa[2]);
}

function checkZip(form,name) {
  var valid = "0123456789-";
  var hyphencount = 0;
  var c = "";
  var ok = true; 
  var thisObj = eval('document.' + form + '.' + name);
  var str = thisObj.value; // input value
  if (!str) { return ok; } 
  if (str.length != 5 && str.length != 10) {
    ok = false;
  }
  for (var i=0; i < str.length; i++) {
    c = "" + str.substring(i, i+1);
    if (c == "-") {
      hyphencount++;
    }
    if (valid.indexOf(c) == "-1") {
      ok = false;
    }
    else if ((hyphencount > 1) || ((str.length==10) && ("" + str.charAt(5) != "-"))) {
      ok = false;
    }
  }
  if (!ok) {
    alert('The zip code ' + str + ' is not valid.');
    thisObj.focus();
    thisObj.select();
    thisObj.value = "";
  }
  return ok;
}

//close off comment to hide this script from old browsers----------->
