function buildTable(n)
{
  //get all codes in basket
  var booklist = getAllCode()
  var bookqty = getAllqty()

  //given n=number of Row
  for (var i=1; i<=n; i++)
  {
    document.write("<tr>\n")

    //display item picture
    var str = "  <td align=center>"+i+"</td>\n"
//    <img src='"+subdir
//    if (booklist.length==0) str += "book1.gif"
//    else str += picture[booklist[i-1]]
//    str +=  "' Height="+picHeight+" Width="+picWidth+" name=pic"+i+" border=0></td>\n"
    document.write(str)

    //Book Code
    document.write("  <td>"+fillCode(i,booklist[i-1])+"  </td>\n")

    //Book Title
    document.write("  <td>"+fillTitle(i,booklist[i-1])+"</td>\n")

    //Qty
    var str = "  <td><input type=text size=2 name=qty"+i+" value=\""
    if (NoCode()>0) str += bookqty[i-1]
    str += "\" onKeyUp=\"if (!isNaN(this.value)) getGrandTotal(); else "+
           "{document.form1.qty"+i+".value='';}\"></td>\n"
    document.write(str)

    //Book Unit Price
    document.write("  <td><input type=text size=7 name=price"+i+" value=\"\"></td>\n")

    //Sub-Total
    document.write("  <td><input type=text size=7 name=subtotal"+i+" value=\"\"></td>\n")

    //delete button
    document.write("  <td align=left><input type=button name=del"+i+" value=Clr "+
                   "onClick=\"delCode("+i+");\"></td>\n")
    document.write("</tr>\n")
  }
}

function fillCode(i,c)
{
  var str = "    <select name=code"+i+" onChange=\"if (this.options[this.selectedIndex]."+
            "value!='a') {document.form1.price"+i+".value=getPrice(document.form1.code"+i+
            ".options[document.form1.code"+i+".selectedIndex].value);"+
            "document.form1.title"+i+".selectedIndex=document.form1.code"+i+
            ".selectedIndex;getGrandTotal();} else {clearRow("+i+");getGrandTotal();}\">\n"+
            "    <option value=\"a\">Select one\n"
  for (var j=0;j<code.length;j++)
  {
    str +=  "    <option "
    if (c==code[j]) str += "selected "
    str +=  "value=\""+code[j]+"\">"+code[j]+"\n"
  }
  str +=    "    </select>\n"
  return str
}

function fillTitle(i,c)
{
  var str = "    <select name=title"+i+" onChange=\"if (this.options[this.selectedIndex]."+
            "value!='a') {document.form1.price"+i+".value=getPrice(this.options"+
            "[this.selectedIndex].value);document.form1.code"+i+
            ".selectedIndex=this.selectedIndex;} else {clearRow("+i+");}\">\n"+
            "    <option value=\"a\">Select one\n"
  for (var j=0;j<title.length;j++)
  {
    str +=  "    <option "
    if (c==code[j]) str += "selected "
    str += "value=\""+code[j]+"\">"+title[j]+"\n"
  }
  str +=    "    </select>\n"
  return str
}

function buildCourier()
{
  var str = "  <select name=delivery onChange=\""+
            "getGrandTotal();\">\n"+
            "    <option value=\"a\">Select one\n"
  for (var j=0;j<CZone.length;j++)
  {
    str +=  "    <option value=\""+CCharges[j]+"\">"+CZone[j]+"\n"
  }
  str +=    "  </select>"
  return str;
}

function clearRow(i)
{
  //reset the i-th row items
  eval("document.form1.code"+i+".selectedIndex=0")
  eval("document.form1.title"+i+".selectedIndex=0")
  eval("document.form1.price"+i+".value=''")
  eval("document.form1.subtotal"+i+".value=''")
}

function clearDelivery()
{
  //Clear Delivery charges fields
  document.form1.delivery.selectedIndex=0;
  document.form1.totalqty.value="";
  document.form1.delivery_charges.value="";
}

function getpic(i)
{
  var c = eval("document.form1.code"+i+".options[document.form1.code"+i+".selectedIndex].value")
  var str="document.form1.pic"+i+".src='"+picture[c]+"'"
  eval(str)
  alert(str)
}

function clearpic(i)
{
  eval("document.form1.pic"+i+".src='"+clrpicture+"'")
}

