//  Copyright (C) 2009 Enabling Simplicity LLC
//          All rights reserved
//  No portion of this script may be reproduced
//  in any form or used for any purpose other than
//  purchase of products from Enabling Simplicity.
//  Violators will be prosecuted under US and
//  international law.
//
var customer, oform, cat, lpe_entry, lse_entry, hasCollapse, isIE7compat;
//  Constructors :
//     Catalog, Catentry, Custer, Docorder, Formentry, Orderform;

//window.onload = order_form_loaded;
addDOMLoadEvent (order_form_loaded);

function dI(x) {
    //  Mainly for minification purposes
    return document.getElementById(x);
}

function isInteger(x) {
    var testresult = false;
    var integ = /(^\d+$)/;
    if ((integ.test(x)) && ! (x === "0")) {
        testresult = true;
    }
    return testresult;
}

function formatCurrency(amt, prefix)
{
    var i, flt, end, isPos, c;
    flt = parseFloat(amt.toString().replace(/\$|\,/g, ''));
    isPos = (flt == (flt = Math.abs(flt)));
    flt = Math.floor(flt * 100 + 0.50000000001);
    c = flt % 100;
    flt = Math.floor(flt / 100).toString();
    for (i = 0; i < Math.floor((flt.length - (1 + i)) / 3); i += 1) {
        end = flt.length - (4 * i + 3);
        flt = flt.substring(0, end) + ',' + flt.substring(end);
    }
    return (((isPos) ? '' : '-') + prefix + flt + '.' + ((c < 10) ? '0' : '') + c.toString());
}

function validInteger(qty) {
    if ((isNaN(0 + qty)) || (qty < 0) || qty != Math.floor(qty)) {
        return false;
    }
    else {
        return true;
    }
}

function findListValue(items, val) {
    var i, l, list;
    list = (isNaN(items.length)) ? items.split(',') : items;
    i = list.length;
    l = list.length;
    for (i = 0; i < l; i += 1) {
        if (val === list[i]) {
            return i;
        }
    }
    return '';
}

function checkqty(e) {
    var ev = (e) ? e : ((event) ? event : null);
    var elm = (ev.target) ? ev.target : ((ev.srcElement) ? ev.srcElement : null);
    var qty = elm.value;
    if (validInteger(qty)) {
        oform.refillform();
    }
    else {
        alert('license quantity must be a whole number greater than 0');
        setTimeout(function () {
            elm.focus(); 
            elm.select();
        }
        , 1);
    }
}

function noreturn(evarg) {
    var ev = (evarg) ? evarg : ((event) ? event : null);
    var node = (ev.target) ? ev.target : ((ev.srcElement) ? ev.srcElement : null);
    if (ev.keyCode === 13) {
        oform.refillform(); 
        return false;
    }
}

function isIE() {
    return navigator.mimeTypes && ! navigator.mimeTypes.length;
}

function showelement(elem) {
    elem.style.visibility = 'visible';
    if (hasCollapse && elem.nodeName !="DIV") {
        elem.style.visibility = 'visible';
    }
    else {
    		if (elem.nodeName == "TABLE") {
		        elem.style.display = 'inline-block';
    		} 
    		else {
		        elem.style.display = 'inline';
		    }    
    }    
}

function hideelement(elem) {
    if (hasCollapse && elem.nodeName !="DIV") {
        elem.style.visibility = 'collapse';
    }
    else {
        elem.style.visibility = 'hidden';
        elem.style.display = 'none';
    }
}

function isHidden(ckelem) {
    var x = dI(ckelem);
    var ppx = x.parentNode.parentNode;
    if (hasCollapse) {
        return ppx.style.visibility != 'visible';
    }
    else {
        return ppx.style.display === 'none';
    }
}

function isVisible(ckelem) {
    return ! isHidden(ckelem);
}

function showitem(rtags) {
    var i, list, li, el;
    list = rtags.split(',');
    for (i = 0; i < list.length; i += 1)
    {
        li = list[i];
        el = dI(li);
        el = el.parentNode.parentNode;
        showelement(el);
    }
}

function hideitem(rtags) {
    var i, list, x;
    list = rtags.split(',');
    for (i = 0; i < list.length; i += 1)
    {
        x = dI(list[i]);
        hideelement(x.parentNode.parentNode);
    }
}

function first_text(elem) {
    var i, n, nm, val, temp, cnodes;
    cnodes = elem.childNodes;
    if (cnodes) {
        for (i = 0; i < cnodes.length; i += 1) {
            n = cnodes[i];
            nm = n.nodeName;
            if (nm && nm == '#text') {
                val = n.nodeValue;
                if (val && /\S/.test(val)) {
                    return n;
                }
                else {
                    continue;
                }
            }
            temp = first_text(cnodes[i]);
            if (temp != '#*#') {
                return temp;
            }
        }
        return '#*#';
    }
    return '#*#';
}

function tryone(url, httpmgr) {
    // temporary
    //  return 200;
    // temporary
    var u = customer;
    try {
        httpmgr.open("HEAD", url, false, u.user, u.pass);
        httpmgr.send(null);
    }
    catch (e) {
        alert('javascript issue: unable to check login credentials');
    }
    return httpmgr.status;
}

