
function Basket(name, ver, orderRef, cookieID, containerId) {
    var m_arrProd = new Array;
    var m_arrSortProd = new Array;
    var m_arrNotifications = new Array;
    var m_lastUpdatedID;
    var m_lastModTime = 0;
    var m_debug = false;
    var m_debugTrace = '';
    var m_startTime = 0;
    var m_reCheckTicks = 5000;
    var m_errorMessage = '';
    var m_budgetAmount = -1;
    var m_overBudget = false;
    var m_endItemCheck = false;

    //ver=3;
    //Public accessible variables
    this.version = ver;
    this.name = name;
    this.orderRef = orderRef;
    this.cookieID = cookieID;
    this.containerId = containerId;
    this.items = function() { return m_arrProd; };
    this.offline = 0;
    this.checkedOut = 0;
    this.isList = 0;
    this.BulkWrite = 0;
    this.MinOrderVal = 0;


    this.TotalVal = 0;
    //Methods
    this.previousLineNo = p_previousLineNo;
    this.renumberItems = p_renumberItems;
    this.paintTotals = p_paintTotals;
    this.lineNo = p_lineNo;
    this.index = p_index;
    this.a = p_addItem;
    this.s = p_setItem;
    this.n = p_addNotification;
    this.deserialise = p_deserialise;
    this.serialise = p_serialise;
    this.clientAdd = p_addItem;
    this.clientSet = p_setItem;
    this.clientSetQty = p_setQty;
    this.clientDelete = p_deleteItem;
    this.clientEmpty = p_deleteAll;
    this.loadFromDB = p_loadFromDB;
    this.addItemDB = p_addItemDB;
    this.deleteItemDB = p_deleteItemDB;
    this.emptyDB = p_emptyDB;
    this.pendingUpdate = p_pendingUpdate;
    this.pendingDelete = p_pendingDelete;
    this.loadCookie = p_loadfromCookie;
    this.saveToCookie = p_saveToCookie;
    this.paint = p_paint;
    this.postBasket = p_postBasket;
    this.paintitem = p_paintitem;
    this.paintNotifications = p_paintNotifications;
    this.paintNotification = p_paintNotification;
    this.painted = p_painted;
    this.checkout = p_checkout;
    this.secureCheckout = p_secureCheckout;
    this.cancelCheckout = p_cancelCheckout;
    this.formatCurrency = formatCurrency;
    this.setMessage = p_setMessage;
    this.setDetails = p_setDetails;
    this.setDetailMinOrder = p_setDetailMinOrder;
    this.setMinOrderVal = p_setMinOrderVal;
    this.setMinOrderReached = p_setMinOrderReached;
    this.checkItem = p_checkItem;
    this.status = p_status;
    this.checkDel = p_checkDel;
    this.GetMinTick = p_getMinTick;
    this.getElement = p_getElementById;
    this.createElement = p_createElement;
    this.loadOnlineBasket = p_loadOnlineBasket;
    this.VersionParameter = p_VersionParameter;
    this.setErrorMsg = p_setErrorMessage;
    this.getErrorMsg = p_getErrorMessage;
    this.showPopup = p_showPopup;
    this.setBudgetAmount = p_setBudgetAmount;
    this.getBudgetAmount = p_getBudgetAmount;
    this.setOverBudget = p_setOverBudget;
    this.isOverBudget = p_isOverBudget;
    this.endItemCheck = p_endItemCheck;
    //this.addAjax=p_AJAX;
    //Private functions
    //Clientside data functions
    function p_loadOnlineBasket(siteURL) {
        var s = '';
        var bi = this.items();
        for (var i = 0; i < bi.length; i++) {
            s += bi[i].productId + '%7C' + bi[i].qty + '%5E'; // field seperator is | record seperator is ^ encoded
        }
        if (s.length > 2) {
            s = s.substr(0, s.length - 3); //remove closing encoded ^
        }
        top.location.href = ('http://' + siteURL + '/UserAccess/Login.aspx?OfflineBasket=' + s);
    }
    function p_addItem(id, code, desc, qty, price, stock) {	//Called by the Server once the item has succesfully been added serverside
        var i = this.index(id);
        if (i > -1) {
            var tQty = m_arrProd[i].qty;
            var tCode = m_arrProd[i].code;
            var tDesc = m_arrProd[i].description;
            var tPrice = m_arrProd[i].price;
            var tStock = m_arrProd[i].stock;
            m_arrProd[i].qty += qty;
            m_arrProd[i].code = code;
            m_arrProd[i].description = desc;
            m_arrProd[i].price = price;
            m_arrProd[i].stock = stock;
            m_arrProd[i].deleted = 0; 		//new line of code
            m_arrProd[i].modified = new Date().valueOf();
        } else {
            //Else create a new item and add to array
            m_arrProd.unshift(new BasketItem(id, code, desc, price, qty, stock));
            i = 0;
            arraySearch(id, 0, i);
        }
        if (this.offline && !this.isList) {
            this.saveToCookie(1);
            this.paint();
        } else {
            if (!this.BulkWrite) { this.paintitem(i); }
        }

        return i;
    }
    function p_setItem(id, code, desc, qty, price, stock) {
        var i = this.index(id); //Find the Item in the basket
        if (i > -1) {
            var tQty = m_arrProd[i].qty;
            var tCode = m_arrProd[i].code;
            var tDesc = m_arrProd[i].description;
            var tPrice = m_arrProd[i].price;
            var tStock = m_arrProd[i].stock;
            m_arrProd[i].code = code;
            m_arrProd[i].description = desc;
            m_arrProd[i].price = price;
            m_arrProd[i].qty = qty;
            m_arrProd[i].stock = stock;
            m_arrProd[i].deleted = 0; 		//new line of code
            m_arrProd[i].modified = new Date().valueOf();
        } else {
            //Else create a new item and add to array
            m_arrProd.unshift(new BasketItem(id, code, desc, price, qty, stock));
            i = 0;
            arraySearch(id, 0, i);
        }
        if (this.offline && !this.isList) {
            this.saveToCookie(1);
            this.paint();
        } else {
            if (!this.BulkWrite) {
                this.paintitem(i);
            }
        }
        return i;
    }
    function p_setQty(id, qty) {
        var i = this.index(id);
        if (i > -1) {
            var tQty = m_arrProd[i].qty;
            m_arrProd[i].qty = qty;
            if (this.offline && !this.isList) {
                this.saveToCookie(1);
                this.paint();
            } else {
                this.paintitem(i);
            }
        }
        return i;
    }
    function p_addNotification(id, href, tooltip, classname) {
        m_arrNotifications.unshift(new Notification(id, href, tooltip, classname));
    }
    function p_getElementById(id) {
        //return p_basketSet().basket.document.getElementById(id);
        return document.getElementById(id);
    }
    function p_createElement(id) {
        //return p_basketSet().basket.document.createElement(id);
        return document.createElement(id);
    }
    function p_deleteItem(id) {
        m_debugTrace = '';
        var modTime = new Date().valueOf();
        var i = this.index(id);
        m_debugTrace += 'Delete item index ' + i + '.\n';
        if (i > -1) {
            arraySearch(id, 1);
            m_arrProd[i].deleted = 1;
            m_arrProd[i].qty = 0;
            if (this.offline && !this.isList) {
                m_arrProd.splice(i, 1);
                this.saveToCookie(1);
                this.paint();
            } else {
                var itemDiv = this.getElement('DivBskt' + id);
                if (itemDiv != null) {
                    var lineNo = this.lineNo(id);
                    //itemDiv.removeNode(itemDiv); ie only!
                    var theParent = itemDiv.parentNode;
                    theParent.removeChild(itemDiv);
                    //p_basketSet().basket.move(30);
                    if (m_arrSortProd.length > 0) {
                        this.renumberItems(i);
                    } else {
                        this.status('No items in your basket');
                    }
                } else {
                    m_debugTrace += 'Delete item ' + i + ' failed.\n';
                }
            }
        }
        m_debugTrace += 'delete Item took ' + (new Date().valueOf() - modTime) + 'ms.\n';
        if (m_debug) { alert(m_debugTrace); }
        this.paintTotals();

//        if (this.isOverBudget()) {
//            this.showPopup('You have gone over your budget of ' + formatCurrency(this.getBudgetAmount(), false) + ' by ' +
//           formatCurrency(Math.abs(this.getBudgetAmount() - this.TotalVal), false), 'Checkout');
//        }
        return i;
    }

    function p_lineNo(id) {
        var lineNo = this.getElement('Num' + id).innerHTML;
        lineNo = Number(lineNo.substr(0, lineNo.length - 2));
        return lineNo;
    }

    var m_lastRenum = 0;
    function p_renumberItems(startIndex, modTime) {
        if (modTime == null) { modTime = new Date().valueOf(); }
        if (m_lastRenum > modTime) { return; } //update no longer valid as another was requested
        m_lastRenum = modTime;
        if (startIndex == null) { startIndex = 0; }
        var lineNo = this.previousLineNo(startIndex);
        var count = 0;
        for (var idx = startIndex; idx < m_arrProd.length; idx++) {
            count++;
            if (count > 30) {
                setTimeout('top.b.renumberItems(' + idx + ',' + modTime + ')', 300); //stop locking the GUI
                m_debugTrace += 'renumber Items break took ' + (new Date().valueOf() - modTime) + 'ms.\n';
                return;
            }
            if (m_arrProd[idx].deleted == 0) {
                lineNo++;
                try {
                    this.getElement('Num' + m_arrProd[idx].productId).innerHTML = lineNo + '. ';
                } catch (e) {//if item is deleted during update
                    lineNo--;
                }
            }
        }
        m_debugTrace += 'renumber Items took ' + (new Date().valueOf() - modTime) + 'ms.\n';
    }

    function p_deleteAll() {
        m_arrSortProd.length = 0;
        m_arrProd.length = 0;
        this.BulkWrite = 1;
        if (this.offline && !this.isList) {
            this.saveToCookie(1);
        }
        this.paint();
        //p_basketSet().basket.move(9999999);
        this.BulkWrite = 0;
    }


    //    function p_AJAX() {
    //    var   add_Ajax='';
    //
    //    if (version > 2) { add_Ajax='&ajax=1'; }

    //    return add_Ajax;
    //    }

    function p_VersionParameter() {

        if (this.version == null) { this.version = 1; }

        return 'version=' + this.version;
    }

    function p_previousLineNo(idx) {
        try {
            if (idx == null || idx <= 0) {
                lineNo = 0;
            } else {
                var aboveIdx = -1;
                for (i = idx - 1; i >= 0 && aboveIdx == -1; i--) {
                    if (m_arrProd[i].deleted == 0) { aboveIdx = i; }
                }

                if (aboveIdx > -1) {
                    lineNo = this.getElement('Num' + m_arrProd[aboveIdx].productId).innerHTML;
                    lineNo = Number(lineNo.substr(0, lineNo.length - 2));
                } else { lineNo = 0; }
            }
        } catch (e) {
            lineNo = 0;
        }
        return lineNo;
    }
    function p_paintitem(idx, lineNo) {
        var modTime = new Date().valueOf();
        if (this.isList) { return; }
        var i = m_arrProd[idx];
        var pid = i.productId;
        m_debugTrace += 'paint item ' + pid + '.\n';
        if (!lineNo) {
            lineNo = this.previousLineNo(idx) + 1;
        }
        var url;
        var onChange;
        if (this.offline) {
            url = '../ProductDetails/' + pid + '.htm';
            onChange = 'return top.objBasket.clientSetQty(' + pid + ', this.value)';
        } else {
            url = '../Catalog/ProductDetails.aspx?productID=' + pid;
            onChange = 'return top.SetQty(' + pid + ', this.value)';
        }
        this.status('');
        var itemDiv = this.getElement('DivBskt' + pid);
        if (itemDiv != null) {
            this.getElement('Num' + pid).innerHTML = lineNo + '. ';
            if (i.description != '') { this.getElement('desc' + pid).innerHTML = i.description; }
            if (i.code != '') { this.getElement('code' + pid).innerHTML = i.code; }
            this.getElement('Qty' + pid).value = i.qty;
            if (i.qty < 1) { this.getElement('Qty' + pid).style.background = '#ff9999'; } else { this.getElement('Qty' + pid).style.background = '#ffffff'; }
            this.getElement('uPrice' + pid).innerHTML = '<B>@</B>' + formatCurrency(i.price, true);
            //if(i.qty>i.stock && i.stock!=-1){
            //	this.getElement('uPrice' + pid).innerHTML+='&nbsp;<A onmouseup="return top.cSts();" onmousedown="return top.sSts(this);" onmouseover="return top.sSts(this);" title="This item is not in stock! click to view details." onmouseout="return top.cSts();" href="'+url+'" target=InfoFrame><img src="../owner/'+sSkinPath+'/basket/exclamation.gif" ></a>';
            //}
            if (i.qty == 0) {
                this.getElement('tot' + pid).innerHTML = '' + formatCurrency(i.qty * i.price, false);
            } else {
                this.getElement('tot' + pid).innerHTML = '' + formatCurrency(i.qty * i.price, true);
            }
            this.getElement('uNotify' + pid).innerHTML = ''; //expect any notifications to be resent on modification.
        } else {//Sorry about the formatting below. I have tried to minimise string concats as these make a big hit to perf.


            var s = '<div class="basketItem">';
            s += '<div class="line1">'; //background="../owner/'+sSkinPath+'/basket/seperator.gif"
            s += '<span id="Num' + pid + '" class="lineNo">' + lineNo + '. </span>';
            s += '<A id="desc' + pid + '" onmouseup="return top.cSts();" class=ModelName onmousedown="return top.sSts(this);" onmouseover="return top.sSts(this);" title="Click for detailed product information" onmouseout="return top.cSts();" href="' + url + '" target=InfoFrame>' + i.description + '</A>';
            s += '</div><div class="line2">';
            s += '<A id="code' + pid + '" onmouseup="return top.cSts();" class=ModelNumber onmousedown="return top.sSts(this);" onmouseover="return top.sSts(this);" title="Click for detailed product information" onmouseout="return top.cSts();" href="' + url + '" target=InfoFrame>' + i.code + '</A>';
            s += '<div class="basketItemNotifications" id="uNotify' + pid + '"></div>';
            s += '<div class="CancelButton" onmouseover="return top.sSts(this);" title="Remove Item from Basket" onclick="';
            if (this.offline) {
                s += 'top.objBasket.clientDelete(' + pid + ');';
            } else {
                s += 'top.Drop(' + pid + ');';
            }
            s += '" onmouseout="return top.cSts();">';
            s += '</div>';
            s += '</div>';
            s += '<div class="line3"><input id="Qty' + pid + '" name="Qty" type="text" value="' + i.qty + '" maxlength="5" size="3" class="basketQty" onChange="' + onChange + '" style="width:30px';
            if (i.qty < 1) { s += ';background:#ff9999'; }
            s += '" onFocus="this.select();"/>';
            s += '<span class="unitCost" ID="uPrice' + pid + '"><strong>@</strong>' + formatCurrency(i.price, true);
            s += '</span>';
            s += '<span class="totalCost" id="tot' + pid + '">';
            if (i.qty == 0) {
                s += '' + formatCurrency(i.qty * i.price, false);
            } else {
                s += '' + formatCurrency(i.qty * i.price, true);
            }
            s += '</span></div></div>';
            if (this.BulkWrite) {
                return '<div id="DivBskt' + pid + '" class="item">' + s + '</div>';
            } else {
                var start = new Date().valueOf();
                //var basket = this.getElement('List');
                var basket = this.getElement('basketcontent');
                var newItem = this.createElement("div");
                newItem.setAttribute("id", "DivBskt" + pid);
                newItem.setAttribute("class", "item");
                if (!basket.childNodes[0])
                    basket.appendChild(newItem);
                else
                    basket.insertBefore(newItem, basket.childNodes[0]);
                this.getElement("DivBskt" + pid).innerHTML = s;
                m_debugTrace += 'insert new div took ' + (new Date().valueOf() - start) + 'ms.\n';
                this.renumberItems();
            }
        }
        /*var tb=this.getElement('Qty' + pid);
        tb.select();
        tb.focus();
        i.painted=1;*/
        i.modified = '';
        m_debugTrace += 'paint item took ' + (new Date().valueOf() - modTime) + 'ms.\n';
        this.paintTotals();
        this.setMessage(''); //Clear error message;

//        if (this.isOverBudget()) {
//            this.showPopup('You have gone over your budget of ' + formatCurrency(this.getBudgetAmount(), false) + ' by ' +
//           formatCurrency(Math.abs(this.getBudgetAmount() - this.TotalVal), false), 'Checkout');
//        }

        return s;
    }

    function p_setMessage(msg) {
        window.status = msg;
        try {
            this.getElement('basketmsg').innerHTML = msg;
            if (msg == '') {
                this.getElement('basketmsg').style.display = 'none';
            } else {
                this.getElement('basketmsg').style.display = 'block';
            }
        } catch (e) {
        }
    }

    function p_status(msg) {
        var msgDiv = this.getElement('bstatus');
        if (msgDiv == null) {
            // the below errors when adding or removing from basket becuase of 'scrlayer.childNodes[0]'
            // msgDiv = this.createElement("bstatus");
            // msgDiv.setAttribute("id", "bstatus");
            // msgDiv.setAttribute("className", "bstatus");
            // var scrlayer=this.getElement(this.containerId);
            // scrlayer.insertBefore(msgDiv,scrlayer.childNodes[0]);
            // msgDiv=this.getElement('bstatus');
            return;
        }
        msgDiv.innerHTML = msg;
    }

    function p_paintTotals() {
        var bi = m_arrProd;
        var sum = 0;
        var items = 0;
        var idx0 = -1;
        for (var i = 0; i < bi.length; i++) {
            if (bi[i].deleted == 0) {
                if (idx0 == -1) { idx0 = i; }
                sum += (bi[i].qty * bi[i].price);
                items += bi[i].qty;
            }
        }

        this.TotalVal = sum;
        this.setMinOrderReached(this.MinOrderVal, this.TotalVal);
        this.getElement("basketSummaryTotal").innerHTML = formatCurrency(sum, false);
        this.getElement("basketTotal").innerHTML = formatCurrency(sum, false);
        this.getElement("basketquantity").innerHTML = items;
        try {
            basketscroller.move(0);
        } catch (e) { }
    }

    function p_paint() {
        if (this.isList) { return; }
        var s = '<TABLE cellSpacing=0 cellPadding=0 width=100% border=0><TR><TD><span id="ErrorMsg" class="ErrorText"></span></TD></TR></TABLE>';
        //s+='<div id=basketcontent style="border-collapse:collapse;width:100%"></div>';
        if (this.containerId == null) {
            this.containerId = 'scrlayer';
        }
        this.getElement(this.containerId).innerHTML = s;
        var bi = m_arrProd;
        var sum = 0;
        var items = 0;
        if (m_arrSortProd.length == 0) {
            this.status('No items in your basket');
        } else {
            s = '';
            var lineNo = 1;
            var idx0 = -1;
            for (var i = 0; i < bi.length; i++) {
                if (bi[i].deleted == 0) {
                    if (idx0 == -1) {
                        idx0 = i;
                    }
                    s += this.paintitem(i, lineNo);
                    sum += (bi[i].qty * bi[i].price);
                    items += bi[i].qty;
                    lineNo++;
                }
            }
            if (lineNo > 0) { this.renumberItems(0); }
            this.getElement('basketcontent').innerHTML = s;
            this.getElement('Qty' + bi[idx0].productId).select();

        }
        if (this.offline) {
            var f = this.p_basketSet().basketbottom.document.forms[0];
            f.Total.value = formatCurrency(sum, false);
        }
        this.paintTotals();

//        if (this.isOverBudget()) {
//            this.showPopup('You have gone over your budget of ' + formatCurrency(this.getBudgetAmount(), false) + ' by ' +
//               formatCurrency(Math.abs(this.getBudgetAmount() - this.TotalVal), false), 'Checkout');
//        }

    }
    function p_paintNotifications() {
        var arrNot = m_arrNotifications;
        for (var i = 0; i < arrNot.length; i++) {
            this.paintNotification(arrNot[i].id, arrNot[i].href, arrNot[i].tooltip, arrNot[i].classname);
        }
        m_arrNotifications.length = 0;

    }
    function p_paintNotification(id, href, tooltip, classname) {
        //var span = p_basketSet().basket.document.getElement('uNotify'+id);
        var span = this.getElement('uNotify' + id);
        if (span != null && typeof (span) != 'undefined') {
            span.innerHTML += '<A onmousedown="return top.sSts(this);" onmouseover="return top.sSts(this);" onmouseup="return top.cSts();" onmouseout="return top.cSts();" title="' + tooltip + '" href="' + href + '" target=InfoFrame><div class="' + classname + '" ></div></a>';
        }
        //An alert which was used perhaps for testing which displays if the span(actually a div) does not exist
        //else {
           
            //alert(' cannot find span in ' + document.body);
        //}
    }
    function p_pendingUpdate(id, i, modTime) {
        var start = new Date().valueOf();
        if (!i) { i = this.index(id); }
        var itemDiv = this.getElement('DivBskt' + id);
        if (itemDiv != null) {
            this.getElement('uPrice' + id).innerHTML = '';
            this.getElement('tot' + id).innerHTML = 'Calculating...';
        }
        m_arrProd[i].painted = 0;
        if (modTime) { m_arrProd[i].modified = modTime; }
        m_debugTrace += 'pending update took ' + (new Date().valueOf() - start) + 'ms.\n';
        return i;
    }
    function p_pendingDelete(id, modTime) {
        var i = this.index(id);
        if (i > -1) {
            var itemDiv = this.getElement('DivBskt' + id);
            if (itemDiv != null) {
                this.getElement('uPrice' + id).innerHTML = '';
                this.getElement('tot' + id).innerHTML = 'Deleting...';
            }
            m_arrProd[i].painted = 0;
            if (modTime) { m_arrProd[i].modified = modTime; }
            return i;
        }
    }
    function p_setDetails(freight, FreightTitle) {
        try {
            f = document.getElementById('basketFreight');
            f.title = FreightTitle;
            if (freight == 0) {
                f.className = 'FreeFreight';
            } else {
                f.className = 'ChargeFreight';
            }
        } catch (e) {
        }
    }

    //	function p_setDetailMinOrder(minOrderValue,minOrderTitle){
    //			try{
    //			    f=document.getElementById('basketMinOrderValue');
    //			    f.title=minOrderTitle;
    ////				if(minOrderValue==0){
    ////				    f.className='NoMinOrderValue';
    ////			    }else{
    ////				    f.className='MinOrderValue';
    ////			    }
    //			    this.MinOrderVal=minOrderValue;
    //			    if (minOrderValue>0) {
    //				if(this.TotalVal >= minOrderValue){
    //				    f.className='MinOrderValueReached';
    //				     } else {
    //				     f.className='MinOrderValue';
    //				     }
    //			        } else {
    //				     f.className='NoMinOrderValue';
    //				     }
    //			}catch(e){
    //			}
    //	}


    function p_setDetailMinOrder(minOrderTitle) {
        try {
            f = document.getElementById('basketMinOrderValue');
            f.title = minOrderTitle;
        } catch (e) {
        }
    }
    //basketMinOrderValue
    function p_setMinOrderReached(minOrderValue, totalvalue) {
        try {
            f = document.getElementById('basketMinOrderValue');
            if (minOrderValue > 0) {
                if (totalvalue >= minOrderValue) {
                    f.className = 'MinOrderValueReached';
                    f.title = '';
                } else {
                    f.className = 'MinOrderValue';
                }
            } else {
                f.className = 'NoMinOrderValue';
                f.title = '';
            }
        } catch (e) {
        }
    }



    function p_setMinOrderVal(minOrderValue) {
        try {
            this.MinOrderVal = minOrderValue;
        } catch (e) {
        }
        //alert(' Your minOrderValue ' +  formatCurrency(minOrderValue,false) + ' and Min Order Value (' +  formatCurrency(this.MinOrderVal,false) + ')!');

    }

    function p_painted(id, painted) {
        var i = this.index(id);
        if (i > -1) {
            m_arrProd[i].painted = painted;
            return i;
        }
    }

    function p_index(id) {
        //return arraySearch(id)
        for (var i = 0; i < m_arrProd.length; i++) {
            if (m_arrProd[i].productId == id) {
                return i;
            }
        }
        return -1;
    }
    function p_checkout() {
        if (this.isList) {
            alert('You cannot Check Out a List!\nAdd the list to the basket first.');
            return;
        }
        if (this.items().length == 0) {
            alert('You cannot proceed to the Check Out with an empty Basket!');
            return;
        }

        if (this.MinOrderVal > 0) {
            if (this.TotalVal < this.MinOrderVal) {
                alert('You cannot proceed to the Check Out, Your total ' + formatCurrency(this.TotalVal, false) + ' is less than Min Order Value (' + formatCurrency(this.MinOrderVal, false) + ')!');
                return;
            }
        }

        if (this.isOverBudget()) {
            //            alert('You have gone over your budget of ' + formatCurrency(this.getBudgetAmount(), false) + ' by ' +
            //                   formatCurrency(Math.abs(this.getBudgetAmount() - this.TotalVal), false));
            this.showPopup('You have gone over your budget of ' + formatCurrency(this.getBudgetAmount(), false) + ' by ' +
                   formatCurrency(Math.abs(this.getBudgetAmount() - this.TotalVal), false), 'Checkout');
            return;
        }

        if (this.checkedOut == 1) {
            this.cancelCheckout();
            return;
        }
        this.checkedOut = 1;
        if (document.getElementById('BasketDesc')) {
            document.getElementById('BasketDesc').style.display = 'none';
        }
        this.status('Your basket contents are at the Check Out!');
        this.getElement('basketcontent').innerHTML = '';
        this.getElement('basketTotal').innerText = '';
        this.orderRef = this.getElement('orderRef').value;
        this.getElement('orderRef').value = '';
        var url;
        if (this.offline) {
            url = top.location.pathname;
            if (top.location.pathname.substring(0, 1) == '/') {
                url = top.location.pathname.substring(1);
            }
            url = url.substring(0, url.indexOf('index.htm'));
            url += 'basket/CheckOut.htm?orderRef=' + this.orderRef;
        } else {
            url = '../basket/CheckOut3.aspx?orderRef=' + this.orderRef; // ------- Modified Here
        }

        var Mainurl = top.InfoFrame.location.pathname.toLowerCase();

        if (Mainurl.indexOf('/basket/checkout') > -1) {
            top.InfoFrame.document.body.onunload = null;
        }
        url = unescape(url);
        top.InfoFrame.location.replace(url);
    }

    function p_secureCheckout() {
        if (this.isList) {
            alert('You cannot Check Out a List!\nAdd the list to the basket first.');
            return;
        }
        if (this.items().length == 0) {
            alert('You cannot proceed to the Check Out with an empty Basket!');
            return;
        }

        if (this.MinOrderVal > 0) {
            if (this.TotalVal < this.MinOrderVal) {
                alert('You cannot proceed to the Check Out, Your total ' + formatCurrency(this.TotalVal, false) + ' is less than Min Order Value (' + formatCurrency(this.MinOrderVal, false) + ')!');
                return;
            }
        }

        if (this.isOverBudget()) {
            alert('You have gone over your budget of ' + formatCurrency(this.getBudgetAmount(), false) + ' by ' +
                   formatCurrency(Math.abs(this.getBudgetAmount() - this.TotalVal), false));
            return;
        }

        if (this.checkedOut == 1) {
            this.cancelCheckout();
            return;
        }
        this.checkedOut = 1;
        if (document.getElementById('BasketDesc')) {
            document.getElementById('BasketDesc').style.display = 'none';
        }

        this.status('Your basket contents are at the Check Out!');
        this.getElement('basketcontent').innerHTML = '';

        document.getElementById('basketTotal').value = '';
        this.orderRef = document.getElementById('orderRef').value;
        document.getElementById('orderRef').value = '';
        var url;
        if (this.offline) {
            url = top.location.pathname;
            url = url.substring(0, url.indexOf('index.htm'));
            url += 'basket/CheckOut.htm?orderRef=' + this.orderRef;
        } else {
            url = 'https://' + top.location.host + '/basket/checkout3.aspx?orderRef=' + this.orderRef;
        }

        var Mainurl = top.InfoFrame.location.pathname.toLowerCase();

        if (Mainurl.indexOf('/basket/checkout') > -1) {
            top.InfoFrame.document.body.onunload = null;
        }

        top.InfoFrame.location.replace(url);

        if (top.intervalID != null) {
            clearInterval(top.intervalID);
        }

        top.intervalID = setInterval("checkCheckoutFinished()", pollInterval);
    }

    function p_cancelCheckout(noredirect) {
        this.checkedOut = 0;
        var r = top.frames['InfoFrame'];
        var loc = r.location.pathname.substr(r.location.pathname.length - 21, 21);
        loc = loc.toLowerCase();
        if (loc.indexOf('basket/checkout') > -1) {
            var d = r.document;
            try {
                d.getElementById('LblHeader').innerText = 'Check Out Cancelled!';
                d.getElementById('Message').innerText = 'Your Order was cancelled and items were placed back in your basket.';
                r.ignoreUnload = true;
                d.getElementById('pnlDetails').innerHTML = '';
            } catch (e) { }
        } else if (!noredirect) {
            if (loc.indexOf('/basket/checkout') > -1) {
                r.location.replace('../basket/CheckOutCancel.aspx');
            }
        }
        var total = 0;
        //var bi=top.objBasket.items();
        var bi = this.items();
        this.checkedOut = 0;
        if (!BasketVisible) {
            if (top.frames['toolbar'].document.getElementById('BasketDesc')) {
                top.frames['toolbar'].document.getElementById('BasketDesc').style.display = '';
            }
        }
        for (var i = 0; i < bi.length; i++) {
            total += bi[i].qty * bi[i].price;
        }
        //var f=p_basketSet().basketbottom.document.forms[0];
        //f.Total.value=formatCurrency(total,false);
        //f.OrderRef.value=this.orderRef;
        this.getElement("basketTotal").value = formatCurrency(total, false);
        this.TotalVal = total;
        this.setMinOrderReached(this.MinOrderVal, this.TotalVal);
        this.getElement("orderRef").value = this.orderRef;
        this.BulkWrite = 1;
        this.paint();
        this.BulkWrite = 0;
    }
    function formatCurrency(num, showPOA) {
        //alert(num);
        num = num.toString().replace(/\$|\,/g, '');
        if (isNaN(num)) {
            if (showPOA == true)
                return 'POA';
            else
                return '$0.00';
        } else {
            if (num <= 0 && showPOA == true) {
                return 'POA';
            }
            sign = (num == (num = Math.abs(num)));
            num = Math.floor(num * 100 + 0.50000000001);
            cents = num % 100;
            num = Math.floor(num / 100).toString();
            if (cents < 10) {
                cents = "0" + cents;
            }
            for (var i = 0; i < Math.floor((num.length - (1 + i)) / 3); i++) {
                num = num.substring(0, num.length - (4 * i + 3)) + ',' + num.substring(num.length - (4 * i + 3));
            }
            return (((sign) ? '' : '-') + '$' + num + '.' + cents);
        }
    }
    //serialisation functions
    function p_deserialise(str) {
        var props = str.split('\n');
        var name;
        var type;
        var value;
        for (var i = 0; i < props.length; i++) {
            var keys = props[i].split('=');
            if (keys.length > 2) {
                name = unescape(keys[0]);
                type = keys[1];
                value = unescape(keys[2]);
                switch (type) {
                    case 's':
                        eval('this.' + name + '=\'' + value + '\';');
                        break;
                    default:
                        if (name == 'BasketItem') {
                            //split the Basket items to an array
                            var BIs = value.split(';');
                            //deserialise each item to the basket array
                            for (var j = 0; j < BIs.length; j++) {
                                m_arrProd[j] = deserialise(unescape(BIs[j]), new BasketItem);
                                arraySearch(j, 0, j);
                            }
                        } else {
                            eval('this.' + name + '=' + value + ';');
                        }
                }
            }
        }
    }
    function p_serialise() {
        var ret = '';
        var newline = false;
        for (var prop in this) {
            if (typeof (this[prop]) != 'undefined' && this[prop] != null) {
                switch (typeof (this[prop])) {
                    case 'function':
                    case 'object':
                        break;
                    case 'string':
                        if (newline) ret += '\n';
                        ret += escape(prop) + '=';
                        ret += 's='; //String type
                        ret += escape(this[prop]);
                        newline = true;
                        break;
                    default:
                        if (newline) {
                            ret += '\n';
                        }
                        ret += escape(prop) + '=';
                        ret += 'v='; //Value type
                        ret += escape(this[prop]);
                        newline = true;
                }
            }
        }
        //serialise the basket array.
        if (newline) {
            ret += '\n';
        }
        ret += 'BasketItem=a=';
        var BIs = '';
        for (var i = 0; i < m_arrProd.length; i++) {
            if (i > 0) {
                BIs += ';';
            }
            BIs += escape(serialise(m_arrProd[i]));
        }
        ret += escape(BIs);
        return ret;
    }
    function p_loadfromCookie(basketname) {
        var bn = 'B';
        //if(arguments.length==1){bn=basketname}
        var c = Get_Cookie(bn);
        if (c != null) {
            this.deserialise(c);
        }
    }
    function p_saveToCookie(autoSave) {
        var s = this.serialise();
        var len = escape(s).length;
        if (len < 4088) {
            Set_Cookie('B', s, addDay(new Date(), 62));
            //check that the cookie was saved successfully.
            if (document.cookie.length == 0) {
                alert(len + ' apparently is too long for the basket!!\nThe basket was not saved. Please remove some line items.');
                return false;
            }
            return true;
        } else {
            if (autoSave == 1) {
                alert('Your basket has reached its saved offline limit. While you may add further items to your basket, no further items will be added to your saved offline basket.');
            } else {
                alert('Your basket cant be saved as it is too large. The data length is currently ' + len + ' and the maximum length allowed is 4088.\n\nPlease remove some items from your basket.');
            }
            return false;
        }
    }

    //ServerSide data functions (Calls to serverside functions)
    //Called by the client. Calls the serverside Add which on successfull return will call the client Add method.
    function p_loadFromDB(id, qty) {
        this.setMessage('Loading basket...');
        this.postBasket('Load');
    }

    //Called by the client. Calls the serverside Add which on successfull return will call the client Add method.
    function p_addItemDB(id, qty, code, desc) {
        m_debugTrace = '';
        var modTime = new Date().valueOf();
        var i = this.index(id);
        m_debugTrace += 'index lookup took ' + (new Date().valueOf() - modTime) + 'ms.\n';

        if (i > -1) {
            if (m_arrProd[i].qty > 0 && id != m_lastUpdatedID) {
                if (!confirm("This item already exists in your basket! Do you still wish to add it?")) { return; }
            }
        }
        this.setMessage('Updating basket...');
        m_lastUpdatedID = id;
        i = this.clientAdd(id, code, desc, qty, 0, 1);

        this.pendingUpdate(id, i, modTime);
        setTimeout('top.b.checkItem(' + id + ',' + m_arrProd[i].qty + ',0,' + modTime + ')', m_reCheckTicks);
        this.postBasket('Update', '../', '&id=' + id + '&qty=' + m_arrProd[i].qty + '&tick=' + modTime, modTime);
        m_debugTrace += 'client item add took ' + (new Date().valueOf() - modTime) + 'ms. ';
        if (m_debug) { alert(m_debugTrace); }
    }

    //Called by the client. Calls the serverside Delete which on successfull return will call the client Delete method.
    function p_deleteItemDB(id) {
        m_debugTrace = '';
        var modTime = new Date().valueOf();
        this.pendingDelete(id, modTime);
        this.setMessage('Updating basket...');
        setTimeout('top.b.checkDel(' + id + ',0)', m_reCheckTicks);
        this.postBasket('Delete', '../', '&id=' + id, modTime);
        m_debugTrace += 'delete Item took ' + (new Date().valueOf() - modTime) + 'ms.\n';
        if (m_debug) {
            alert(m_debugTrace);
        }
    }
    function p_emptyDB() {
        this.cancelCheckout();
        this.setMessage('Emptying basket...');
        this.postBasket('Empty', '../');
    }
    function p_getMinTick() {
        var min = 8640000000000000; //The Max tick value.
        for (var i = 0; i < m_arrProd.length; i++) {
            if (m_arrProd[i].modified != '') {
                min = Math.min(min, m_arrProd[i].modified);
            }
        }
        return min;
    }
    function p_checkItem(id, qty, retries, modTime) {

        if (this.m_endItemCheck == true) {
            this.m_endItemCheck = false;

            return;
        }

        var now = new Date().valueOf();
        if (m_lastModTime < now - (retries * 1000)) {
            var i = this.index(id);
            if (i > -1) {
                if (m_arrProd[i].modified != '' && modTime >= m_arrProd[i].modified) {
                    if (retries < 5) {
                        var minTick = this.GetMinTick();
                        setTimeout('top.b.checkItem(' + id + ',' + qty + ',' + (retries + 1) + ',' + modTime + ')', m_reCheckTicks);
                        this.postBasket('get', '../', '&tick=' + minTick, modTime);
                    } else {
                        if (retries == 5) {
                            setTimeout('top.b.checkItem(' + id + ',' + qty + ',' + (retries + 1) + ',' + modTime + ')', m_reCheckTicks);
                            this.postBasket('Update', '../', '&id=' + id + '&qty=' + qty + '&tick=' + modTime, modTime);
                        } else {
                            if (confirm('Failed to add item ' + m_arrProd[i].description + ' (' + m_arrProd[i].code + ')! Try again?')) {
                                setTimeout('top.b.checkItem(' + id + ',' + qty + ',0,' + modTime + ')', m_reCheckTicks);
                                this.postBasket('Update', '../', '&id=' + id + '&qty=' + qty + '&tick=' + modTime, modTime);
                            } else { this.clientDelete(id); }
                        }
                    }
                }
            }
        } else {
            setTimeout('top.b.checkItem(' + id + ',' + qty + ',' + retries + ',' + modTime + ')', m_reCheckTicks);
        }
    }
    function p_checkDel(id, retries) {

        //        if (this.isOverBudget()) {
        //            //this.clientDelete(id);
        //            //this.showPopup();
        //            alert('You are over your budget!');
        //            this.m_errorMessage = '';
        //            return;
        //        }

        var now = new Date().valueOf();
        if (m_lastModTime < now - (retries * 1000)) {
            var i = this.index(id);
            if (i > -1) {
                if (m_arrProd[i].deleted == 0) {
                    if (retries < 5) {
                        setTimeout('top.b.checkDel(' + id + ',' + (retries + 1) + ')', m_reCheckTicks);
                        this.postBasket('Delete', '', '&id=' + id);
                    } else {
                        if (confirm('Failed to delete ' + m_arrProd[i].description + ' (' + m_arrProd[i].code + ')! Try again?')) {
                            this.deleteItemDB(Id);
                        } else { this.paintitem(i); }
                    }
                }
            }
        } else {
            setTimeout('top.b.checkDel(' + id + ',' + retries + ')', m_reCheckTicks);
        }
    }
    function p_postBasket(action, prefix, params, modTime) {
        if (!modTime) { modTime = new Date().valueOf(); }
        if (!params) { params = ''; }
        if (!prefix) { prefix = ''; }
        m_lastModTime = new Date().valueOf();
        //top.control.location.replace(prefix + 'basket/action.aspx?action=' + action + params);
        var url = prefix + 'basket/action.aspx?' + this.VersionParameter() + '&action=' + action + params;
        top.neotekscript(url);

        //ajaxget('basket.xml');
    }

    function sortItem(value, index) {
        this.value = value;
        this.index = index;
    }
    function arraySearch(vValue, RemoveCount, index) {
        var iIdx = -1;
        var idx = -1;
        //create reverse order index
        if (index != null) {
            index = m_arrProd.length;
        }
        if (m_arrSortProd.length == 0) {
            if (index != null) {
                m_arrSortProd.splice(0, 0, new sortItem(vValue, index));
                return 0;
            }
            return -1;
        }
        if (RemoveCount == null) { RemoveCount = 0; }

        var iStartIndex, iEndIndex, iMiddleIndex;

        /*			var t='';
        for(var i=0;i<m_arrSortProd.length;i++){
        t+=m_arrSortProd[i].value + '\n';
        }
        alert(vValue + '\n' + t);//'Item '+ m_arrSortProd.length + ' added at ' + iIdx + ' value ' + vValue + ' after ' + m_arrSortProd[iStartIndex].value  + ' before ' + m_arrSortProd[iEndIndex].value);
        */
        iStartIndex = 0;
        iMiddleIndex = -1;
        iEndIndex = m_arrSortProd.length - 1;

        while (iIdx == -1) {
            iMiddleIndex = iStartIndex + Math.ceil((iEndIndex - iStartIndex) / 2);

            switch (vValue) {
                case m_arrSortProd[iStartIndex].value: idx = iStartIndex;
                case m_arrSortProd[iMiddleIndex].value: idx = iMiddleIndex;
                case m_arrSortProd[iEndIndex].value: idx = iEndIndex;
            }

            if (idx > -1) {
                if (RemoveCount > 0) {
                    m_arrSortProd.splice(idx, RemoveCount);
                    return -1;
                }
                //return reverse order index
                return m_arrProd.length - m_arrSortProd[idx].index;
            }

            if (iStartIndex == iMiddleIndex) {
                iIdx = iStartIndex;
            } else if (iEndIndex == iMiddleIndex) {
                iIdx = iEndIndex;
            } else if (vValue > m_arrSortProd[iMiddleIndex].value) {
                iStartIndex = iMiddleIndex + 1;
            } else if (vValue < m_arrSortProd[iMiddleIndex].value) {
                iEndIndex = iMiddleIndex - 1;
            }

        }
        //Insert new record if not found
        if (iIdx > -1 && index != null) {
            if (vValue < m_arrSortProd[iIdx].value) { iIdx--; }
            if (iIdx < 0) { iIdx = 0; }
            if (vValue > m_arrSortProd[iIdx].value) { iIdx++; }
            m_arrSortProd.splice(iIdx, 0, new sortItem(vValue, index));
        }
        return -1;
    }
}
function BasketItem(id, code, desc, price, qty, stock) {
    this.productId = id;
    this.code = code;
    this.description = desc;
    this.price = price;
    this.qty = qty;
    this.stock = stock;
    this.painted = 0;
    this.deleted = 0;
    this.modified = ''; //use this to hold ticks of last modification.
}
function Notification(id, href, tooltip, classname) {
    this.id = id;
    this.href = href;
    this.tooltip = tooltip;
    this.classname = classname;
}