///if i="999", clear all cookie or fields
function delCode(i)
{
  //either order form is via cookie or plain selection order page
  if (NoCode()>0)
  {
    //order form is via cookie
    //get code
    if (i=="999")
    {
       delAllCode();
    }
    else
    {
      var c = eval("document.form1.code"+i+".options[document.form1.code"+i+".selectedIndex].value")
//      alert(c)
      delfromBasket(c)
      self.location.reload();
    }
  }
  else
  {
    //order form is normal form
    //simply reset the selected row
    var row = document.form1.row.value
    if (i=="999")
    {
      for (var j=1; j<=row; j++)
      {
        clearRow(j)
      }
    }
    else clearRow(i);
    getGrandTotal();
  }
}

function getPrice(i)
{
  if (i!="a") return formatDigit(Price[i],2);
  return true;
}

function fillPrice()
{
  //loop through all code and title
  //and ensure selected code/title has unit price listed
  var row = document.form1.row.value;
  for (var i=1; i<=row; i++)
  {
    var c = eval("document.form1.code"+i+".options[document.form1.code"+i+
                 ".selectedIndex].value")
    if (c!="a") eval("document.form1.price"+i+".value=getPrice(c)")
  }
}

//loop through all rows and fill in subtotals
function getSubTotal(i)
{
  var row = parseInt(document.form1.row.value)
  for (var i=1; i<=row; i++)
  {
    var code = eval("document.form1.code"+i+".options[document.form1.code"+i+
                    ".selectedIndex].value")
    var title = eval("document.form1.title"+i+".options[document.form1.title"+i+
                     ".selectedIndex].value")
    var qty = eval("document.form1.qty"+i+".value")
    if ((code!="a") && (title!="a") && (qty!=""))
    {
      //item selected & quantity filled
      //recalculate subtotal
      var unitPrice = deformatDigit(getPrice(code))
      var subtotal = formatDigit(parseFloat(unitPrice) * parseFloat(qty),2)
      eval("document.form1.subtotal"+i+".value=subtotal")
    }
    else
    {
      eval("document.form1.qty"+i+".value=\"\"")
//      eval("document.form1.code"+i+".selectedIndex=0")
//      eval("document.form1.title"+i+".selectedIndex=0")
//      eval("document.form1.price"+i+".value=\"\"")
      eval("document.form1.subtotal"+i+".value=\"\"")
    }
  }
}

function getTotalQty()
{
  var total = 0;
  var row = document.form1.row.value;
  for (var j=1; j<=row; j++)
  {
    var qty = eval("document.form1.qty"+j+".value")
    if (qty!="") total += parseInt(qty);
  }
  if (total>0) document.form1.totalqty.value=total;
}

function getDelivery()
{
  var delivery = document.form1.delivery.options[document.form1.delivery.selectedIndex].value;
  if (delivery!="a")
  {
    getTotalQty()
    var totalQty = document.form1.totalqty.value;
    if (totalQty!="")
    {
      var d_charges = parseFloat(totalQty)*parseFloat(delivery);
      document.form1.delivery_charges.value= formatDigit(d_charges,2);
    } 
    else 
    {
      document.form1.totalqty.value="";
      document.form1.delivery_charges.value="";
    }
  }
  else
  {
    document.form1.totalqty.value="";
    document.form1.delivery_charges.value="";
  }
}

function getGrandTotal()
{
  getSubTotal();
  getDelivery();

  var sum = 0.0;
  var book = 0;
  var row = document.form1.row.value;
  for (var i=1;i<=row;i++)
  {
    //go through item subtotal & sum them up
    var subtotal = eval("document.form1.subtotal"+i+".value")
    if (subtotal!="")
    {
      sum = sum + parseFloat(deformatDigit(subtotal))
      book=1;
    }
  }

  if ((sum>0.0) && (book==1))
  {
    var d_charges = document.form1.delivery_charges.value;
    if (d_charges!="")
    {
      sum = sum + parseFloat(deformatDigit(d_charges));
      document.form1.grandtotal.value = formatDigit(sum,2);
    }
    else
    {
      document.form1.grandtotal.value="";
    }
  }
  else
  {
    //no items selected
    clearDelivery();
    document.form1.grandtotal.value = "";
  }
}

//given a number formatted by using function formatDigit(n,d)
//return the number in original format
function deformatDigit(n)
{
  var str = ""
  for (var i=0;i<n.length;i++)
  {
    var c = n.charAt(i)
    if (c!=",") str += n.substr(i,1)
  }
  return str;
}

