﻿// Ensure root namespaces are existing
Type.registerNamespace('ise.Products');

ise.Products.ProductController = {
    
    initialize : function() {
        this.products = new Array();
        this.observers = new Array();
    },
    
    registerProduct : function(product) {
        if(product) {
            this.products[product.getId()] = product;
            this.notifyObservers(product);
            
            return product;
        }
    },
    
    getProduct : function(id) {
        return this.products[id];
    },
    
    addObserver : function(observer) {
        if(observer) {
            this.observers[this.observers.length] = observer;
        }
    },
    
    notifyObservers : function(product) {
        for(var ctr=0; ctr< this.observers.length; ctr++) {
            this.observers[ctr].notify(product);
        }
    }
}

ise.Products.ProductController.initialize();

ise.Products.ImagePreLoader = function(id) {
    this.id = id;
    this.images = new Array();
    this.preLoadingCompleteEventHandlers = new Array();
}
ise.Products.ImagePreLoader.registerClass('ise.Products.ImagePreLoader');
ise.Products.ImagePreLoader.prototype = {

    add : function(img) {
        this.images.push(img);
    },
    
    addPreloadingCompleteEventHandler : function(handler) {
        this.preLoadingCompleteEventHandlers.push(handler);
    },
    
    process : function() {
        //var lambda = this.doProcess.bind(this);
        var lambda = Function.createDelegate(this, this.doProcess);
        this.doProcess(lambda);
    },
    
    doProcess : function(lambda) {
        if(this.images.length > 0) {
            var recurse = function(){if(lambda){lambda(lambda)};}
            var current = this.images.pop();
            if(current && current.src) {
                var req = new Ajax.Request(current.src,
                    {
                        method : 'get',
                        onSuccess : function(transport) {
                            current.exists = (200 == transport.status);
                            recurse();
                        },
                        onFailure : function(transport) {
                            current.exists = false;
                            recurse();
                        }
                    }
                );
            }
            else {
                recurse();
            }
        }
        else {
            this.onPreloadingComplete();
        }
        
    },
    
    onPreloadingComplete : function() {
        for(var ctr=0;ctr<this.preLoadingCompleteEventHandlers.length; ctr++) {
            var handler = this.preLoadingCompleteEventHandlers[ctr];
            handler(this);
        }
    }

}


ise.Products.Product = function(id, itemCode, itemType) {
    this.id = id;
    this.itemCode = itemCode;
    this.itemType = itemType;
    
    this.currentUnitMeasure = null;
    this.price = null;
    this.imageData = null;
    
    this.priceChangedEventHandlers = new Array();
    this.attributeChangedEventHandlers = new Array();
    this.unitMeasures = new Array();
    this.unitMeasureChangedEventHandlers = new Array();
    
    this.restrictedQuantities = null;
    this.minQuantity = 0;
    this.hidePriceUntilCart = false;
    
    this.imagesLoadedEventHandlers = new Array();
    
    this.hasVat = false;
    this.vatSetting = ise.Constants.VAT_SETTING_EXCLUSIVE;
    
    this.showBuyButton = true;
}
ise.Products.Product.registerClass('ise.Products.Product');
ise.Products.Product.prototype = {

    setUnitMeasureIntrinsics : function(unitMeasures) {
        this.unitMeasures = unitMeasures;
        
        if(this.unitMeasures.length>0) {
            this.setUnitMeasure(this.unitMeasures[0].code);
        }
        
        this.onAttributeChanged();
    },
    
    getUnitMeasures : function() {
        return this.unitMeasures;
    },
    
    getId : function() {
        return this.id;
    },
    
    getItemCode : function() {
        return this.itemCode;
    },
    
    getItemType : function() {
        return this.itemType;
    },
    
    getUnitMeasure : function() {
        return this.currentUnitMeasure.code;
    },
    
    getUnitMeasureQuantity : function() {
        return this.currentUnitMeasure.unitMeasureQuantity;
    },
    
    getPrice : function() {
        return this.currentUnitMeasure.price;
    },
    
    getPriceFormatted : function() {
        return this.currentUnitMeasure.priceFormatted;
    },
    
    getPromotionalPrice : function() {
        return this.currentUnitMeasure.promotionalPrice;
    },
    
    getPromotionalPriceFormatted : function() {
        return this.currentUnitMeasure.promotionalPriceFormatted;
    },
    
    hasPromotionalPrice : function() {
        return this.currentUnitMeasure.hasPromotionalPrice;
    },
    
    getHasVat : function() {
        return this.hasVat;
    },
    
    setHasVat : function(hasVat) {
        this.hasVat = hasVat;
    },
    
    getVatSetting : function() {
        return this.vatSetting;
    },
    
    setVatSetting : function(vatSetting) {
        this.vatSetting = vatSetting;
    },
    
    getVat : function() {
        return this.currentUnitMeasure.tax;
    },
    
    getFreeStock : function() {
        return this.currentUnitMeasure.freeStock;
    },
    
    hasAvailableStock : function() {
        return this.getFreeStock() > 0;
    },
    
    hasRestrictedQuantities : function() {
        return null != this.restrictedQuantities && this.restrictedQuantities.length > 0;
    },
    
    getRestrictedQuantities : function() {
        return this.restrictedQuantities;
    },
    
    setRestrictedQuantities : function(quantities) {
        this.restrictedQuantities = quantities;
    },
    
    setMinimumOrderQuantity : function(qty) {
        this.minQuantity = qty;
    },
    
    getMinimumOrderQuantity : function() {
        return this.minQuantity;
    },
    
    setHidePriceUntilCart : function(hide) {
        this.hidePriceUntilCart = hide;
    },
    
    getHidePriceUntilCart : function() {
        return this.hidePriceUntilCart;
    },
    
    setShowBuyButton : function(show) {
        this.showBuyButton = show;
    },
    
    getShowBuyButton : function() {
        return this.showBuyButton;
    },
    
    setUnitMeasure : function(unitMeasure) {
        for(var ctr=0; ctr< this.unitMeasures.length; ctr++) {
            var currentUnitMeasure =  this.unitMeasures[ctr];
            if(currentUnitMeasure.code == unitMeasure) {
                this._setCurrentUnitMeasure(currentUnitMeasure);
            }
        }
        
        this.onUnitMeasureChanged();
    },
    
    addUnitMeasureChangedEventHandler : function(handler) {
        this.unitMeasureChangedEventHandlers[this.unitMeasureChangedEventHandlers.length] = handler;
    },
    
    onUnitMeasureChanged : function() {
        for(var ctr=0;ctr< this.unitMeasureChangedEventHandlers.length; ctr++) {
            var handler = this.unitMeasureChangedEventHandlers[ctr];
            handler(this);
        }
    },
    
    _setCurrentUnitMeasure : function(unitMeasure) {
        this.currentUnitMeasure = unitMeasure;
        
        this.onPriceChanged();
    },    
    addPriceChangedEventHandler : function(handler) {
        this.priceChangedEventHandlers[this.priceChangedEventHandlers.length] = handler;
    },
    
    addAttributeChangedEventHandler : function(handler) {
        this.attributeChangedEventHandlers[this.attributeChangedEventHandlers.length] = handler;
    },
    
    onPriceChanged : function() {
        for(var ctr=0;ctr< this.priceChangedEventHandlers.length; ctr++) {
            var handler = this.priceChangedEventHandlers[ctr];
            handler(this);
        }
    },
    
    onAttributeChanged : function() {
        for(var ctr=0;ctr< this.attributeChangedEventHandlers.length; ctr++) {
            var handler = this.attributeChangedEventHandlers[ctr];
            handler(this);
        }
    },
    
    getImageData : function() {
        return this.imageData;
    },
    
    
    areImagesLoaded : function() {
        return this.imagesAreLoaded;
    },
    
    
    addImagesLoadedEventHandler : function(handler) {
        this.imagesLoadedEventHandlers.push(handler);
    },
    
    onImagesLoaded : function() {
        for(var ctr=0; ctr<this.imagesLoadedEventHandlers.length; ctr++) {
            var handler = this.imagesLoadedEventHandlers[ctr];
            handler(this);
        }
    },
    
    setImageData : function(data) {
        this.imageData = data;
        
        if(data.isRemote) {
            this.imagesAreLoaded = false;
            this.preLoadImages();
            
        }
        else {
            this.imagesAreLoaded = true;
        }
    },
    
    preLoadImages : function() {
        if(this.imageData) {
            var loader = new ise.Products.ImagePreLoader(this.id);
            loader.add(this.imageData.medium);
            loader.add(this.imageData.large);
            loader.add(this.imageData.swatch);
            for(var ctr=0; ctr<10; ctr++) {
                loader.add(this.imageData.mediumImages[ctr]);
                loader.add(this.imageData.largeImages[ctr]);
                loader.add(this.imageData.microImages[ctr]);
            }
            
            //loader.addPreloadingCompleteEventHandler(this.onPreloadingImagesCompleteEventHandler.bind(this));
            var handler = Function.createDelegate(this, this.onPreloadingImagesCompleteEventHandler);
            loader.addPreloadingCompleteEventHandler(handler);
            loader.process();
        }
    },
    
    onPreloadingImagesCompleteEventHandler : function() {
        this.imagesAreLoaded = true;
        this.onImagesLoaded();
    },
    
    getMediumImage : function(index) {
        if(arguments.length == 0) {
            return this.imageData.medium;
        }
        else {
            return this.imageData.mediumImages[index];
        }
    },
    
    getLargeImage : function(index) {
        if(arguments.length == 0) {
            return this.imageData.large;
        }
        else {
            return this.imageData.largeImages[index];
        }
    },
    
    getMicroImage : function(index) {
        return this.imageData.microImages[index];
    },
    
    serializeToForm : function() {
        
    },
    
    toString : function() {
        return 'ise.Products.Product';
    }

}