function customizenonuserform() {
    showitem('HBZ,UUP,LPE,LSE');
}

function customizeuserform(has, allprods) {
    var licenselist = has.join(',');
    hideitem(allprods.toString());
    if (! licenselist.match(/\=y/)) {
        customizenonuserform(); 
        return;
    }
    if (licenselist.match(/hbz=y/)) {
        showitem('HBZX');
    }
    else {
        showitem('HBZ');
    }
    if (licenselist.match(/uu=y/g)) {
        showitem('UUPX');
    }
    else {
        showitem('UUP');
    }
    if (licenselist.match(/lpe=y/)) {
        showitem('LPX');
    }
    else if (licenselist.match(/lse=y/)) {
        showitem('LSX,UGSP');
    }
    else if (licenselist.match(/ve=y/)) {
        showitem('UGVP,UGVS');
    }
    else {
        showitem('LPE'); 
        showitem('LSE');
    }
//    if (isHidden('UGVS') && ! licenselist.match(/lpe=y/)) {
    if (!licenselist.match(/lpe=y/)) {
        if (! licenselist.match(/fnv=y/)) {
            showitem('FNV');
        }
        if (! licenselist.match(/fnt=y/)) {
            showitem('FNT');
        }
        if (! licenselist.match(/fnd=y/)) {
            showitem('FND');
        }
        if (! licenselist.match(/fnr=y/)) {
            showitem('FNR');
        }
        if (! licenselist.match(/fns=y/)) {
            showitem('FNS');
        }
    }
}

function Catentry(product, prodfullname, price) {
    this.product = product;
    this.prodfullname = prodfullname;
    this.price = price;
    this.qty = 0;
    this.discount = 0;
}

function Catalog() {
    var c = [];
    var me = this;
    function pushcat(tag, desc, price) {
        c.push(new Catentry(tag, desc, price));
    }

    function findcitem(tag) {
        var i = 0;
        var l = c.length;
        var ci = new Catentry();
        for (i = 0; i < l; i += 1) {
            ci = c[i]; 
            if (tag == tag.match(ci.product)) {
                break;
            }
        }
        return i;
    }

    this.getcitem = function (tag) {
        return c[findcitem(tag)];
    };

    this.gettags = function () {
        // c is an array local to the enclosing constructor function
        var k = c.slice(0);
        var t = [];
        var i = 0;
        var l = k.length;
        var ci = new Catentry();
        for (i = 0; i < l; i += 1) {
            ci = k[i]; 
            t.push(ci.product);
        }
        return t;
    };

    this.getprice = function (tag) {
        if (tag == "UT") {
            alert('script error - inform Enabling Simplicity');
        }
        return me.getcitem(tag).price;
    };

    pushcat('LPE', 'UltraTree Lifetime Premium Edition', 599);
    pushcat('LSE', 'UltraTree Lifetime Standard Edition', 399);
    pushcat('UGVS', 'UT Lifetime Standard Upgrade', 200);
    pushcat('UGVP', 'UT Lifetime Premium Upgrade', 400);
    pushcat('UGSP', 'UT Lifetime Premium Upgrade', 200);
    pushcat('LPX', 'UltraTree Lifetime Premium Edition', 599);
    pushcat('LSX', 'UltraTree Lifetime Standard Edition', 399);
    pushcat('HBZ', 'HyperBrowZe', 399);
    pushcat('HBZX', 'HyperBrowZe', 399);
    pushcat('UUP', 'Up and Up', 199);
    pushcat('UUPX', 'Up and Up', 199);
    pushcat('FNT', 'UT Tagging Feature', 75);
    pushcat('FNV', 'UT Recursive Views', 75);
    pushcat('FNR', 'UT Rearrange Feature', 50);
    pushcat('FNS', 'UT Stylesheet Feature', 50);
    pushcat('FND', 'UT Drag and Drop Feature', 50);
    this.c = c.slice(0);
}

// Called when an add button is pressed
// mainly to centralize the management of mutual exclusivity of products
function mutualExclude(tag) { 
    function g(tag) {
        return oform.getItemByTag(tag);
    }
    var ying, yang;
    yang = g(tag);
    switch (tag) {
    case "LSE":
        ying = g("LPE");
        break;
    case "LPE":
        ying = g("LSE");
        break;
    case "UGVS":
        ying = g("UGVP");
        break;
    case "UGVP":
        ying = g("UGVS");
        break;
    case "UGSP":
        ying = g("LSX");
        break;
    case "LSX":
        ying = g("UGSP");
        break;
    default:
        return;
    }
    yang.excludeEntry(ying);        
}

function getInputRow(item) {
		var mothr,mname;
		mothr = item;
		mname = 'X'
		while (mname !== 'TR')
		{
			mothr = mothr.parentNode;
			if (mothr) {mname = mothr.nodeName;}
			else {return document;}
		}
		return mothr;	
}
   