//given a number (float or integet), n
//return a formatted string with truncated decimal of digits d
//e.g. given .333333, return 0.33
//e.g. given 123.45555, return 123.45
//e.g. given 1000.55, return 1,000.55
function formatDigit(n,d)
{
    var a = n + ""
    var DotIndex = a.lastIndexOf(".")

    var beforeDot = a.substring(0,DotIndex)
    if (DotIndex==-1) beforeDot=a
    if (beforeDot=="") beforeDot="0"
    if (beforeDot.length>3)
    {
        //insert comma into thousands
        var temp = ""
        var count=beforeDot.length
        while (count>3)
        {
          temp = ","+beforeDot.substr(count-3,3)+temp
          count -= 3
        }
        if (temp!="")
        {
          var n1 = (beforeDot.length/3)+""
          var n2 = n1.substr(n1.lastIndexOf(".")+1,1)
          if (n2=="3")
            beforeDot=beforeDot.substr(0,1)+temp
          else if (n2=="6")
            beforeDot=beforeDot.substr(0,2)+temp
          else
            beforeDot=beforeDot.substr(0,3)+temp
        }
    }

    if (DotIndex==-1)
    {
      //inserting zeros after decimal point
      //after decimal point, no digits, then add two zeros
      var afterDot="00"
    }
    else if ((a.length-DotIndex-1)==1)
    {
      //after decimal point, one digit, then add one zero after the digit
      var afterDot=a.charAt(a.length-1)+"0"
    }
    else
    {
      //after decimal point, has min two digits, take only first two digits
      var afterDot=a.substr(DotIndex+1,d)
    }
    return (beforeDot+"."+afterDot)
}