ise.Products.MatrixAttribute = function(code, value){
    this.code = code;
    this.value = value;    
}
ise.Products.MatrixAttribute.registerClass('ise.Products.MatrixAttribute');
ise.Products.MatrixAttribute.prototype = {
    
    matches : function(other) {
        return this.code == other.code && this.value == other.value;
    }
}

ise.Products.MatrixProduct = function(id, itemCode, itemType) {
    ise.Products.MatrixProduct.initializeBase(this, [id, itemCode, itemType]);
    
    this.attributes = new Array();
}
ise.Products.MatrixProduct.registerClass('ise.Products.MatrixProduct', ise.Products.Product);
ise.Products.MatrixProduct.prototype = {

    setAttributes : function(attributes) {
        //this.attributes = attributes;
        //this.attributes = $H(attributes); <- NOT YET SUPPORTED!!!        
        this.extractAttributes(attributes);
    },
    
    extractAttributes : function(attributesAsArray) {
        for(var ctr=0; ctr<attributesAsArray.length; ctr++) {
            var definedAttribute = attributesAsArray[ctr];
            
            var attribute = new ise.Products.MatrixAttribute(definedAttribute.Code, definedAttribute.Value);
            this.attributes.push(attribute);
        }  
    },
    
    getAttributes : function() {
        return this.attributes;
    },
    
    hasMatch : function(otherAttribute) {
        var ownAttributes = this.attributes; 
        for(var ctr=0; ctr<ownAttributes.length; ctr++) {
            var ownAttribute = ownAttributes[ctr];
            if(ownAttribute.matches(otherAttribute)) {
                return true;
            }
        }
        
        return false;
    },
    
    matches : function(selectedAttributes) {
        var matchCount = 0;
        
        var ownAttributes = this.attributes;
        
        for(var ctr=0; ctr<selectedAttributes.length; ctr++) {
            var selectedAttribute = selectedAttributes[ctr];
            if(this.hasMatch(selectedAttribute)) {
                matchCount++;
            }
        }
        
        return selectedAttributes.length == ownAttributes.length && matchCount == ownAttributes.length;
        
        /*
        selectedAttributes.each(
            function(selectedAttribute) {
                if(ownAttributes[selectedAttribute.key] == selectedAttribute.value) {
                    matchCount++;
                }
            }
        );        
        
        
        return  (selectedAttributes.keys().length == this.attributes.keys().length) && 
                (matchCount == this.attributes.keys().length);
        */
    },
    
    toString : function() {
        return 'ise.Products.MatrixProduct';
    }
}

ise.Products.MatrixGroupProduct = function(id, itemCode, itemType) {
    ise.Products.MatrixGroupProduct.initializeBase(this, [id, itemCode, itemType]);
    
    this.matrixProducts = new Array();
    this.interChangeEventHandlers = new Array();
    
    this.attributes = null;
    this.selectedMatrixProduct = null;
    this.matrixProductsWithImagesPreloaded = 0;        
    this.onImagesLoaded = this.onMatrixImagesLoaded;
}
ise.Products.MatrixGroupProduct.registerClass('ise.Products.MatrixGroupProduct', ise.Products.Product);
ise.Products.MatrixGroupProduct.prototype = {

    onMatrixImagesLoaded : function() {
        if(this.matrixProductsWithImagesPreloaded == this.matrixProducts.length) {
            for(var ctr=0; ctr<this.imagesLoadedEventHandlers.length; ctr++) {
                var handler = this.imagesLoadedEventHandlers[ctr];
                handler(this);
            }
        }
    },
    
    registerMatrixProduct : function(product) {
        this.matrixProducts[this.matrixProducts.length] = product;
        var handler = Function.createDelegate(this, this.onMatrixItemImageLoaded);
        product.addImagesLoadedEventHandler(handler);
    },
    
    onMatrixItemImageLoaded : function() {
        this.matrixProductsWithImagesPreloaded++;
        this.onMatrixImagesLoaded();
    },
    
    chooseMatrixItem : function(itemCode) {
        var matchFound = false;
        
        for(var ctr=0; ctr<this.matrixProducts.length; ctr++) {
            var currentMatrixProduct = this.matrixProducts[ctr];
            if(currentMatrixProduct.getItemCode() == itemCode) {
                this.setSelectedMatrixProduct(currentMatrixProduct);
                matchFound = true;
            }
        }
        
        if(!matchFound) {
            this.selectedMatrixProduct = null;
        }
    },
    
    chooseAttributes : function(attributes) {
        var matchFound = false;
        
        for(var ctr=0; ctr<this.matrixProducts.length; ctr++) {
            var currentMatrixProduct = this.matrixProducts[ctr];
            if(currentMatrixProduct.matches(attributes)) {
                this.setSelectedMatrixProduct(currentMatrixProduct);
                matchFound = true;
            }
        }
        
        if(!matchFound) {
            this.selectedMatrixProduct = null;
        }
    },
    
    getSelectedMatrixProduct : function() {
        return this.selectedMatrixProduct;
    },
    
    hasSelectedMatrixProduct :function() {
        return null != this.selectedMatrixProduct;
    },
    
    setSelectedMatrixProduct : function(selectedMatrixProduct) {
        this.selectedMatrixProduct = selectedMatrixProduct;        
        this.ownAsSelf(selectedMatrixProduct);
    },
    
    ownAsSelf : function(other) {
        this.id = other.getId();
        this.itemCode = other.getItemCode();
        this.setRestrictedQuantities(other.getRestrictedQuantities());
        this.setHidePriceUntilCart(other.getHidePriceUntilCart());
        this.setShowBuyButton(other.getShowBuyButton());
        this.setMinimumOrderQuantity(other.getMinimumOrderQuantity());
        this.setUnitMeasureIntrinsics(other.getUnitMeasures());
        this.setImageData(other.getImageData());
        this.setAttributes(other.getAttributes());
        
        this.onInterChange();
    },
    
    getAttributes : function() {
        return this.attributes;
    },
    
    setAttributes : function(attributes) {
        this.attributes = attributes;
    },
    
    addInterChangeEventHandler : function(handler) {
        this.interChangeEventHandlers[this.interChangeEventHandlers.length] = handler;
    },
    
    onInterChange : function() {
        for(var ctr=0; ctr<this.interChangeEventHandlers.length; ctr++) {
            var handler = this.interChangeEventHandlers[ctr];
            handler(this);
        }
    },
    
    getSwatchImage : function(id) {
        for(var ctr=0; ctr<this.matrixProducts.length; ctr++) {
            var matrixProduct = this.matrixProducts[ctr];
            if(matrixProduct.getId() == id) {
                return matrixProduct.imageData.swatch;
            }
        }
    },
    
    toString : function() {
        return 'ise.Products.MatrixGroupProduct';
    }
    
}