function Formentry(rowtag) {
    var qty_col = 0,
    add_col = 1;
    prod_col = 2,
    price_col = 3,
    total_col = 4,
    x = dI(rowtag);
    var rowcells;

    function removeItem(e) {
        e.addstat = 0; // 0 if addbutton showing, 1 if deletebutton
        e.addbutton.src = "buttons/addbutton.jpg";
        e.addbutton.title = "add this item to the cart";
        e.outbutton = e.addbutton.src;
        e.quantity.value = 0;
        e.discamt = 0;
        hideelement(e.quantity);
    }

    function handleButton(ev) {
        var me;
        var e = (ev) ? ev : window.event;
        var targ;
        if (e.target) {
            targ = e.target;
        }
        else if (e.srcElement) {
            targ = e.srcElement;
        }
        else {
            targ = null;
        }
        if (targ.nodeType == 3) // defeat Safari bug
        {
            targ = targ.parentNode;
        }
        me = targ.me;
        if (me.addstat === 0) {
            switch (e.type)
            {
            case "mouseover" :
                me.outbutton = targ.src;
                targ.src = "buttons/addbutton_over.jpg";
                break;
            case "mouseout" :
                targ.src = me.outbutton;
                break;
            case "click" :
                me.addstat = 1;
                targ.src = "buttons/deletebutton.jpg";
                me.addbutton.title = "remove this item from the cart";
                me.outbutton = targ.src;
                me.quantity.value = 1;
                showelement(me.quantity); 
                mutualExclude(me.rowtag);
                if (me.rowtag === "UGVP" || me.rowtag === "UGVS") {
                    hideitem('FND,FNS,FNR,FNV,FNT');
                }
                oform.refillform();
                break;
            default :
                break;
            }
        }
        else {
            switch (e.type)
            {
            case "mouseover" :
                me.outbutton = targ.src;
                targ.src = "buttons/deletebutton_over.jpg";
                break;
            case "mouseout" :
                targ.src = me.outbutton;
                break;
            case "click" :
                removeItem(me);  // removes the item from the cart only, not the form !
                oform.refillform();
                break;
            default :
                break;
            }
        }
    }
    function findnode(nodes) {
        for (var i = 0; i < nodes.length; i += 1) {
            if (nodes[i].nodeValue !== undefined) {
                return nodes[i];
            }
        }
        return null;
    }
    this.excludeEntry = function (e) {
        removeItem(e);  // removes item form order
    };
    this.formrow = getInputRow(x);
    //this.formrow = x.parentNode.parentNode;
    rowcells = this.formrow.getElementsByTagName("TD");
    this.rowprice = 0;
    this.addstat = 0;
    this.rowtag = rowtag;
    if (rowtag === 'LPE') {
        lpe_entry = this;
    }
    else if (rowtag === 'LSE') {
        lse_entry = this;
    }
    this.quantity = rowcells[qty_col].getElementsByTagName("INPUT")[0];
    this.quantity.value = 0;
    this.discamt = 0;
    hideelement(this.quantity);
    this.price = findnode(rowcells[price_col].childNodes);
    this.extendedPrice = findnode(rowcells[total_col].childNodes);
    this.addbutton = rowcells[add_col].getElementsByTagName("IMG")[0];
    this.addbutton.onclick = handleButton;
    this.addbutton.onmouseover = handleButton;
    this.addbutton.onmouseout = handleButton;
    this.addbutton.rowtag = rowtag;
    this.addbutton.title = "add this item to the cart";
    this.addbutton.me = this;
    this.outbutton = "";
}