//
//  Cookie Functions -- "Night of the Living Cookie" Version (25-Jul-96)
//
//  Written by:  Bill Dortch, hIdaho Design <bdortch@hidaho.com>
//  The following functions are released to the public domain.
//
//  This version takes a more aggressive approach to deleting
//  cookies.  Previous versions set the expiration date to one
//  millisecond prior to the current time; however, this method
//  did not work in Netscape 2.02 (though it does in earlier and
//  later versions), resulting in "zombie" cookies that would not
//  die.  DeleteCookie now sets the expiration date to the earliest
//  usable date (one second into 1970), and sets the cookie's value
//  to null for good measure.
//
//  Also, this version adds optional path and domain parameters to
//  the DeleteCookie function.  If you specify a path and/or domain
//  when creating (setting) a cookie**, you must specify the same
//  path/domain when deleting it, or deletion will not occur.
//
//  The FixCookieDate function must now be called explicitly to
//  correct for the 2.x Mac date bug.  This function should be
//  called *once* after a Date object is created and before it
//  is passed (as an expiration date) to SetCookie.  Because the
//  Mac date bug affects all dates, not just those passed to
//  SetCookie, you might want to make it a habit to call
//  FixCookieDate any time you create a new Date object:
//
//    var theDate = new Date();
//    FixCookieDate (theDate);
//
//  Calling FixCookieDate has no effect on platforms other than
//  the Mac, so there is no need to determine the user's platform
//  prior to calling it.
//
//  This version also incorporates several minor coding improvements.
//
//  **Note that it is possible to set multiple cookies with the same
//  name but different (nested) paths.  For example:
//
//    SetCookie ("color","red",null,"/outer");
//    SetCookie ("color","blue",null,"/outer/inner");
//
//  However, GetCookie cannot distinguish between these and will return
//  the first cookie that matches a given name.  It is therefore
//  recommended that you *not* use the same name for cookies with
//  different paths.  (Bear in mind that there is *always* a path
//  associated with a cookie; if you don't explicitly specify one,
//  the path of the setting document is used.)
//  
//  Revision History:
//
//    "Toss Your Cookies" Version (22-Mar-96)
//      - Added FixCookieDate() function to correct for Mac date bug
//
//    "Second Helping" Version (21-Jan-96)
//      - Added path, domain and secure parameters to SetCookie
//      - Replaced home-rolled encode/decode functions with Netscape's
//        new (then) escape and unescape functions
//
//    "Free Cookies" Version (December 95)
//
//
//  For information on the significance of cookie parameters, and
//  and on cookies in general, please refer to the official cookie
//  spec, at:
//
//      http://www.netscape.com/newsref/std/cookie_spec.html    
//
//******************************************************************
//
// "Internal" function to return the decoded value of a cookie
//
function getCookieVal (offset) {
  var endstr = document.cookie.indexOf (";", offset);
  if (endstr == -1)
    endstr = document.cookie.length;
  return unescape(document.cookie.substring(offset, endstr));
}
//
//  Function to correct for 2.x Mac date bug.  Call this function to
//  fix a date object prior to passing it to SetCookie.
//  IMPORTANT:  This function should only be called *once* for
//  any given date object!  See example at the end of this document.
//
function FixCookieDate (date) {
  var base = new Date(0);
  var skew = base.getTime(); // dawn of (Unix) time - should be 0
  if (skew > 0)  // Except on the Mac - ahead of its time
    date.setTime (date.getTime() - skew);
}
//
//  Function to return the value of the cookie specified by "name".
//    name - String object containing the cookie name.
//    returns - String object containing the cookie value, or null if
//      the cookie does not exist.
//
function GetCookie (name) {
  var arg = name + "=";
  var alen = arg.length;
  var clen = document.cookie.length;
  var i = 0;
  while (i < clen) {
    var j = i + alen;
    if (document.cookie.substring(i, j) == arg)
      return getCookieVal (j);
	i = document.cookie.indexOf(" ", i) + 1;
    if (i == 0) break; 
  }
  return null;
}
//
//  Function to create or update a cookie.
//    name - String object containing the cookie name.
//    value - String object containing the cookie value.  May contain
//      any valid string characters.
//    [expires] - Date object containing the expiration data of the cookie.  If
//      omitted or null, expires the cookie at the end of the current session.
//    [path] - String object indicating the path for which the cookie is valid.
//      If omitted or null, uses the path of the calling document.
//    [domain] - String object indicating the domain for which the cookie is
//      valid. If omitted or null, uses the domain of the calling document.
//    [secure] - Boolean (true/false) value indicating whether cookie transmission
//      requires a secure channel (HTTPS).  
//
//  The first two parameters are required.  The others, if supplied, must
//  be passed in the order listed above.  To omit an unused optional field,
//  use null as a place holder.  For example, to call SetCookie using name,
//  value and path, you would code:
//
//      SetCookie ("myCookieName", "myCookieValue", null, "/");
//
//  Note that trailing omitted parameters do not require a placeholder.
//
//  To set a secure cookie for path "/myPath", that expires after the
//  current session, you might code:
//
//      SetCookie (myCookieVar, cookieValueVar, null, "/myPath", null, true);
//
function SetCookie (name,value,expires,path,domain,secure) {
  document.cookie = name + "=" + escape (value) +
    ((expires) ? "; expires=" + expires.toGMTString() : "") +
    ((path) ? "; path=" + path : "") +
    ((domain) ? "; domain=" + domain : "") +
    ((secure) ? "; secure" : "");
}

//  Function to delete a cookie. (Sets expiration date to start of epoch)
//    name -   String object containing the cookie name
//    path -   String object containing the path of the cookie to delete.  This MUST
//             be the same as the path used to create the cookie, or null/omitted if
//             no path was specified when creating the cookie.
//    domain - String object containing the domain of the cookie to delete.  This MUST
//             be the same as the domain used to create the cookie, or null/omitted if
//             no domain was specified when creating the cookie.
//
function DeleteCookie (name,path,domain) {
  if (GetCookie(name)) {
    document.cookie = name + "=" +
      ((path) ? "; path=" + path : "") +
      ((domain) ? "; domain=" + domain : "") +
      "; expires=Thu, 01-Jan-70 00:00:01 GMT";
  }
}

//add a book code to basket
function addtoBasket(code)
{
  //check if book is in basket already
  var booklist = getAllCode()
  var str = ""
  for (var i=0; i<booklist.length; i++)
  {
    str += booklist[i]+","
  }

  var found = 0
  for (var i=0; i<booklist.length; i++)
  {
    if (code==booklist[i])
    {
      found=1;
      break;
    }
  }

  //set cookie expiry date to be 4 hours later
  var expdate = new Date ();
  FixCookieDate (expdate); // Correct for Mac date bug - call only once for given Date object!
  expdate.setTime (expdate.getTime() + (4 * 60 * 60 * 1000)); // 4 hrs from now 

  var qty = 0
  //found book in basket already
  if (found==1)
  {
    var qty = GetCookie(code)
    if (qty==null) qty="1"
    else qty = parseInt(qty)+1
  }
  else
  {
    //book is not in basket
    qty = 1 //set counter to 1

    //update book list cookie - insert new code into cookie list
    var str = GetCookie(BorneoCookieName)
    if (str==null) str=""
    if (str=="") str = code;
    else str += ":"+code
    SetCookie(BorneoCookieName, str, expdate)
  }

  //update cookie
  SetCookie (code, qty+"", expdate);
}