ise.Products.PriceControl = function(id, clientId) {
    this.id = id;
    this.ctrl = $getElement(clientId);
}
ise.Products.PriceControl.registerClass('ise.Products.PriceControl');

ise.Products.PriceControl.prototype = {
    setProduct: function(product) {
        this.setProductWithLabel(product, 'true');
    },

    setProductWithLabel: function(product, showLabel) {
        if (product) {
            this.product = product;
            this.attachPriceChangedEventHandler();

            this.buildDisplayWithLabel(showLabel);
            //this.buildDisplay();
        }
        else {
            ise.Products.ProductController.addObserver(this);
        }
    },

    notify: function(product) {
        if (product.getId() == this.id) {
            this.setProduct(product);
        }
    },

    attachPriceChangedEventHandler: function() {
        if (this.product) {
            var handler = Function.createDelegate(this, this.onProductPriceChanged);
            this.product.addPriceChangedEventHandler(handler);
        }
    },

    clearDisplay: function() {
        this.ctrl.innerHTML = "";
    },

    buildDisplay: function() {
        this.buildDisplayWithLabel('true');
    },

    buildDisplayWithLabel: function(displayLabel) {
        if (this.product) {
            this.clearDisplay();

            if (!this.product.getHidePriceUntilCart()) {
                var pnlPrice = document.createElement('DIV');
                pnlPrice.id = 'pnlPrice_' + this.id;
                this.ctrl.appendChild(pnlPrice);

                var lblPriceCaption = document.createElement('SPAN');
                lblPriceCaption.id = 'lblPriceCaption_' + this.id;

                if (displayLabel == 'true') {
                    lblPriceCaption.innerHTML = ise.StringResource.getString('is_showproduct.aspx.52');
                }

                lblPriceCaption.innerHTML = lblPriceCaption.innerHTML + '&nbsp;';

                pnlPrice.appendChild(lblPriceCaption);

                var lblPrice = document.createElement('SPAN');
                lblPrice.id = 'lblPrice_' + this.id;
                lblPrice.innerHTML = this.product.getPriceFormatted() + '&nbsp';

                pnlPrice.appendChild(lblPrice);

                // begin
                // by  : glviente
                // date: 05/06/09
                // info: as the UM changes with the Price display, available items
                //       should also change.

                // getting html components involved.
                var lblStockHint = $getElement('lblStockHint_' + this.id);
                var imgStockHint = $getElement('imgStockHint_' + this.id);

                // displays the Stock Hint if lblStockHint element is present.
                if (lblStockHint != null) {

                    // checked if FreeStock is greater than zero
                    if (this.product.getFreeStock() > 0) {
                        var nFreeStock = this.product.getFreeStock();

                        // FOR WHOLE Number Display Option - If as 'is' as Value Please Comment Out
                        // -----------------------------------------------------------------------
                        //jakirton - Changed this to Math.floor becasue the ToFixed() sometimes rounded up
                        //which would show more product available then there actually was.
                        var nFreeTemp = Math.floor(nFreeStock);

                        nFreeTemp += '';
                        nFreeArray = nFreeTemp.split('.');
                        nFreeItem = nFreeArray[0];
                        nFreeActual = nFreeArray.length > 1 ? '.' + nFreeArray[1] : '';

                        var nRegExp = /(\d+)(\d{3})/;
                        while (nRegExp.test(nFreeItem)) {
                            nFreeItem = nFreeItem.replace(nRegExp, '$1' + ',' + '$2');
                        }
                        nFreeStock = nFreeItem + nFreeActual;
                        // -----------------------------------------------------------------------                                                                                                    

                        lblStockHint.innerText = nFreeStock + ' ' + ise.StringResource.getString('is_showproduct.aspx.90');
                    }
                    else {
                        if (imgStockHint != null) {
                            imgStockHint.style.visibility = 'visible';
                        }
                    }
                }

                // 
                // end            

                var lblPrice_VAT = document.createElement('SPAN');
                lblPrice_VAT.id = 'lblPrice_VAT';
                if (this.product.getHasVat()) {
                    if (this.product.getVatSetting() == ise.Constants.VAT_SETTING_INCLUSIVE) {
                        lblPrice_VAT.innerHTML = ise.StringResource.getString('is_showproduct.aspx.57');
                    }
                    else {
                        lblPrice_VAT.innerHTML = ise.StringResource.getString('is_showproduct.aspx.56');
                    }
                }

                pnlPrice.appendChild(lblPrice_VAT);
                lblPrice_VAT.className = 'VATLabel';
                pnlPrice.className = "SalesPrice";

                if (this.product.hasPromotionalPrice()) {
                    var pnlPromotionalPrice = document.createElement('DIV');
                    pnlPromotionalPrice.id = 'pnlPromotionalPrice_' + this.id;
                    this.ctrl.appendChild(pnlPromotionalPrice);

                    var lblPromotionalPriceCaption = document.createElement('SPAN');
                    lblPromotionalPriceCaption.id = 'lblPromotionalPriceCaption_' + this.id
                    lblPromotionalPriceCaption.innerHTML = ise.StringResource.getString('is_showproduct.aspx.53') + '&nbsp;';
                    pnlPromotionalPrice.appendChild(lblPromotionalPriceCaption);

                    var lblPromotionalPrice = document.createElement('SPAN');
                    lblPromotionalPrice.id = 'lblPromotionalPrice_' + this.id
                    lblPromotionalPrice.innerHTML = this.product.getPromotionalPriceFormatted() + '&nbsp';
                    pnlPromotionalPrice.appendChild(lblPromotionalPrice);

                    var lblPromotionalPrice_VAT = document.createElement('SPAN');
                    lblPromotionalPrice_VAT.id = 'lblPromotionalPrice_VAT'
                    if (this.product.getHasVat()) {
                        if (this.product.getVatSetting() == ise.Constants.VAT_SETTING_INCLUSIVE) {
                            lblPromotionalPrice_VAT.innerHTML = ise.StringResource.getString('is_showproduct.aspx.57');
                        }
                        else {
                            lblPromotionalPrice_VAT.innerHTML = ise.StringResource.getString('is_showproduct.aspx.56');
                        }
                    }
                    pnlPromotionalPrice.appendChild(lblPromotionalPrice_VAT);

                    pnlPromotionalPrice.className = 'PromotionalPrice';
                    pnlPrice.className = "SalesPriceOverridden";
                    lblPromotionalPrice_VAT.className = 'VATLabel';
                }
            }
        }
    },

    onProductPriceChanged: function(product) {
        this.buildDisplay();
    }

}