function Docorder() {
    var item, fe;
    var i, cust = customer, licenselist = '';
    var that = this;
    var prodcodes = cat.gettags();
    var discnode = dI('dscnt').childNodes[0];
    var subtotalnode = dI('subtotal').childNodes[0];
    var totalnode = dI('grandtotal').childNodes[0];
    var logintable = dI('logintable');
    var ckoblock = dI('ckoblock');
    var additemsrow = dI('additemsrow');
    var totalstable = dI('totalstable');
    
    this.getItemByTag = function (tag) {
        var i, c;
        for (i = 0; i < this.lineitem.length; i += 1) {
            c = this.lineitem[i];
            if (c.rowtag === tag) {
                return c;
            }
        }
        return null;
    };

    this.refillform = function () {
        var orderhasUT, orderhasUGVS, orderhasUGVP, orderhasUGSP, LSEQty;
        var u = customer;
        var i, qty, qtyval, price, extprice, cattag, formItem, theItem, isLPE = false;

        function settotal(x) {
            var fitem = formItem;
            var citem = cat.getcitem(cattag);
            var u = customer;
            var catsep = (u.orderlist.length === 0) ? '' : ',';
            var qty, extprice, price, itag;
            var junk;
            qty = Number(fitem.quantity.value); // damn thing is a string unless Number is used. 
            citem.qty = qty;
            switch (x) {
            case 0 :
                var catprice = cat.getprice(cattag);
                fitem.price.nodeValue = "$" + catprice;
                fitem.extendedPrice.nodeValue = " ";
                break;
            case 1 :
                u.orderlist += (catsep + cattag);
                price = cat.getprice(cattag);
                fitem.price.nodeValue = "$" + price;
                fitem.extendedPrice.nodeValue = "$" + String(price * qty);
                u.subtotal += price * qty;   // keep tabs on the total order
                u.numitems += qty;           // keep tally of total licenses ordered
                // Count items qualified for quantity discount - excludes upgrades and feature items
                junk = cattag;
                junk1 = junk.indexOf("UG");
                junk2 = junk.indexOf("FN");
                u.num_qualified += (junk.indexOf("UG") === 0 || junk.indexOf("FN") === 0) ? 0 : qty;
                break;
            case 2 :
                fitem.price.nodeValue = 'included';
                fitem.extendedPrice.nodeValue = " ";
                break;
            case 3 :
                fitem.price.nodeValue = ' ';
                fitem.extendedPrice.nodeValue = ' ';
                break;

            }
        }

        orderhasUT = false;
        orderhasUGVS = false;
        orderhasUGVP = false;
        orderhasUGSP = false;
        LSEQty = 0;
        customer.cleartotals();
        customizeuserform(u.lic, prodcodes);

        for (i = 0; i < that.lineitem.length; i += 1) {
            theItem = that.lineitem[i];
            formItem = theItem;
            qty = theItem.quantity;
            qtyval = Number(qty.value);
            cattag = formItem.rowtag;
            if (isHidden(cattag)) {
                qty.value = 0;
            }
            switch (cattag)
            {
            case "LSE" :
                if (qtyval > 0) {
                    orderhasUT = true;
                    isLPE = false;
                    LSEQty = qtyval;
                    showelement(qty);
                    settotal(1);
                    showitem('FND,FNS,FNR,FNV,FNT');
                }
                else {
                    settotal(0);
                }
                break;
            case "LPE" :
                if (qtyval > 0) {
                    orderhasUT = true;
                    isLPE = true;
                    showelement(qty);
                    settotal(1);
                    showitem('FND,FNS,FNR,FNV,FNT');
                }
                else {
                    settotal(0);
                }
                break;
            case "LSX" :
                /*  more LSE licenses */
                if (orderhasUGSP) {
                    qty.value = 0;
                    qty.disabled = true;
                }
                else {
                    qty.disabled = false;
                }
                if (qty.value > 0) {
                    settotal(1);
                }
                else {
                    settotal(0);
                }
                break;
            case "UGSP" :
                orderhasUGSP = (qty.value > 0) ? true : false;
                if (orderhasUGSP) {
                    settotal(1);
                }
                else {
                    settotal(0);
                }
                break;
            case "UGVS" :
                qty.disabled = true;  // this is alwaya disabled because VE licenses are always single
                orderhasUGVS = (qty.value > 0) ? true : false;
                if (orderhasUGVS) {
                    settotal(1);
                }
                else {
                    settotal(0);
                }
                break;
            case "UGVP" :
                qty.disabled = true;  // this is alwaya disabled because VE licenses are always single
                orderhasUGVP = (qty.value > 0) ? true : false;
                if (orderhasUGVP) {
                    settotal(1);
                }
                else {
                    settotal(0);
                }
                break;
            case "FNV" :
            case "FNT" :
            case "FND" :
            case "FNR" :
            case "FNS" :
                if (orderhasUT || ! (isHidden('UGVP') && isHidden('UGSP') && isHidden('LSX')))
                {
                    if (isLPE || orderhasUGVP || orderhasUGSP)
                    {
                        hideelement(qty);
                        hideelement(theItem.addbutton);
                        settotal(2);
                    }
                    else
                    {
                        showelement(theItem.addbutton);
                        if (theItem.addstat === 1) { // means the deletebutton is showing so item is chosen
                            showelement(qty);
                            qty.value = (LSEQty > 0) ? LSEQty : 1;  // Use LSEQ
                            settotal(1);
                            qty.disabled = true;
                        }
                        else {
                            hideelement(qty);
                            settotal(0);
                        }
                    }
                }
                else
                {
                    qty.disabled = false;
                    if (! isHidden('LPE'))
                    {
                        if (isLPE) {
                            settotal(2);
                        }
                        else {
                            settotal(0);
                        }
                    }
                }
                break;
            default :
                if (qty.value > 0) {
                    settotal(1);
                }
                else {
                    settotal(0);
                }
                break;

            }
        }
        /* end for loop */

        customer.calc_discount();
        subtotalnode.nodeValue = formatCurrency(customer.subtotal, '$');
        discnode.nodeValue = formatCurrency(customer.discount, '$');
        totalnode.nodeValue = formatCurrency(customer.total, '$');
        if (customer.subtotal > 0) {
            hideelement(additemsrow);
            showelement(ckoblock);
            showelement(totalstable);
            showelement(dI('carthd1'));
            showelement(dI('carthd2'));
            showelement(dI('carthd3'));
            showelement(dI('discmsg'));
            showelement(dI('prnbutton'));
            
        }
        else {
            hideelement(ckoblock);
            hideelement(totalstable);
            hideelement(dI('discmsg'));
            hideelement(dI('prnbutton'));
            showelement(additemsrow);
        }
        return;

    };   /* end this.refillform  */

    hideelement(ckoblock);
    hideelement(totalstable);
    this.lineitem = [];
    for (i = 0; i < prodcodes.length; i += 1) {
        fe = new Formentry(prodcodes[i]);
        this.lineitem[i] = fe;
    }
}