function deserialise(str, obj) {
    var props = str.split('\n');
    var name;
    var type;
    var value;
    for (var i = 0; i < props.length; i++) {
        var keys = props[i].split('=');
        if (keys.length > 2) {
            name = unescape(keys[0]);
            type = keys[1];
            value = unescape(keys[2]);
            switch (type) {
                case 's':
                    eval('obj.' + name + '=\'' + strEsc(value) + '\';');
                    break;
                default:
                    eval('obj.' + name + '=' + value + ';');
            }
        }
    }
    return obj;
}
function serialise(obj) {
    var ret = '';
    var newline = false;
    for (var prop in obj) {
        if (typeof (obj[prop]) != 'undefined' && obj[prop] != null) {
            if (newline) { ret += '\n'; }
            ret += escape(prop) + '=';
            switch (typeof (obj[prop])) {
                case 'string':
                    ret += 's='; //String type
                    break;
                case 'object':
                    ret += 'o='; //Object type
                    break;
                default:
                    ret += 'v='; //Value type
            }
            ret += escape(obj[prop]);
        }
        newline = true;
    }
    return ret;
}
function strEsc(str) {
    /*
    var re1 = /\\/;
    var re2 = /\'/;
    var ret = str.replace(re1, '\\\\');
    return ret.replace(re2, '\\\'');
    */
    return str;
}