ise.Products.UnitMeasureControl = function(id, clientId) {
    this.id = id;
    this.ctrl = $getElement(clientId);
    this.product = null;
}
ise.Products.UnitMeasureControl.registerClass('ise.Products.UnitMeasureControl');
ise.Products.UnitMeasureControl.prototype = {

    setProduct : function(product) {
        if(product) {
            this.product = product;
            this.buildDisplay();
            
            if(this.product.getItemType() == 'Matrix Group') {
                var handler = Function.createDelegate(this, this.onProductInterChanged);
                this.product.addInterChangeEventHandler(handler);
            }
        }
        else {
            ise.Products.ProductController.addObserver(this);
        }
    },
    
    notify : function(product) {
        if(product.getId() == this.id) {
            this.setProduct(product);
        }
    },
    
    onUnitMeasureChanged : function(sender) {
        if(this.product) {
            var selectedUnitMeasure = sender.options[sender.selectedIndex].value;
            
            this.product.setUnitMeasure(selectedUnitMeasure);
        }
    },
    
    onProductInterChanged : function() {
        this.buildDisplay();
    },
    
    buildDisplay : function() {
        this.clearDisplay();
        
        var umCode = this.product.getUnitMeasure();
        var idx = 0;
        
        var unitMeasures = this.product.getUnitMeasures();
        if(unitMeasures.length > 1) {
            var span = document.createElement('SPAN');
            span.id = 'lblUnitMeasure_' + this.id;
            span.innerHTML = ise.StringResource.getString('is_showproduct.aspx.51') + '&nbsp;';
            this.ctrl.appendChild(span);
            
            var select = document.createElement('SELECT');
            select.id = 'UnitMeasureCode_' + this.id;
            select.name = 'UnitMeasureCode';
            
            for(var ctr=0; ctr<unitMeasures.length; ctr++) {
                var current = unitMeasures[ctr];
                select.options.add(new Option(current.description, current.code));
                
                if(umCode == current.code) {
                    idx = ctr;
                }
            }
            
            this.ctrl.appendChild(select);
            
            //$(select).selectedIndex = idx;
            select.selectedIndex = idx;
                        
            //$(select).observe('change', this.onUnitMeasureChanged.bind(this, select))            
            var handler = Function.createDelegate(this, this.onUnitMeasureChanged);
            // we need to call our handler that accepts the drop down list as parameter
            // we therefore use anonymous method instead
            var onChangeHandler = function() {
                // pass the combobox as parameter
                handler(select);
            }
            $addHandler(select, 'change', onChangeHandler);
        }
        else {
            var input = document.createElement('INPUT');
            input.type = 'hidden';
            input.id = 'UnitMeasureCode_' + this.id;
            input.name = 'UnitMeasureCode';            
            this.ctrl.appendChild(input);
            
            var span = document.createElement('SPAN');
            span.id = 'lblUnitMeasure_' + this.id;
            span.innerHTML = ise.StringResource.getString('is_showproduct.aspx.51') + '&nbsp;' + unitMeasures[0].description;
            this.ctrl.appendChild(span);
        }
    },
    
    clearDisplay : function() {
        this.ctrl.innerHTML = '';
    }
    
}


ise.Products.MatrixAttributeControl = function(id, attribute) {
    this.ctrl = $getElement(id);
    this.attribute = attribute;
    
    this.attributeChangedEventHandlers = new Array();
    
    if(this.ctrl) {
        this._attachAttributeChangedEventHandler();
    }
}
ise.Products.MatrixAttributeControl.registerClass('ise.Products.MatrixAttributeControl');
ise.Products.MatrixAttributeControl.prototype = {

    _attachAttributeChangedEventHandler : function() {
        var handler = Function.createDelegate(this, this.onAttributeChanged);
        //this.ctrl.observe('change', this.onAttributeChanged.bind(this));
        $addHandler(this.ctrl, 'change', handler);
    },
    
    onAttributeChanged : function() {
        var value = this.ctrl.options[this.ctrl.selectedIndex].value;
        
        for(var ctr=0; ctr< this.attributeChangedEventHandlers.length; ctr++) {
            var handler = this.attributeChangedEventHandlers[ctr];
            handler(value);
        }
    },
    
    addAttributeChangedEventHandler : function(handler) {        
        this.attributeChangedEventHandlers[this.attributeChangedEventHandlers.length] = handler;
    },
    
    getAttribute : function() {
        return this.attribute;
    },
    
    getValue : function() {
        if(this.hasAttributeSelected()) {
            var value = this.ctrl.options[this.ctrl.selectedIndex].value;
            return value;
        }
        
        return ise.Constants.EMPTY_STRING;
    },
    
    setValue : function(value) {
        var idx = 0;
        
        for(var ctr=0;ctr<this.ctrl.options.length; ctr++) {
            var option = this.ctrl.options[ctr];
            if(option.value == value) {
                idx = ctr;
                break;
            }
        }
        
        this.ctrl.selectedIndex = idx;
    },
    
    hasAttributeSelected : function() {
        return this.ctrl.selectedIndex > 0;
    }

}

ise.Products.MatrixAttributeGroupControl = function(id) {
    this.id = id;
    
    this.attributeControls = new Array();
    this.product = null;
    
    this.pnlError = $getElement('pnlMatrixAttribute_Error_' + id);
    this.pnlSelectCaption = $getElement('pnlMatrixAttribute_SelectCaption_' + id);
    this.pnlStockHint = $getElement('pnlStockHint_' + id);

    this.attachFormHandler();
}