function Custer() {
    var that = this;
    this.tracer = 'Custer';
    this.user = '';
    this.pass = '';
    this.validuser = false;
    this.lic = [];         // list of previously licensed products in form of lowercase item tags
    this.blic = [];        // this.lic includes UT features, this.blic does not.
    this.orderlist = '';   // list of uppercase item tags in comma delimited string (products in order)
    this.numitems = 0.00;  // total number of individual licenses in current order
    this.num_qualified = 0.00;
    this.subtotal = 0.00;  // actually gross order
    this.total = 0.00;     // actually net after discounts
    this.volume_discount = 0.00;  // volume discount for the order
    this.sale_discount = 0.00;    // sale discount for the order
    this.discount = 0.00;         // total discount for the order  (sale + volume)
    this.discountrate = 0.00;     // calculated discount rate for the whole order

    this.clearauth = function () {
  	    that.user = '';
	      that.pass = '';
		    that.lic = [];         // list of previously licensed products in form of lowercase item tags
		    that.blic = [];        // this.lic includes UT features, this.blic does not.
	      that.validuser = false;
        hideelement(dI("logintable"));     // login rows no longer needed
    }
    
    this.cleartotals = function () {
        // do NOT clear lic 
        this.numitems = 0.0;
        this.num_qualified = 0.0;
        this.total = 0.0; 
        this.subtotal = 0.0; 
        this.discount = 0.0;
        this.orderlist = '';
    }; /* end this.cleartotals   */

    this.tryauth = function () {
        var httpmgr, ret, flic, x, y, z, ll, i;
        var d = document;
        var url, urlbase = '';

        this.user = dI('licensee').value;
        this.pass = dI('custpass').value;
        this.lic = ['lpe', 'lse', 've', 'uu', 'hbz', 'uj2'];
        this.blic = this.lic.slice(0);

        function updatelic(him) {
            var temp;
            ret = (ret === 200) ? 'y' : 'n';
            if (ret === 'y') {
                him.validuser = true;
            }
            temp = him.lic[i] + '=' + ret;
            him.lic[i] = temp;
        }
        /* end updatelic  */

        httpmgr = (window.XMLHttpRequest) ? new XMLHttpRequest() : new ActiveXObject('Microsoft.XMLHTTP');
        for (i = 0; i < this.lic.length; i += 1) {
            url = urlbase + 'auth' + this.lic[i] + '.php';
            ret = tryone(url, httpmgr);
            if (ret > 400) {
                alert('Validation script error. Response was ' + ret);
                break;
            }
            updatelic(this);
        } //  end for
        x = /lse=y/g;
        y = /ve=y/g;
        z = this.lic.toString();
        ll = this.lic.length;
        if (z.match(x) || z.match(y)) {
            flic = ['fnv', 'fnt', 'fnd', 'fnr', 'fns'];
            this.lic = this.lic.concat(flic);
            for (i = ll; i < this.lic.length; i += 1) {
                url = urlbase + 'auth' + this.lic[i] + '.php';
                ret = tryone(url, httpmgr);
                updatelic(this);
            }
            /* end for lic items */
        }
        /* end if */

        hideelement(dI("logintable"));     // login rows no longer needed
        if (this.user && this.validuser === false) {
            showelement(dI("validationrow3")); // no license found message
            hideelement(dI("validationrow2")); // licensee found
            hideelement(dI("validationrow1")); // original prompt
            this.lic.length = 0;
            this.blic.length = 0;
        }
        /* end if */
        else if (this.user && this.validuser === true) {
            hideelement(dI("validationrow3")); // no license found message
            showelement(dI("validationrow2")); // licensee found
            hideelement(dI("validationrow1")); // original prompt
        }
        /* end else */
        else {
            hideelement(dI("validationrow3")); // no license found message
            hideelement(dI("validationrow2")); // licensee found
            showelement(dI("validationrow1")); // original prompt
        }
        /* end else */

        customizeuserform(this.lic, cat.gettags());
        //oform.refillform();
        junk = 0; // for debug stop only
        //return false;

    };  /* end this.tryauth */

    this.setdisc = function () {
        var i, c, k, xk, l, m, s, list, discrates, liccount, discrate, discnode, aggregate_count, volume_discountrate, discount_base, dummy; 
        if (!this.orderlist.length) {return;}
        list = this.orderlist.split(',');  
        this.discount = 0;
        this.discountrate = 0;

        // the base for applying volume discounts is an even $100 multiple
        // and does not include items whose tags begin 'UG' or 'FN' (features or upgrades)
        discount_base = 0;
        for (i = 0; i < list.length; i += 1) {
            s = list[i];
            c = cat.getcitem(s);
            discount_base += (s.indexOf("UG") === 0 || s.indexOf("FN") === 0) ? 0.00 : c.price * c.qty;       
        }
        discount_base = 100 * Math.ceil(discount_base / 100);  
        discrates = [0, 0, 0.1, 0.15, 0.20, 0.25]; // discount rates for 0, 1, 2,... items
        liccount = 0;
        // If this.validuser is false, this.lic has no length
        // Here we count the number of licensed major products 
        for (i = 0; i < this.blic.length; i += 1) { // blic used only to mark the items that are discount generators
            if (this.lic[i].indexOf("=y") > 0) {
                liccount += 1;         
            }
        }
        //  discount rate increases up to 5 items ordered or previously licensed 
        volume_discountrate = discrates[Math.min(5,this.num_qualified + liccount)];  

        this.volume_discount = discount_base * volume_discountrate;

        //  sale is 20% off
        //  if order more than 200, rounded up to nearest $10
        //  otherwise round to nearest dollar
        //xk = 0.20 * (this.subtotal - this.volume_discount);  // the raw discount
       // m = xk % 1;  
        //k = (this.subtotal > 200 && m > 1) ? 10 : 1;   // the discount rounding factor
        //this.sale_discount = k * Math.ceil((1/k) * xk);
        this.sale_discount = 0;
        
        this.discount = this.sale_discount + this.volume_discount;
        if (this.discount > 0) {
            dummy = 7;   
        }
        discrate = (this.discount > 0) ? this.discount / this.subtotal : 0.00;      

        var discmsg = ((discrate > 0) && this.subtotal > 0) ? (' (' + Math.floor(discrate * 100).toString() + '%)') : '';
        // discmsg = 'Discount ' + discmsg;
        discmsg = 'Discount:';
        discnode = first_text(dI('disclabel'));
        discnode.nodeValue = discmsg;
        this.discountrate = discrate;
    };

    this.calc_discount = function () {
        this.setdisc();
        this.total = this.subtotal - this.discount;
    };

    that = this;
}