function p_setErrorMessage(message) {
    this.m_errorMessage = message;
}

function p_getErrorMessage() {
    return this.m_errorMessage;
}

function p_showPopup(theMessage, title) {
    top.NeotekPopup.Close();

    var settings = {
        URL: null,
        ShowClose: true,
        DoFade: true,
        Title: title,
        Message: theMessage,
        CloseOnLoseFocus: false,
        BackgroundColor: 'White',
        Rounded: false,
        Height: 50,
        Width: 300
    };

    top.NeotekPopup.Show(settings);
    return;
}

function p_setBudgetAmount(theAmount) {
    this.m_budgetAmount = theAmount;
}

function p_getBudgetAmount() {
    return this.m_budgetAmount;
}

function p_setOverBudget(isOver) {
    this.m_overBudget = isOver
}

function p_isOverBudget() {
    if (this.m_budgetAmount < 0) {
        return false;
    }

    if (this.TotalVal > this.m_budgetAmount) {
        return true;
    }
    else {
        return false;
    }
}

function p_endItemCheck(endCheck) {
    this.m_endItemCheck = endCheck;
}



// Types:       element, popup, script
// Properties:  ProductId, Type, Value, Class, Extended

var BasketNotify = {
    Set: function(setting) {
        switch (setting.Type) {
            case "element":
                b.n(setting.ProductId, setting.Extended.href, setting.Extended.title, setting.Class);
                break;
            case "popup":
                break;
            case "script":
                try {
                    eval(setting.Value);
                } catch (ex) { /* Do Nothing */ }
                break;
        }
    }
};