ise.Products.MatrixAttributeGroupControl.registerClass('ise.Products.MatrixAttributeGroupControl');
ise.Products.MatrixAttributeGroupControl.prototype = {

    setProduct : function(product) {
        if(product) {
            this.product = product;
            
            if(this.product.getItemType() == 'Matrix Group') {
                var handler = Function.createDelegate(this, this.onProductInterChanged);
                this.product.addInterChangeEventHandler(handler);
            }
        }
        else {
            ise.Products.ProductController.addObserver(this);
        }
    },
    
    notify : function(product) {
        if(product.getId() == this.id) {
            this.setProduct(product);
        }
    },
    
    attachFormHandler : function() {
        var addToCartForm = ise.Products.AddToCartFormController.getForm(this.id);
        
        var handler = Function.createDelegate(this, this.onAddToCartFormValidating);
        var addToCartFormValidatingEventHandler = handler;
        if(addToCartForm) {
            addToCartForm.addAddToCartValidatingEventHandler(addToCartFormValidatingEventHandler);
        }
        else {
            var id = this.id;
            
            var observer = {
            
                notify : function(form) {
                    if(form.getId() == id) {
                        form.addAddToCartValidatingEventHandler(addToCartFormValidatingEventHandler);
                    }
                }
                
            }
            
            ise.Products.AddToCartFormController.addObserver(observer);
        }
    },
    
    onAddToCartFormValidating : function(e) {
        if(!this.ensureAllAttributesAreSelected()) {
            e.cancel = true;
                        
            this.pnlError.innerHTML = ise.StringResource.getString('is_showproduct.aspx.59') + ' ';
            //this.pnlSelectCaption.hide();
            this.pnlSelectCaption.style.display = 'none';
            
            var appendComma = false;
            
            for(var ctr=0; ctr<this.attributeControls.length; ctr++) {
                var ctrl = this.attributeControls[ctr];            
                if(!ctrl.hasAttributeSelected()) {
                    this.pnlError.innerHTML += (appendComma? ', ' : '') + ctrl.getAttribute();
                    appendComma = true;
                }
            }
        }
        else {
            if(!this.product.hasSelectedMatrixProduct()) {
                e.cancel = true;                
                this.pnlError.innerHTML = ise.StringResource.getString('is_showproduct.aspx.58');
            }
        }
    },
    
    onProductInterChanged : function() {
        this.clearError();
        
        var attributes = this.product.getAttributes();
        var controls = this.attributeControls;        
        
        for(var ctr=0; ctr<attributes.length; ctr++) {
            var attribute = attributes[ctr];
            
            for(var ictr=0; ictr<controls.length; ictr++) {
                var currentControl = controls[ictr];
                if(currentControl.getAttribute() == attribute.code) {
                    currentControl.setValue(attribute.value);
                }
            }
        }
    },
    
    clearError : function() {
        this.pnlError.innerHTML = '';
    },
    
    registerAttributeControl : function(control) {
        this.attributeControls[this.attributeControls.length] = control;
        
        var handler = Function.createDelegate(this, this.onAttributeChangedEventHandler);
        control.addAttributeChangedEventHandler(handler);
    },
    
    onAttributeChangedEventHandler : function(selectedValue) {
        this.clearError();
        
        if(this.ensureAllAttributesAreSelected()) {
            var allAttributes = new Array();
            
            for(var ctr=0; ctr<this.attributeControls.length; ctr++) {
                var ctrl = this.attributeControls[ctr];
                //allAttributes[ctrl.getAttribute()] = ctrl.getValue();
                var attribute = new ise.Products.MatrixAttribute(ctrl.getAttribute(), ctrl.getValue());
                allAttributes.push(attribute);
            }
            this.product.chooseAttributes(allAttributes);
            
            if(!this.product.hasSelectedMatrixProduct()) {
                this.pnlError.innerHTML = ise.StringResource.getString('is_showproduct.aspx.58');
                //this.pnlSelectCaption.hide();
                this.pnlSelectCaption.style.display = 'none';
                if (this.pnlStockHint) {
                    //this.pnlStockHint.hide()
                    this.pnlStockHint.style.display = 'none';
                }
            }
        }
        else
        {
            //this.pnlSelectCaption.show();
            this.pnlSelectCaption.style.display = '';
            if (this.pnlStockHint) {
                //this.pnlStockHint.hide()
                this.pnlStockHint.style.display = 'none';
            }
        }
    },
    
    ensureAllAttributesAreSelected : function() {
        for(var ctr=0; ctr<this.attributeControls.length; ctr++) {
            var ctrl = this.attributeControls[ctr];
            
            if(!ctrl.hasAttributeSelected()) {
                return false;
            }
        }
        
        return true;
    }

}


ise.Products.ImageMultipleControl = function(id, index, src) {
    this.id = id;
    this.index = index;
    
    this.ctrl = $getElement(id);
    this.ctrl.src = src;
    
    this.attachClickEventHandler();
    this.attachHoverEventHandler();
    
    this.selectEventHandlers = new Array();
    this.hoverEventHandlers = new Array();
}
ise.Products.ImageMultipleControl.registerClass('ise.Products.ImageMultipleControl');
ise.Products.ImageMultipleControl.prototype = {

    getIndex : function() {
        return this.index;
    },
    
    attachClickEventHandler : function() {
        var handler = Function.createDelegate(this, this.onClickEventHandler);
        //this.ctrl.observe('click', this.onClickEventHandler.bind(this));
        $addHandler(this.ctrl, 'click', handler);
    },
    
    addSelectEventHandler : function(handler) {
        this.selectEventHandlers[this.selectEventHandlers.length] = handler;
    },
    
    attachHoverEventHandler : function() {
        var handler = Function.createDelegate(this, this.onHoverEventHandler);
        //this.ctrl.observe('mouseover', this.onHoverEventHandler.bind(this));
        $addHandler(this.ctrl, 'mouseover', handler);
    },
    
    onClickEventHandler : function() {
        for(var ctr=0; ctr<this.selectEventHandlers.length; ctr++) {
            var handler = this.selectEventHandlers[ctr];
            handler(this);
        }
    },
    
    addHoverEventHandler : function(handler) {
        this.hoverEventHandlers[this.hoverEventHandlers.length] = handler;
    },
    
    onHoverEventHandler : function() {
        for(var ctr=0; ctr<this.hoverEventHandlers.length; ctr++) {
            var handler = this.hoverEventHandlers[ctr];
            handler(this);
        }
    },
    
    setImage : function(src) {
        this.ctrl.src = src;
    },
    
    show : function() {
        this.ctrl.style.display = "";
    },
    
    hide : function() {
        this.ctrl.style.display = "none";
    }
}

ise.Products.ImageSwatchControl = function(id, clientId, itemCode){
    this.id = id;
    this.itemCode = itemCode;
    
    this.ctrl = $getElement(clientId);
    
    this.attachClickEventHandler();
    this.selectEventHandlers = new Array();
}
ise.Products.ImageSwatchControl.registerClass('ise.Products.ImageSwatchControl');
ise.Products.ImageSwatchControl.prototype = {

    getId : function() {
        return this.id;
    },
    
    getItemCode : function() {
        return this.itemCode;
    },
    
    attachClickEventHandler : function() {
        var handler = Function.createDelegate(this, this.onClickEventHandler);
        //this.ctrl.observe('click', handler);
        $addHandler(this.ctrl, 'click', handler);
    },
    
    
    addSelectEventHandler : function(handler) {
        this.selectEventHandlers[this.selectEventHandlers.length] = handler;
    },
    
    onClickEventHandler : function() {
        for(var ctr=0; ctr<this.selectEventHandlers.length; ctr++) {
            var handler = this.selectEventHandlers[ctr];
            handler(this);
        }
    },
    
    setImage : function(src) {
        this.ctrl.src = src;
    },
    
    show : function() {
        this.ctrl.style.display = "";
    },
    
    hide : function() {
        this.ctrl.style.display = "none";
    }
    
}