// @
function Orderform(who) {
    var my = this;
    var me = who;
    this.who = who;
    this.prodcount = 0;
    this.theForm = document.createElement('form');
    this.theForm.method = "POST";
    this.theForm.target = '_self';
}

Orderform.prototype.initform = function () {
    switch (this.who) {
    case "pp" :
        this.theForm.action = "https://www.paypal.com/us/cgi-bin/webscr";
        this.aI("cmd", "_cart");
        this.aI("upload", "1");
        this.aI("business", "admin@enablingsimplicity.com");
        this.aI("no_shipping", "1");
        this.aI("no_note", "1");
        this.aI("currency_code", "USD");
        this.aI("lc", "US");
        this.prod_stub = "item_name_";
        this.qty_stub = "quantity_";
        this.price_stub = "amount_";
        this.desc_stub = "";
        break;
    case "gc" :
        this.theForm.action = "https://checkout.google.com/cws/v2/Merchant/133884871943070/checkoutForm";
        //  this.theForm.action = "https://sandbox.google.com/checkout/cws/v2/Merchant/965182923943434/checkoutForm";
        this.aI("_charset_", "utf-8");
        this.prod_stub = "item_name_";
        this.qty_stub = "item_quantity_";
        this.price_stub = "item_price_";
        this.desc_stub = "item_description_";
        break;
    }
};
//*
Orderform.prototype.aI = function (nm, val) {
    var newEl;
    if (isIE()) {
        newEl = document.createElement("<input name='" + nm + "'>");
    }
    else {
        newEl = document.createElement("input");
        newEl.name = nm;
    }
    newEl.value = val;
    newEl.type = "hidden";
    this.theForm.appendChild(newEl);
};
//*
Orderform.prototype.aP = function (citem) {
    var itemnum, me, fmtdisc, proddesc;
    this.prodcount += 1;
    itemnum = this.prodcount;
    me = this.who;
    // Make the quantity  entry for the current item
    this.aI(this.qty_stub + itemnum, citem.qty);

    // For Paypal we allocate discount across items 
    // For GCO we deduct the discount as a separate item
    // The allocated discount is per item, due to the fact PayPal does the multiply of qty by item price

    // Make the price entry for this item
    this.aI(this.price_stub + itemnum, formatCurrency(citem.price - citem.discount, ''));

    // Make the description entry for this item
    if (this.desc_stub) {  // The GCO case
        this.aI(this.desc_stub + itemnum, 'single user license');
        this.aI(this.prod_stub + itemnum, citem.prodfullname);
    }
    else { // The PayPal case
        proddesc = citem.prodfullname + ' - single user license';
        if (citem.discount) {
            fmtdisc = formatCurrency(citem.discount * citem.qty, '$');
            this.aI(this.prod_stub + itemnum, proddesc + ' (discounted ' + fmtdisc + ')');
        }
        else {
            this.aI(this.prod_stub + itemnum, proddesc);
        }
    }
};
//*
Orderform.prototype.sendOrder = function () {
    var theBody, me, catitem, list;
    list = customer.orderlist;
    var i, lineitems, itemnum, discval;
    me = this.who;
    this.initform(me);
    this.prodcount = 0;
    lineitems = list.split(',');
    for (i = 0; i < lineitems.length; i += 1) {
        catitem = cat.getcitem(lineitems[i]);
        this.aP(catitem);
    }
    if ((me === 'gc') && customer.discount > 0) {  // For GCO we add a discount line item if discounted order
        itemnum = 1 + lineitems.length;
        itemnum = itemnum.toString();
        discval = formatCurrency(- 0.01 * Math.floor(customer.discount * 100), '');
        this.aI(this.price_stub + itemnum, discval);
        this.aI(this.qty_stub + itemnum, 1);
        this.aI(this.prod_stub + itemnum, 'Discount');
        this.aI(this.desc_stub + itemnum, '(' + (Math.floor(100 * customer.discountrate)).toString() + '%)');
    }
    theBody = document.getElementsByTagName('body')[0];
    this.theForm.id = 'zfx';
    var elm = dI(this.theForm.id);
    if (elm) {
        theBody.removeChild(elm);
    }
    theBody.appendChild(this.theForm);
    dI(this.theForm.id).submit();
    return false;
};
//*
//
function placeOrder(who) {
    var x = new Orderform(who);
    x.sendOrder();
}
//*
function pp_checkout() {
    var lineitems, citem, totaldisc, i, j, x;
    // Allocate discount to line items. PP does not support a negative-valued line item.
    lineitems = customer.orderlist.split(',');
    totaldisc = customer.discount;
    //alert('original discount for order is ' + totaldisc);
    //alert('cat.c.length is ' + cat.c.length);
    for (i = 0; i < cat.c.length; i += 1) {
        citem = cat.c[i];
        citem.discount = 0; //  VERY necessary housekeeping
    }  
    for (i = 0; i < 1000; i += 1) {
        j = (i < lineitems.length) ? i : i % lineitems.length;
        citem = cat.getcitem(lineitems[j]);
        if (citem.discount > 0) {
            x = 0.01 / citem.qty; 
            citem.discount += x;
            //alert('changed discount for ' + citem.product + ' to ' + citem.discount);
            totaldisc -= 0.01;
        }    
        else {           
            citem.discount = 0.01 * Math.floor(100 * customer.discountrate * citem.price);     
            // item total discount must be an exact multiple of the item quantity
            //alert('set discount for ' + citem.product + ' to ' + citem.discount);
            totaldisc -= citem.qty * citem.discount;
        }
        if (totaldisc <= 0) {
            break;
        }
    }
//    alert('final discount for order is ' + totaldisc);
    placeOrder('pp');
}