function updateBasket()
{
  var counter = 0

  //get all books in basket and update counter
  var booklist = getAllCode()

  for (var i=0; i<booklist.length; i++)
  {
    var b = GetCookie(booklist[i])
    if ((!isNaN(b)) && (b!=null)) counter += parseInt(b)
  }
}

function getAllCode()
{
  //get the list of Code stored in Basket
  var alllist = GetCookie(BorneoCookieName)

  if (alllist==null) // list not created yet
  {
    return "";
  }
  else
  {
    //loop through list and get all book codes
    return (alllist.split(":"))
  }
}

function delAllCode()
{
  var booklist = getAllCode();
  for (var i=0; i<booklist.length; i++)
  {
    DeleteCookie(booklist[i]);
  }
  DeleteCookie(BorneoCookieName);
}

function inBasket(code)
{
  var booklist = getAllCode()
  for (var i=0; i<booklist.length; i++)
  {
    if (code==booklist[i])
    {
      return i;
    }
  }
  return -1;
}

function delfromBasket(code)
{
  var i = inBasket(code)

  //make sure there is items to be deleted
  //if there is only 1 item in basket, just call function to delete all items
  //otherwise delete that item only
  if (NoCode()==1) delAllCode()
  else
  {
    //delete individual item cookie
    if (i>=0)
    {
      var booklist = getAllCode()
      DeleteCookie(booklist[i])
    }

    //delete item from book list cookie
    var str = GetCookie(BorneoCookieName)
    var newstr = ""
    var lastPointer = 0

    //loop through list and get all code except the one given
    for (var i=0; i<str.length; i++)
    {
      var once = 0
      if ((str.charAt(i)==":") || (i==(str.length-1)))
      {
        //found ":", then get the following stream of code
        if (str.charAt(i)==":")
        {
          var newCode = str.substring(lastPointer,i)
          if ((newCode!=code) && (newCode!=""))
          {
            if (i==(str.length-1)) newstr += newCode
            else newstr += newCode + ":"
          }
          once = 1
        }
        else if ((once==0) && (i==(str.length-1))) // no ":" at the end of string
        {
          var newCode = str.substring(lastPointer,i+1)
          if ((newCode!=code) && (newCode!="")) 
          {
            newstr += newCode
          }
        }
        lastPointer = i+1;
      }
    }

    //get rid of last ":" if exists
    if (newstr.substr(newstr.length-1,1)==":") newstr=newstr.substr(0,newstr.length-1)

    //set cookie expiry date to be 4 hours later
    var expdate = new Date ();
    FixCookieDate (expdate); // Correct for Mac date bug - call only once for given Date object!
    expdate.setTime (expdate.getTime() + (4 * 60 * 60 * 1000)); // 4 hrs from now 
 
    SetCookie(BorneoCookieName, newstr, expdate)
  }
}
function NoCode()
{
  //get all books in basket and update counter
  var booklist = getAllCode()

  return booklist.length
}

function getAllqty()
{
  var booklist = getAllCode()
  var qtylist = new Array()
  for (var i=0; i<booklist.length; i++)
  {
    qtylist[qtylist.length] = GetCookie(booklist[i])
  }
  if (qtylist.length>0) return qtylist;
  else return "";
}

//return 1 if any one fields has selected code
//return 0 otherwise
function hasItems()
{
  var row = document.form1.row.value
  for (var i=1; i<=row; i++)
  {
    var c = eval("document.form1.code"+i+".selectedIndex")
    if (c!="0") return 1;
  }
  return 0;
}

//tries to clear all items listed in table
//if cookies are used, clear all cookie
//if cookies are not used, reset all table fields
function clearAllFields()
{
  var n = NoCode();

  if ((hasItems()==1) || (n>0))
  {
    if (confirm("Clear all selection. OK?"))
    {
      delCode("999");
      getGrandTotal();
      if (n>0) self.location.reload();
    }
  } 
}