ise.Products.LargeImageLinkControl = function(id) {
    this.id = id;
    this.ctrl = $getElement(id);
    
    this.attachClickEventHandler();
    this.selectEventHandlers = new Array();
}
ise.Products.LargeImageLinkControl.registerClass('ise.Products.LargeImageLinkControl');
ise.Products.LargeImageLinkControl.prototype = {

    attachClickEventHandler : function() {
        //this.ctrl.observe('click', this.onClickEventHandler.bind(this));
        var handler = Function.createDelegate(this, this.onClickEventHandler);
        $addHandler(this.ctrl, 'click', handler);
    },
    
    
    addSelectEventHandler : function(handler) {
        this.selectEventHandlers[this.selectEventHandlers.length] = handler;
    },
    
    onClickEventHandler : function() {
        for(var ctr=0; ctr<this.selectEventHandlers.length; ctr++) {
            var handler = this.selectEventHandlers[ctr];
            handler(this);
        }
    },
    
    show : function() {
        this.ctrl.style.display = "";
    },
    
    hide : function() {
        this.ctrl.style.display = "none";
    }
}

ise.Products.ImageControl = function(id, clientId) {
    this.id = id;
    this.ctrl = $getElement(clientId);
    
    this.lnkLargeImage = null;
    this.multipleControls = new Array();
    this.swatchControls = new Array();
    this.product = null;
    
    this.multipleImageIndex = -1;
    
    this.useMicroImages = false;
    this.handleHover = false;
}
ise.Products.ImageControl.registerClass('ise.Products.ImageControl');
ise.Products.ImageControl.prototype = {

    setProduct : function(product) {
        if(product) {
            this.product = product;
            
            if(this.product.areImagesLoaded()) {
                this.arrangeDisplay();
            }
            else {
                var handler = Function.createDelegate(this, this.onProductImagesLoaded);
                this.product.addImagesLoadedEventHandler(handler);
            }
            
            if(this.product.getItemType() == 'Matrix Group') {
                this.attachInterChangeEventHandler();
            }
        }
        else {
            ise.Products.ProductController.addObserver(this);
        }
    },
    
    notify : function(product) {
        if(product.getId() == this.id) {
            this.setProduct(product);
        }
    },
    
    arrangeDisplay : function() {
        if(this.product) {
            var src = this.product.getMediumImage().src;
            this.setImage(src);
            
            this.toggleLargeImageVisibility();
            this.arrangeMultipleControls();
            
            if(this.product.getItemType() == 'Matrix Group') {
                this.arrangeSwatchControls();
            }
        }
    },
    
    onProductImagesLoaded : function() {
        this.arrangeDisplay();
    },
    
    setLargeImageControl : function(control) {
        if(control) {
            this.lnkLargeImage = control;
            var handler = Function.createDelegate(this, this.onLargeImageLinkSelected);
            this.lnkLargeImage.addSelectEventHandler(handler);
            this.toggleLargeImageVisibility();
        }
    },
    
    setUseMicroImages : function(useMicro) {
        this.useMicroImages = useMicro;
    },
    
    setHandleHover : function(handle) {
        this.handleHover = handle;
    },
    
    attachInterChangeEventHandler : function() {
        var handler = Function.createDelegate(this, this.onProductInterChanged);
        this.product.addInterChangeEventHandler(handler);
    },
    
    refreshImage : function() {
        var src = this.product.getMediumImage().src;
        this.setImage(src);
        
        this.multipleImageIndex = -1;
        
        this.toggleLargeImageVisibility();
        this.arrangeMultipleControls();
    },
    
    onProductInterChanged : function() {
       this.refreshImage();
    },
    
    registerMultipleControl : function(control) {
        this.multipleControls[this.multipleControls.length] = control;
        
        var handler = Function.createDelegate(this, this.onMultipleImageControlSelected);
        control.addSelectEventHandler(handler);
        
        if(this.handleHover) {
            control.addHoverEventHandler(handler);
        }
        
        this.arrangeMultipleControls();
    },
    
    toggleLargeImageVisibility : function() {
        if(this.lnkLargeImage && this.product) {
            
            var img = null;
            if(this.multipleImageIndex == -1) {
                img = this.product.getLargeImage();
            }
            else {
                img = this.product.getLargeImage(this.multipleImageIndex);
            }
            
            if(img && img.exists) {
                // ise.Products.LargeImageLinkControl has show function
                this.lnkLargeImage.show();
                
                var handler = Function.createDelegate(this, this.showLargeImage);
                this.ctrl.onclick = handler;
                
                this.ctrl.className = 'product_image';
            }
            else {
                // ise.Products.LargeImageLinkControl has hide function
                this.lnkLargeImage.hide();
            }
        }
    },
    
    onLargeImageLinkSelected : function() {
        this.showLargeImage();
    },
    
    showLargeImage : function() {
        var img = null;
        if(this.multipleImageIndex == -1) {
            img = this.product.getLargeImage();
        }
        else {
            img = this.product.getLargeImage(this.multipleImageIndex);
        }
        
        var url = 'popup.aspx?psrc='+ encodeURIComponent(img.src);
        var name = 'LargeImage';
        var resizable = img.resizable?'yes':'no';
        var params = 'toolbar=no,location=no,directories=no,status=no,menubar=no,scrollbars=' + resizable + ',resizable=' + resizable + ',copyhistory=no,width=' + img.size.width + ',height=' + img.size.height + 'left=0,top=0';
        window.open(url, name, params);
    },
    
    arrangeMultipleControls : function() {
        if(this.product) {
            for(var ctr=0; ctr<this.multipleControls.length; ctr++) {
                var control = this.multipleControls[ctr];
                var img = this.product.getMediumImage(ctr);
                if(img && img.exists) {
                    // control has show function
                    control.show();
                    
                    if(this.useMicroImages) {
                        var micro = this.product.getMicroImage(ctr);
                        control.setImage(micro.src);
                    }
                }
                else {
                    // control has hide function
                    control.hide();
                }
            }
        }
    },
    
    onMultipleImageControlSelected : function(control) {
        var index = control.getIndex();
        this.multipleImageIndex = index;
        
        var src = this.product.getMediumImage(index).src;
        
        this.setImage(src);
        this.toggleLargeImageVisibility();
    },
    
    registerSwatchControl : function(control) {
        this.swatchControls[this.swatchControls.length] = control;
        
        var handler = Function.createDelegate(this, this.onSwatchImageControlSelected);
        control.addSelectEventHandler(handler);
    },
    
    arrangeSwatchControls : function() {
        for(var ctr=0; ctr<this.swatchControls.length; ctr++) {
            var swatchControl = this.swatchControls[ctr];
            var id = swatchControl.getId();
            var swatch = this.product.getSwatchImage(id);
            if(swatch && swatch.exists) {
                swatchControl.setImage(swatch.src);
                // SwatchControl has a show function
                swatchControl.show();
                //swatchControl.style.display = '';
            }
            else {
                // SwatchControl has a hide function
                swatchControl.hide();
                //swatchControl.style.display = 'none';
            }
        }
    },
    
    onSwatchImageControlSelected : function(control) {
        var itemCode = control.getItemCode();
        this.product.chooseMatrixItem(itemCode);
    },
    
    setImage : function(src) {
        this.ctrl.src = src;
    }
    
}