function gc_checkout() {
    placeOrder('gc');
}

//*

function configurePrintable() {
    var d, q, prods, disc, ihtml, frag, itemtable, itemtablerows, modelrow;

    function set_valuenode(d, trow, val) {
        var tdnodes = trow.getElementsByTagName('td');
        var cnode = tdnodes[2];
        var txtnode = d.createTextNode(formatCurrency(val, '$'));
        cnode.appendChild(txtnode);
    }
    /* end set_valuenode */

    function add_itemrows(d, v) {
        var i, r, u, c, p, ci, rRef;

        function makecell(cls, txt) {
            var col = d.createElement('td');
            var txtfrag = d.createTextNode(txt);
            col.className = cls;
            col.appendChild(txtfrag);
            return col;
        }
        /* end makecell */

        u = customer;
        p = u.orderlist.split(',').reverse();
        for (i = 0; i < p.length; i += 1) {
            rRef = d.createElement('tr');
            ci = cat.getcitem(p[i]);
            rRef.appendChild(makecell('aaqtytext', ci.qty));
            rRef.appendChild(makecell('aaproducttext', ci.prodfullname + ' - single user license'));
            rRef.appendChild(makecell('aaproductprice', formatCurrency(ci.qty * ci.price, '$')));
            v.parentNode.insertBefore(rRef, v);
        }
    }
    /* end add_itemrows */

    d = NewWindow.document;
    itemtable = d.getElementsByTagName('table')[1];
    itemtablerows = itemtable.getElementsByTagName('tr');
    modelrow = itemtablerows[3];  // 5, 6, 8
    set_valuenode(d, itemtablerows[6], customer.subtotal);
    set_valuenode(d, itemtablerows[7], - customer.discount);
    set_valuenode(d, itemtablerows[10], customer.total);
    add_itemrows(d, modelrow);
    modelrow.parentNode.removeChild(modelrow);
}
/* end configurePrintable  */

function printOrder() {
    var d, hd, bdy, htm, t;
    NewWindow = window.open('printform.htm', '_blank',
    "width=700,height=500," +
    "menubar=1," +
    "toolbar=0," +
    "status=0," +
    "scrollbars=1," +
    "resizable=0");

    d = NewWindow.document;
    if (isIE()) {
        while (! d.getElementsByTagName('table').length) {
            continue;
        }
        configurePrintable();
    }
    else {
        NewWindow.onload = configurePrintable;
    }
}