ise.Products.StockHintControl = function(id, clientId, inStockSrc, outOfStockSrc) {
    this.id = id;
    this.ctrl = $getElement(clientId);
    this.inStockSrc = inStockSrc;
    this.outOfStockSrc = outOfStockSrc;
            
    this.attributeControls = new Array();
    
    this.pnlSelectCaption = $getElement('pnlMatrixAttribute_SelectCaption_' + id);
    this.pnlStockHint = $getElement('pnlStockHint_' + id);
}
ise.Products.StockHintControl.registerClass('ise.Products.StockHintControl');
ise.Products.StockHintControl.prototype = {

    setProduct : function(product) {
        if(product) {
            this.product = product;
            this.arrangeDisplay();
            
            if(this.product.getItemType() == 'Matrix Group') {
                var handler = Function.createDelegate(this, this.onProductInterChanged);
                this.product.addInterChangeEventHandler(handler);
            }
        }
        else {
            ise.Products.ProductController.addObserver(this);
        }
    },
    
    notify : function(product) {
        if(product.getId() == this.id) {
            this.setProduct(product);
        }
    },
    
    onProductInterChanged : function() {
        this.arrangeDisplay();
    },
    
    arrangeDisplay : function() {
        if(this.product) {           
            if(this.product.getItemType() == 'Matrix Group') {            
                if (this.product.hasSelectedMatrixProduct()) {
                    //this.pnlSelectCaption.hide();
                    this.pnlSelectCaption.style.display = 'none';
                
                    //this.pnlStockHint.show();
                    this.pnlStockHint.style.display = '';
                }
                else {                
                    this.pnlSelectCaption.innerHTML = ise.StringResource.getString('is_showproduct.aspx.73') + '<br/><br/>';
                    //this.pnlSelectCaption.show();
                    this.pnlSelectCaption.style.display = '';
                
                    //this.pnlStockHint.hide();
                    this.pnlStockHint.style.display = 'none';
                }
            }
                        
            if(this.product.hasAvailableStock()) {
                this.showInStock();
            }
            else {
                this.showOutOfStock();
            }
        }
    },
    
    showInStock : function() {
        this.ctrl.src = this.inStockSrc;
    },
    
    showOutOfStock : function() {
        this.ctrl.src = this.outOfStockSrc;
    },
    
    show : function() {
        this.style.display = "";
    },
    
    hide : function() {
        this.style.display = "none";
    }
    
}

ise.Products.PricingLevelControl = function(id, clientId) {
    this.id = id;
    this.ctrl = $getElement('pnlPricingLevel_' + id);
    this.pnlInline = $getElement('pnlPricingLevelInline_' + id);
    this.pnlPopUp = $getElement('pnlPricingLevelPopUp_' + id);
    this.lnkPopUp = $getElement('lnkPricingLevelPopUp_' + id);
    
    this.product = null;
    this.showInline = true;
    this.backColor = '';
}
ise.Products.PricingLevelControl.registerClass('ise.Products.PricingLevelControl');
ise.Products.PricingLevelControl.prototype = {

    setProduct : function(product) {
        if(product) {
            this.product = product;
            this.buildDisplay();
            
            if(this.product.getItemType() == 'Matrix Group') {
                var handler = Function.createDelegate(this, this.onProductInterChanged);
                this.product.addInterChangeEventHandler(handler);
            }
        }
        else {
            ise.Products.ProductController.addObserver(this);
        }
    },
    
    notify : function(product) {
        if(product.getId() == this.id) {
            this.setProduct(product);
        }
    },
    
    onProductInterChanged : function() {
        this.buildDisplay();
    },
    
    setShowInline : function(inline) {
        this.showInline = inline;
    },
    
    setBackColor : function(color) {
        this.backColor = color;
    },
    
    clearDisplay : function() {
        //this.pnlInline.hide();
        this.pnlInline.style.display = 'none';
        //this.pnlPopUp.hide();
        this.pnlPopUp.style.display = 'none';
    },
    
    buildDisplay : function() {
        this.clearDisplay();
        if(this.product && !this.product.hasPromotionalPrice()) {
        
            var handler = Function.createDelegate(this, this.arrangeDisplay);            
            
            var itemCode = encodeURIComponent(this.product.getItemCode());
            var service = new ActionService();
            service.GetPricingLevel(itemCode, handler);
            /*
            var req = new Ajax.Request('action.axd?action=pricingLevel&itemCode=' + encodeURIComponent(this.product.getItemCode()),
                {
                    method : 'get',
                    onSuccess : function(transport) {
                        display(transport.responseText);
                    },
                    onFailure : function(transport) {
                    }
                }
            );
            */
        }
    },
    
    arrangeDisplay : function(html) {
        if(html == '') {
            if(this.pnlInline) this.pnlInline.style.display = 'none';
            if(this.pnlPopUp) this.pnlPopUp.style.display = 'none';
        }
        else {
            if(this.showInline) {
                this.pnlInline.innerHTML = '<p><b>' + ise.StringResource.getString('showproduct.aspx.8') + '<br/>' + html + '<br/> </b></p>';
                
                //this.pnlInline.show();
                this.pnlInline.style.display = '';
            }
            else {
                // tooltip.js
                new ToolTip(this.lnkPopUp.id, 'pricingLevel_ToolTip', html);
                
                //this.lnkPopUp.onmouseover = function(){ddrivetip(html, this.backColor, 300)};
                //this.lnkPopUp.onmouseout = hideddrivetip;
                
                //this.pnlPopUp.show();
                this.pnlPopUp.style.display = '';
            }
        }
    }
}

ise.Products.QuantityControl = function(id, clientId, initialQuantity) {
    this.id = $getElement(id);
    this.ctrl = $getElement(clientId);
    this.initialQuantity = initialQuantity;
    
    this.product = null;
    this.getValueDelegate = null
}
ise.Products.QuantityControl.registerClass('ise.Products.QuantityControl');
ise.Products.QuantityControl.prototype = {

    getValue : function() {
        if(this.getValueDelegate) {
            return this.getValueDelegate();
        }
        
        return 0;
    },
    
    setProduct : function(product) {
        if(product) {
            this.product = product;
            this.buildDisplay();
            
            if(this.product.getItemType() == 'Matrix Group') {
                var handler = Function.createDelegate(this, this.onProductInterChanged);
                this.product.addInterChangeEventHandler(handler);
            }
        }
        else {
            ise.Products.ProductController.addObserver(this);
        }
    },
    
    notify : function(product) {
        if(product.getId() == this.id) {
            this.setProduct(product);
        }
    },
    
    onProductInterChanged : function() {
        this.buildDisplay();
    },
    
    buildDisplay : function() {
        this.clearDisplay();
        
        var span = document.createElement('SPAN');
        span.id = 'lblQuantity_' + this.id;
        span.innerHTML = ise.StringResource.getString('is_showproduct.aspx.50') + '&nbsp;';
        this.ctrl.appendChild(span);
            
        if(this.product.hasRestrictedQuantities()) {
            var restrictedQuantities = this.product.getRestrictedQuantities();
            var select = document.createElement('SELECT');
            select.id = 'Quantity_' + this.id;
            select.name = 'Quantity';
            
            for(var ctr=0; ctr<restrictedQuantities.length; ctr++) {
                var quantity = restrictedQuantities[ctr];
                select.options.add(new Option(quantity, quantity));
            }
            
            this.ctrl.appendChild(select);
            
            this.getValueDelegate = function(){ return select.options[select.selectedIndex].value; };
        }
        else {
            var input = document.createElement('INPUT');
            input.type = 'text';
            input.id = 'Quantity' + this.id;
            input.name = 'Quantity';
            input.size = 3;
            input.maxLength = 7;
            input.value = this.initialQuantity;
            this.ctrl.appendChild(input);
            
            this.getValueDelegate = function(){ return input.value; };
        }
    },
    
    clearDisplay : function() {
        this.ctrl.innerHTML = '';
    }
        
}