function myfp_getObjectByID(oid, o) {
    var c, el, els, f, m, n;
    if (! o) {
        o = document;
    }
    if (o.getElementById) {
        el = o.getElementById(oid);
    }
    else if (o.layers) {
        c = o.layers;
    }
    else if (o.all) {
        el = o.all[oid];
    }
    if (el) {
        return el;
    }
    if (o.id == oid || o.name == oid) {
        return o;
    }
    if (o.childNodes) {
        c = o.childNodes;
    }
    if (c) {
        for (n = 0; n < c.length; n += 1) {
            el = myfp_getObjectByID(oid, c[n]);
            if (el) {
                return el;
            }
        }
    }
    f = o.forms;
    if (f) {
        for (n = 0; n < f.length; n += 1) {
            els = f[n].elements;
            for (m = 0; m < els.length; m += 1) {
                el = myfp_getObjectByID(oid, els[n]);
                if (el) {
                    return el;
                }
            }
        }
    }
    return null;
}

function myfp_swapImg() {
    var doc = document, args = arguments, elm, n;
    doc.imgSwapArray = [];
    for (n = 2; n < args.length; n += 2) {
        elm = myfp_getObjectByID(args[n]);
        if (elm) {
            doc.imgSwapArray[doc.imgSwapArray.length] = elm;
            elm.$src = elm.src;
            elm.src = args[n + 1];
        }
    }
}

function myfp_preloadImgs() {
    var d = document, a = arguments;
    if (! d.myfp_imgs) {
        d.myfp_imgs = [];
    }
    for (var i = 0; i < a.length; i += 1) {
        d.myfp_imgs[i] = new Image();
        d.myfp_imgs[i].src = a[i];
    }
}

function mymouser(evarg) {
    var x, e, elm;
    var ev = (evarg) ? evarg : ((event) ? event : null);
    elm = (ev.target) ? ev.target : ((ev.srcElement) ? ev.srcElement : null);
    switch (ev.type) {
    case 'mouseover' :
        x = 1; 
        e = 'over';
        break;
    case 'mouseout' :
        x = 0; 
        e = 'out';
        break;
    case 'mouseup' :
        x = 0; 
        e = 'out';
        break;
    case 'mousedown' :
        x = 1; 
        e = 'down';
        break;
        // default : return;
    default :
        x = 0; 
        e = 'out';
        break;
    }
    myfp_swapImg(x, 0, elm.id, elm.uuu + e + '.jpg');
}

function setoneswap(s) {
    var u = 'buttons/' + s + '_';
    var iid = s + '_img';
    var elm = dI(iid);
    if (! elm) {
        return;
    }
    elm.uuu = u;
    myfp_preloadImgs(u + 'over.jpg', u + 'down.jpg');
    elm.onmouseover = mymouser;
    elm.onmousedown = mymouser;
    elm.onmouseup = mymouser;
    elm.onmouseout = mymouser;
}

Array.prototype.reduction = function (f) {
    if (this.length == 1) {
        return this[0];
    }
    var xl = this.slice(0);
    var x = xl.pop();
    return f(xl.reduction(f), x);
};

function setswaps(m) {
    var a = m.split(',');
    var i, l = a.length;
    for (i = 0; i < l; i += 1) {
        setoneswap(a[i]);
    }
}

function order_form_loaded() {
    var checkCollapse = function (o) {
        if (document.documentMode && document.documentMode < 8) {
        		return false;
        }
        try { 
            o.style.visibility = 'collapse';
            if (o.style.visibility === 'collapse') {
                return true;    
            }
        }
        catch (e) {
            o.style.display = 'none';
            return false;
        }
        return false;
    };    
    hasCollapse = checkCollapse(dI("UUPX").parentNode);
    hideelement(dI("scriptmsg"));
    hideelement(dI("ckoblock"));
    hideelement(dI("totalstable"));
    hideelement(dI("logintable"));
    hideelement(dI("validationrow2"));  // login accepted message
    hideelement(dI("validationrow3"));  // login denied message
    showelement(dI("mastertable"));  // the whole shebang
    showelement(dI("scripted_content"));  // the whole shebang
    customer = new Custer();
    cat = new Catalog();
    oform = new Docorder();
    var i, elm;
    var refill = oform.refillform;
    var d = document;
    var cartitems = dI('cartitems');
    var inputnodes = cartitems.getElementsByTagName("INPUT");
    for (i = 0; i < inputnodes.length; i += 1) {
        elm = inputnodes[i];
        elm.onchange = checkqty;
    }

    dI("licensee").onchange = refill;
    dI("custpass").onchange = refill;
    dI("gc_img").onclick = gc_checkout;
    dI("pp_img").onclick = pp_checkout;
    dI("prn_img").onclick = printOrder;
    dI('log_img').onclick = function () {
        customer.tryauth();
    };
    dI('can_img').onclick = function () {
        customer.clearauth();
    };
    var slw = function () {  // show login pseudo-window
        showelement(dI("logintable"));
        setTimeout(function () {
            dI("licensee").select();
        },50);
    };
    dI("validationrow1").onclick = slw;
    dI("validationrow3").onclick = slw;
    d.onkeypress = noreturn;
    setswaps('can,log,prn,chk,hbz_info,uu_info,lse_info,lpe_info');
    refill();
}