ise.Products.AddToCartForm = function(id) {
    this.id = $getElement(id);
    this.pnlAddToCart = $getElement('pnlAddToCartForm_' + id);
    
    this.form = $getElement('AddToCartForm_' + id); 
    var submitHandler = Function.createDelegate(this, this.onAddToCartClick);
    this.form.onsubmit = submitHandler; //this.onAddToCartClick.bind(this);
    
    this.btnAddToCart = $getElement('AddToCart_' + id);
    var addToCartClickHandler = Function.createDelegate(this, this.onAddToCartClick);
    this.btnAddToCart.onclick = addToCartClickHandler; //this.onAddToCartClick.bind(this);
    
    this.btnAddToWishList = $getElement('AddToWishList_' + id);
    if(this.btnAddToWishList) {
        var addToWishHandler = Function.createDelegate(this, this.onAddToWishListClick);
        this.btnAddToWishList.onclick = addToWishHandler; //this.onAddToWishListClick.bind(this);
    }
    
    this.ctrlQuantity = null;
    this.checkForFreeStock = false;
    this.product = null;
    
    this.addToCartValidatingEventHandlers = new Array();
}
ise.Products.AddToCartForm.registerClass('ise.Products.AddToCartForm');
ise.Products.AddToCartForm.prototype = {

    getId : function() {
        return this.id;
    },
    
    setProduct : function(product) {
        if(product) {
            this.product = product;
            this.toggleVisibility();
            
            if(this.product.getItemType() == 'Matrix Group') {
                var handler = Function.createDelegate(this, this.toggleVisibility);
                this.product.addInterChangeEventHandler(handler);
            }
        }
        else {
            ise.Products.ProductController.addObserver(this);
        }
    },
    
    toggleVisibility : function() {
        if(this.product.getShowBuyButton()) {
            //this.pnlAddToCart.show();
            this.pnlAddToCart.style.display = '';
        }
        else {
            //this.pnlAddToCart.hide();
            this.pnlAddToCart.style.display = 'none';
        }
    },
    
    notify : function(product) {
        if(product.getId() == this.id) {
            this.setProduct(product);
        }
    },
    
    addAddToCartValidatingEventHandler : function(handler) {
        this.addToCartValidatingEventHandlers.push(handler);
    },
    
    onAddToCartValidating : function(cancelEventArgs) {
        
        for(var ctr=0; ctr<this.addToCartValidatingEventHandlers.length; ctr++) {
            var cancelEventHandler = this.addToCartValidatingEventHandlers[ctr];
            cancelEventHandler(cancelEventArgs);
            if(cancelEventArgs.cancel) {
                return true;
            }
        }
        
        return false;
    },    
    
    setCheckForFreeStock : function(check) {
        this.checkForFreeStock = check;
    },
    
    onAddToCartClick : function() {
        if(this.validate()) {
            return this.doSubmit();
        }
        else {
            return false;
        }
    },
    
    onAddToWishListClick : function() {
        if(this.validate()) {
            $getElement('IsWishList_' + this.id).value = 1;
            
            return this.doSubmit();
        }
        else {
            return false;
        }
    },
    
    setQuantityControl : function(control) {
        this.ctrlQuantity = control;
    },
    
    validate : function() {
        if(null == this.product) {
            alert(ise.StringResource.getString('is_showproduct.aspx.57'));
            return false;
        }
        
        // check for other handlers
        var cancelEventArgs = { cancel : false }
        this.onAddToCartValidating(cancelEventArgs);
        if(cancelEventArgs.cancel) {        
            return false;
        }
        
        if(this.product.getItemType() == 'Matrix Group' && !this.product.hasSelectedMatrixProduct()) {
            alert(ise.StringResource.getString('is_showproduct.aspx.48'));
            return false;
        }
        
        var quantity = this.ctrlQuantity.getValue();
        
        if(!quantity.match(/^\d+$/)) {
            alert(ise.StringResource.getString('common.cs.80'));
            return false;
        }        
        
        if(quantity == 0) {
            alert(ise.StringResource.getString('common.cs.84'));
            return false;
        }
        
        if(quantity < this.product.getMinimumOrderQuantity()) {
            alert(ise.StringResource.getString('is_showproduct.aspx.55') + this.product.getMinimumOrderQuantity());
            return false;
        }
        
        if(this.checkForFreeStock) {
        
            if( this.product.getItemType() == 'Stock' || 
                this.product.getItemType() == 'Matrix Group' || 
                this.product.getItemType() == 'Matrix Item' || 
                this.product.getItemType() == 'Assembly') {
            
                if(this.product.getFreeStock() <= 0) {
                    alert(ise.StringResource.getString('is_showproduct.aspx.49'));
                    return false;
                }
                
                if(this.product.getFreeStock() < quantity) { 
                    alert(ise.StringResource.getString('is_showproduct.aspx.61') + '   ' + this.product.getFreeStock());
                    return false;
                }            
            }
            else if(this.product.getItemType() == "Kit") {
                var allHasStock = true;
                
                for(var ctr=0; ctr<this.product.groups.length; ctr++) {
                    if(allHasStock) {
                        var group = this.product.groups[ctr];
                        var items = group.getSelectedItems();
                        
                        for(var ictr=0; ictr<items.length; ictr++) {
                            var item = items[ictr];
                            
                            if( item && 
                                (item.getItemType() == 'Stock' || item.getItemType() == 'Matrix Item' || item.getItemType() == 'Assembly')) {
                                if(item.getFreeStock() < quantity) { 
                                    allHasStock = false;
                                    break;
                                }
                            }
                        }
                    }
                }
                
                if(!allHasStock) {
                    alert(ise.StringResource.getString('is_showproduct.aspx.70'));
                    return false;
                }
            }            
            
        }
        
        if(this.product.getItemType() == "Kit") {
            this.product.persistComposition();
        }
        
        return true;
    },
    
    doSubmit : function() {
        if(this.product.getItemType() == 'Matrix Group' && this.product.hasSelectedMatrixProduct()) {
            $getElement('ProductID_' + this.id).value = this.product.getId();
        }
        
        return true;
    }
    
}

ise.Products.AddToCartFormController = {
    
    initialize : function() {
        this.forms = new Array();
        this.observers = new Array();
    },
    
    registerForm : function(form) {
        this.forms[form.getId()] = form;
        this.notifyObservers(form);
    },
    
    getForm : function(id) {
        return this.forms[id];
    },
    
    addObserver : function(observer) {
        this.observers.push(observer);
    },
    
    notifyObservers : function(form) {
        for(var ctr=0; ctr<this.observers.length; ctr++) {
            var observer = this.observers[ctr];
            observer.notify(form);
        }
    }

}

ise.Products.AddToCartFormController.initialize();