﻿/**
 * @fileoverview This file contains JavaScript objects that support
 * the L'Oreal Core System V2.2. This file is commented using conventions
 * that support the documenting tool JSDoc
 * {@link http://sourceforge.net/projects/jsdoc JSDoc}
 * Syntax for the comments can be found at:
 * {@link http://jsdoc.sourceforge.net/#tagref JSDoc Comments}
 * {@link http://java.sun.com/j2se/javadoc/writingdoccomments/ Javadoc Comments}
 *
 * @author INS - Fatri Nesimi: <a href="mailto:fatri.nesimi@ins.com">fatri.nesimi@ins.com</a>
 * @author INS - Anthony Sena: <a href="mailto:anthony.sena@ins.com">anthony.sena@ins.com</a>
 * @version 1.0
 */
/** 
 * This function was supported in Ajax so called Atlas. Unfortunately, it seems
 * not to be supported so to let the rest of javascript unchanged I am creating this function instead
 *
 */
 /*
function $(elementId) {
   return document.getElementById(elementId);
}
*/
/**
 * IsTypeDefined is a boolean indicating wether the TYPE is defined or no
 * which is part of the MS AJAX
 */
var IsTypeDefined=false; 
/** 
 * Determines if TYPE is defined and if so, it set a global variable to true
 */
function SetTypeState() {
       if (typeof(Type)!='undefined') {
               IsTypeDefined=true
       }
       else {
            IsTypeDefined=false;
            eval("Core=function() {  }");
       
       }
}
/** 
 * calls SetTypeState and sets it to true if TYPE is defined
 */
SetTypeState();


/*
 * It Creates a namespace using MS Ajax Libraries "making javascript easier" if TYPE is defined
 */
 if (IsTypeDefined){ Type.registerNamespace("Core");  }

/**
 * @class WebServiceAPI_Class is intended to centralize all the webservices calls.
 * If a web service is timed out, the control is passed to js function onTimeout.
 * If an error is raised, the control is passed to js function onError.
 * @constructor
 * @see onTimeout({object} result)
 * @see onError({object} result)
 */ 
Core.WebServiceAPI_Class= function() {
    /*
     * Methods
     */

    /**
     * Used to add a product to a customer's favorite list
     * @param {string} CustomerId The customer ID GUID
     * @param {int} FavoriteProductType The type of favorite list to retrieve
     * @param {string} RetailerCode The current retailer code
     * @param {string} ProductCode The product code to add to the customer's favorite list
     * @param {function} OnCompleteFuncName This is the callback function after the web service returns the result data
     */
    this.AddToFavorites=function(CustomerId, FavoriteProductType, RetailerCode, ProductCode, OnCompleteFuncName) {
        if(!IsAjaxLoaded()) { return false; }
        try {
            //DoWait();
            MicrosoftFrance.MCS.Commerce.WS.AJAXProject.FavoritesWebService.FavoriteListProductAdd(CustomerId, FavoriteProductType, RetailerCode, ProductCode,eval(OnCompleteFuncName),onError);
        }
        catch (e)  {
            DoDefault();
            window.status = e.message;
        }
        return false;
    }    

    /**
     * Adds rating information for the selected <i>CustomerID</i>, <i>ProductForumName</i> and <i>ProductCode</i>
     * 
     * @param {string} ProductForumName The product forum name used for this rating
     * @param {string} ProductCode The source product code used to find the associated products
     * @param {string} CustomerID String in a form of GUID representing the Customer ID
     * @param {int} RateLevel The integer rating from the customer
     * @param {function} OnCompleteFuncName This is the callback function after the web service returns the result data
     */
    this.AddProductRating=function(ProductForumName, ProductCode, CustomerID, RateLevel, OnCompleteFuncName){
        if(!IsAjaxLoaded()) {return false;}

        try
        {
            DoWait();
            MicrosoftFrance.MCS.Commerce.WS.AJAXProject.ProductWebService.AddProductRating(ProductForumName, ProductCode, CustomerID, RateLevel,eval(OnCompleteFuncName),onError);

        }
        catch (e)
        {
            DoDefault();
            window.status = e.message;
        }
        return false;
    }

    /** 
     * Checks to see if a product is a part of a customer's favorite list.
     * @param {string} CustomerId The customer ID GUID
     * @param {int} FavoriteProductType The type of favorite list to retrieve
     * @param {string} RetailerCode The current retailer code
     * @param {string} ProductCode The product code to add to the customer's favorite list
     * @param {function} OnCompleteFuncName This is the callback function after the web service returns the result data
     */
    this.FavoriteListProductMembership=function(CustomerId, FavoriteProductType, RetailerCode, ProductCode, OnCompleteFuncName) {    
        if(!IsAjaxLoaded()) {return false;}

        try
        {
            DoWait();
            MicrosoftFrance.MCS.Commerce.WS.AJAXProject.FavoritesWebService.FavoriteListProductMembership(CustomerId, FavoriteProductType, RetailerCode, ProductCode,eval(OnCompleteFuncName),onError);
        }
        catch (e)
        {
            DoDefault();
            window.status = e.message;
        }
        return false;                
    }

    /**
     * This method provides a way for a customer to log into the website. This method should
     * be called using a secured page so that information is sent encrypted
     * over the wire.
     * @param {string} CustomerId The customer ID GUID
     * @param {string} Login The customer login (typically email address)
     * @param {string} Password The customer password
     * @param {function} OnCompleteFuncName This is the callback function after the web service returns the result data
     */
    this.CustomerLogin=function(CustomerId, Login, Password, OnCompleteFuncName,OnLoginError) {
        if(!IsAjaxLoaded()) { return false; }
        try {
            //DoWait();
            MicrosoftFrance.MCS.Commerce.WS.AJAXProject.CustomerWebService.Login(CustomerId, Login, Password,eval(OnCompleteFuncName),eval(OnLoginError));
        }
        catch (e)  {
            DoDefault();
            window.status = e.message;
        }
        return false;
    }

    
    /**
     * This method provides a way for a customer to register on the website. This method should
     * be called using a secured page so that information is sent encrypted
     * over the wire.
     * @param {string} CustomerId The customer ID GUID
     * @param {string} FirstName The customer first name
     * @param {string} LastName The customer last name
     * @param {string} Email The customer email (will be the customer's login)
     * @param {string} Password The customer password
     * @param {function} OnCompleteFuncName This is the callback function after the web service returns the result data
     */
     this.CustomerRegister=function(CustomerId, FirstName, LastName, Email, Password, OnCompleteFuncName){
        if(!IsAjaxLoaded()) { return false; }

        try {
            DoWait();
            MicrosoftFrance.MCS.Commerce.WS.AJAXProject.CustomerWebService.Register(CustomerId, FirstName, LastName, Email, Password, eval(OnCompleteFuncName),onError);
        }
        catch (e)  {
            DoDefault();
            window.status = e.message;
        }
        return false;
    }
    
    /**
     * Retrieves a list of a customer's favorite products
     * @param {string} CustomerId The customer ID GUID
     * @param {int} FavoriteProductType The type of favorite list to retrieve
     * @param {string} RetailerCode The current retailer code
     * @param {function} OnCompleteFuncName This is the callback function after the web service returns the result data
     */
    this.GetFavorites=function(CustomerId, FavoriteProductType, RetailerCode, OnCompleteFuncName) {
        if(!IsAjaxLoaded()) { return false; }

        try {
            DoWait();
            MicrosoftFrance.MCS.Commerce.WS.AJAXProject.FavoritesWebService.FavoriteListGet(CustomerId, FavoriteProductType, RetailerCode, eval(OnCompleteFuncName),onError);
        }
        catch (e)  {
            DoDefault();
            window.status = e.message;
        }
        return false;
    }
    
    /**
     * This method loads product information for a selected retailer
     * @param {string} RetailerCode Retailer Code
     * @param {string} ProductCode Product Code(SKU)
     * @param {bool} VariantsWanted If true, variants are also loaded with the product information
     * @param {function} OnCompleteFuncName This is the callback function after the web service returns the result data
     */
    this.GetProductInformationByRetailer=function(RetailerCode, ProductCode, VariantsWanted, OnCompleteFuncName) {
        if(!IsAjaxLoaded()) { return false; }

        try {
            DoWait();
           
            if (VariantsWanted) {
                MicrosoftFrance.MCS.Commerce.WS.AJAXProject.ProductWebService.GetProductInformationVariantsWantedByRetailer(RetailerCode, ProductCode, VariantsWanted,  eval(OnCompleteFuncName),onError,onTimeout);

            }
             else {
                 MicrosoftFrance.MCS.Commerce.WS.AJAXProject.ProductWebService.GetProductInformationByRetailer(RetailerCode, ProductCode, eval(OnCompleteFuncName),onError);
            }
        }
        catch (e)  {
            DoDefault();
            window.status = e.message;
        }
        return false;
    }
   
    /**
     * This method loads a particular product based on product code or a particular variant
     * @param {string} ProductCode Product Code(SKU)
     * @param {bool} VariantsWanted If true, variants are also loaded with the product information
     * @param {function} OnCompleteFuncName This is the callback function after the web service returns the result data
     */
    this.LoadProduct=function(ProductCode, VariantsWanted, OnCompleteFuncName)  {
        if(!IsAjaxLoaded()) { return false; }

        try {
            DoWait();
            if (VariantsWanted) {
             MicrosoftFrance.MCS.Commerce.WS.AJAXProject.ProductWebService.GetProductInformationVariantsWanted(ProductCode,true,eval(OnCompleteFuncName),onError);
            }
            else {
                MicrosoftFrance.MCS.Commerce.WS.AJAXProject.ProductWebService.GetProductInformation(ProductCode,eval(OnCompleteFuncName),onError);
               
            }
        }
        catch (e)  {
            DoDefault();
            window.status = e.message;
        }
        return false;
    }
    
    
     /**
     * This method loads a particular product based on product code or a particular variant
     * @param {string} ProductCode Product Code(SKU)
     * @param {string} filterExpression
     * @param {function} OnCompleteFuncName This is the callback function after the web service returns the result data
     */
     this.LoadProductWithFilteredVariants=function(ProductCode, filterExpression, OnCompleteFuncName)  {
        if(!IsAjaxLoaded()) { return false; }

        try {
            DoWait();
            MicrosoftFrance.MCS.Commerce.WS.AJAXProject.ProductWebService.GetProductInfoWithFilteredVariants(ProductCode,filterExpression,eval(OnCompleteFuncName),onError);
        }
        catch (e)  {
             DoDefault();
             window.status = e.message;
        }
        return false;
    }
        
    /**
     * This method loads a particular product based on product code or a particular variant
     * @param {string} ProductCode Product Code(SKU)
     * @param {bool} VariantsWanted If true, variants are also loaded with the product information
     * @param {function} OnCompleteFuncName This is the callback function after the web service returns the result data
     */
    this.LoadDiscontinuedProduct=function(RetailerCode, ProductCode,IgnoreFlags, VariantsWanted, OnCompleteFuncName)  {
        if(!IsAjaxLoaded()) { return false; }

        try {
            if (VariantsWanted) {
             //MicrosoftFrance.MCS.Commerce.WS.AJAXProject.ProductWebService.GetProductInformationVariantsWantedIgnoreFlags(RetailerCode, ProductCode, IgnoreFlags, VariantsWanted,eval(OnCompleteFuncName),onError);
              MicrosoftFrance.MCS.Commerce.WS.AJAXProject.ProductWebService.GetProductInformationVariantsWantedIgnoreFlagsSetFilter(RetailerCode, ProductCode, IgnoreFlags, VariantsWanted,"PRDRTL_ONLINE=-1",eval(OnCompleteFuncName),onError);
            }
            else {
                MicrosoftFrance.MCS.Commerce.WS.AJAXProject.ProductWebService.GetProductInformationIgnoreFlags(RetailerCode, ProductCode, IgnoreFlags, eval(OnCompleteFuncName),onError);
               
            }
        }
        catch (e)  {
            DoDefault();
            window.status = e.message;
        }
        return false;
    }
     
    /**
     * This method loads a pariticular product for a selected retailer. Allows for loading
     * product information for products that are inactive or offline. 
     * @param {string} RetailerCode Retailer Code
     * @param {string} ProductCode Product Code(SKU)
     * @param {bool} IgnoreFlags If true, load the product information regardless of its online status
     * @param {bool} VariantsWanted If true, variants are also loaded with the product information
     * @param {function} OnCompleteFuncName This is the callback function after the web service returns the result data
     */
    this.LoadProductIgnoreFlags=function(RetailerCode, ProductCode, IgnoreFlags, VariantsWanted, OnCompleteFuncName) {
        if(!IsAjaxLoaded()) { return false; }
        try {
            //DoWait();
            if (VariantsWanted) {
                   MicrosoftFrance.MCS.Commerce.WS.AJAXProject.ProductWebService.GetProductInformationVariantsWantedIgnoreFlags(RetailerCode, ProductCode, IgnoreFlags, VariantsWanted,eval(OnCompleteFuncName),onError);
            }
            else {
               
                   MicrosoftFrance.MCS.Commerce.WS.AJAXProject.ProductWebService.GetProductInformationIgnoreFlags(RetailerCode, ProductCode, IgnoreFlags, eval(OnCompleteFuncName),onError);
            }
        }
        catch (e)  {
            DoDefault();
            window.status = e.message;
        }
        return false;
    }
    
    /**
     * This method loads a pariticular product and its variants for the selected category
     * with information about recommendations based on the specified diagnosis code. 
     * @param {string} CurrentCustomerID The current customer ID (GUID)
     * @param {string} ProductCode Product Code(SKU)
     * @param {string} DiagCode The diagnosis code 
     * @param {string} CategoryCode The category code
     * @param {string} RetailerCode The retailer code
     * @param {function} OnCompleteFuncName This is the callback function after the web service returns the result data
     */
    this.LoadProductWithDiagnosisInformation=function(CurrentCustomerID, ProductCode, DiagCode, CategoryCode, RetailerCode,FilterExpression, OnCompleteFuncName)
    {
        if(!IsAjaxLoaded()) { return false; }
        try 
        {
             DoWait();
             MicrosoftFrance.MCS.Commerce.WS.AJAXProject.DiagnosisWebService.GetProductInfoWithDiagRecommendation(CurrentCustomerID, ProductCode, DiagCode, CategoryCode, RetailerCode, FilterExpression, eval(OnCompleteFuncName), onError);
        }
        catch (e)  
        {
            DoDefault();
            window.status = e.message;
        }
        return false;
    }

    /**
     * Retreieve variant information from the server for the selected product code
     * @param {string} RetailerCode Retailer Code
     * @param {string} ProductCode Product Code (SKU)
     * @param {function} OnCompleteFuncName This is the callback function after the web service returns the result data
     */
    this.GetVariantInformation=function(RetailerCode, ProductCode, OnCompleteFuncName) {
        if(!IsAjaxLoaded()) { return false; }

        try {
            DoWait();
            MicrosoftFrance.MCS.Commerce.WS.AJAXProject.ProductWebService.GetVariantInformation(RetailerCode, ProductCode,  eval(OnCompleteFuncName),onError);
        }
        catch (e)  {
            DoDefault();
            window.status = e.message;
        }
        return false;
    }
    
        /**
     * Retreieve variant information from the server for the selected product code
     * @param {string} RetailerCode Retailer Code
     * @param {string} ProductCode Product Code (SKU)
     * @param {function} OnCompleteFuncName This is the callback function after the web service returns the result data
     */
    this.GetVariantInformationIgnoreFlags=function(RetailerCode, ProductCode, ignoreFlags, OnCompleteFuncName) {
        if(!IsAjaxLoaded()) { return false; }

        try {
            //DoWait();
            MicrosoftFrance.MCS.Commerce.WS.AJAXProject.ProductWebService.GetVariantInformationIgnoreFlags(RetailerCode, ProductCode, ignoreFlags,  eval(OnCompleteFuncName),onError);
        }
        catch (e)  {
            DoDefault();
            window.status = e.message;
        }
        return false;
    }
    
    /**  
     * This method saves product notification information for a selected email address
     * and product
     * @param {string} CustomerEmail The customer's email address
     * @param {string} ProductCode Product Code(SKU)
     * @param {function} OnCompleteFuncName This is the callback function after the web service returns the result data
     */
    this.ProductStockNotificationSave=function(CustomerEmail, ProductCode, OnCompleteFuncName) {
        if(!IsAjaxLoaded()) {return false;}

        try
        {
            DoWait();
            MicrosoftFrance.MCS.Commerce.WS.AJAXProject.CustomerWebService.ProductStockNotificationSave(CustomerEmail, ProductCode,eval(OnCompleteFuncName),onError);

        }
        catch (e)
        {
            DoDefault();
            window.status = e.message;
        }
        return false;
    }

    /**
     * This methods adds an item to the shopping bag
     * @param {string} CustomerID String in a form of GUID representing the Customer ID
     * @param {string} ProductCode Product Code of the variant
     * @param {int} Quantity The number of <i>ProductCode</i> variants to add
     * @param {function} OnCompleteFuncName This is the callback function after the web service returns the result data
     */
    this.AddSingleProductToCart=function(CustomerID, ProductCode, Quantity, OnCompleteFuncName) {
        if(!IsAjaxLoaded()) {return false;}
        try
        {
            DoWait();
            MicrosoftFrance.MCS.Commerce.WS.AJAXProject.ShoppingCartWebService.AddSingleItem(CustomerID, ProductCode, Quantity,eval(OnCompleteFuncName),onError);
        }
        catch (e)
        {
            DoDefault();
            window.status = e.message;
        }
        return false;
    }

    /**
     * This methods adds multiple item to the shopping bag
     * @param {string} CustomerID String in a form of GUID representing the Customer ID
     * @param {Array} ProductCodes Array of variant product codes to add to the basket
     * @param {Array} Quantity Array with the cooresponding number of <i>ProductCode</i> variants to add
     * @param {function} OnCompleteFuncName This is the callback function after the web service returns the result data
     */
    this.AddMultipleProductsToCart=function(CustomerID, ProductCodes, Quantity, OnCompleteFuncName) {
        if(!IsAjaxLoaded()) {return false;}

        try
        {
            DoWait();
            MicrosoftFrance.MCS.Commerce.WS.AJAXProject.ShoppingCartWebService.AddMultipleItems(CustomerID, ProductCodes, Quantity, eval(OnCompleteFuncName),onError);
        }
        catch (e)
        {
            DoDefault();
            window.status = e.message;
        }
        return false;
    }
    
    /**
     * Retrieves the shopping cart
     * @param {string} CustomerID String in a form of GUID representing the Customer ID
     * @param {function} OnCompleteFuncName This is the callback function after the web service returns the result data
     */
    this.RetrieveShoppingCart=function (CustomerID, OnCompleteFuncName) {
        if(!IsAjaxLoaded()) {return false;}

        try
        {
            DoWait();
            MicrosoftFrance.MCS.Commerce.WS.AJAXProject.ShoppingCartWebService.RetrieveShoppingCart(CustomerID,eval(OnCompleteFuncName),onError);
        }
        catch (e)
        {
            DoDefault();
            window.status = e.message;
        }
        return false;
    }

    /**
     * Retrieves the last <i>N</i> number of items from the shopping cart
     * 
     * @param {string} CustomerID String in a form of GUID representing the Customer ID
     * @param {int} intLastItems The number of items to retrieve from the shopping cart. It assumes the shopping cart is stored as a stack so that the last intLastItems will be the most recently added ones.
     * @param {function} OnCompleteFuncName This is the callback function after the web service returns the result data
     */
    this.RetrieveShoppingCartLastItems=function(CustomerID, intLastItems, OnCompleteFuncName) {
        if(!IsAjaxLoaded()) {return false;}

        try
        {
            DoWait();
            MicrosoftFrance.MCS.Commerce.WS.AJAXProject.ShoppingCartWebService.RetrieveLastItems(CustomerID, intLastItems, eval(OnCompleteFuncName),onError);
        }
        catch (e)
        {
            DoDefault();
            window.status = e.message;
        }
        return false;
    }

    /**
     * Retrieves the promotion proximity for the customer's shopping 
     * cart. This method can be used to retrieve promotion proximity based on 
     * availability. See the parameter promotionAvailabilty for the available switches.
     * @param {string} CustomerID String in a form of GUID representing the Customer ID
     * @param {int} distancesToDisplay The number of distances to display. This will return up to <i>distancesToDisplay</i> promotion distances.
     * @param {string} evaluators Comma-delimited list of the type of promotions to evaluate for distance information. They are: CustomerRoleEvaluator, CustomerSegmentEvaluator, LineNotEmptyEvaluator, BasketPriceEvaluator, BasketItemsQuantityEvaluator, BasketItemsAxeEPQuantityEvaluator, BasketSpecificItemQuantityEvaluator, KeyCodeEvaluator
     * @param {int} promotionAvailability Used to get promotion distances based on promotion availability. Set this to NULL to evaluate only available promtoions. Otherwise, use the following values to tailor which promotions are returned: (0 = ALL, 1 = Available, 2 = Unavailable).
     * @param {function} OnCompleteFuncName This is the callback function after the web service returns the result data
     */
    this.GetPromotionProximity=function(CustomerId, distancesToDisplay, evaluators, promotionAvailability, OnCompleteFuncName) {
        if(!IsAjaxLoaded()) { return false; }

        try {
            DoWait();
            if (promotionAvailability != null) {
               MicrosoftFrance.MCS.Commerce.WS.AJAXProject.ShoppingCartWebService.GetPromotionProximityByAvailability(CustomerId, distancesToDisplay, evaluators, promotionAvailability,eval(OnCompleteFuncName),onError);
            }
            else {
              
               MicrosoftFrance.MCS.Commerce.WS.AJAXProject.ShoppingCartWebService.GetPromotionProximity(CustomerId, distancesToDisplay, evaluators, eval(OnCompleteFuncName),onError);
            }
        }
        catch (e)  {
            DoDefault();
            window.status = e.message;
        }
        return false;
    }
    
    /**
     * Retrieves the product association specified for the selected <i>AssociationName</i> and <i>ProductCode</i>
     * TODO - TEST
     * @param {string} RetailerCode The retailer code
     * @param {string} ProductCode The source product code used to find the associated products
     * @param {string} AssociationName The product association name
     * @param {bool} VariantsWanted When true, the variants for each product in the association are returned
     * @param {function} OnCompleteFuncName This is the callback function after the web service returns the result data
     */
    this.GetProductAssociations=function(RetailerCode,ProductCode,AssociationName,VariantsWanted,OnCompleteFuncName)  {
        if(!IsAjaxLoaded()) {return false;}

        try
        {
            DoWait();
            MicrosoftFrance.MCS.Commerce.WS.AJAXProject.ProductWebService.GetProductAssociations(RetailerCode, ProductCode,AssociationName,VariantsWanted, eval(OnCompleteFuncName),onError);
        }
        catch (e)
        {
            DoDefault();
            window.status = e.message;
        }
        return false;
    }
    
        /**
     * Retrieves the dicontinued product association specified for the selected <i>AssociationName</i> and <i>ProductCode</i>
     * TODO - TEST
     * @param {string} RetailerCode The retailer code
     * @param {string} ProductCode The source product code used to find the associated products
     * @param {string} AssociationName The product association name
     * @param {bool} VariantsWanted When true, the variants for each product in the association are returned
     * @param {function} OnCompleteFuncName This is the callback function after the web service returns the result data
     */
    this.GetProductAssociationsIgnoreFlags=function(RetailerCode,ProductCode,AssociationName,VariantsWanted,ignoreFlags,OnCompleteFuncName)  {
        if(!IsAjaxLoaded()) {return false;}

        try
        {
            DoWait();
            MicrosoftFrance.MCS.Commerce.WS.AJAXProject.ProductWebService.GetProductAssociationsIgnoreFlags(RetailerCode, ProductCode,AssociationName,VariantsWanted,ignoreFlags, eval(OnCompleteFuncName),onError);
        }
        catch (e)
        {
            DoDefault();
            window.status = e.message;
        }
        return false;
    }
    
            /**
     * Retrieves the dicontinued product association specified for the selected <i>AssociationName</i> and <i>ProductCode</i>
     * TODO - TEST
     * @param {string} RetailerCode The retailer code
     * @param {string} ProductCode The source product code used to find the associated products
     * @param {string} AssociationName The product association name
     * @param {bool} VariantsWanted When true, the variants for each product in the association are returned
     * @param {function} OnCompleteFuncName This is the callback function after the web service returns the result data
     */
    this.GetDiscontinuedProductAssociationsIgnoreFlags=function(RetailerCode,ProductCode,AssociationName,VariantsWanted,ignoreFlags,OnCompleteFuncName)  {
        if(!IsAjaxLoaded()) {return false;}

        try
        {
            //DoWait();
            MicrosoftFrance.MCS.Commerce.WS.AJAXProject.ProductWebService.GetProductAssociationsIgnoreFlags(RetailerCode, ProductCode,AssociationName,VariantsWanted,ignoreFlags, eval(OnCompleteFuncName),onError);
        }
        catch (e)
        {
            DoDefault();
            window.status = e.message;
        }
        return false;
    }
    
     /**
     * Retrieves topic information
     * @param {string} categoryCode The selected categoryCode
     * @param {string} filterCriteria 
     * @param {function} OnCompleteFuncName This is the callback function after the web service returns the result data
     */
    this.GetCategoryProductsCodes=function(categoryCode,filterCriteria,variantsWanted,OnCompleteFuncName)  {
        if(!IsAjaxLoaded()) {return false;}

        try
        {
            DoWait();
            MicrosoftFrance.MCS.Commerce.WS.AJAXProject.ProductWebService.GetCategoryProductsCodes(categoryCode,filterCriteria,variantsWanted, eval(OnCompleteFuncName),onError);
        }
        catch (e)
        {
            DoDefault();
            window.status = e.message;
        }
        return false;
    }

     /**
     * Retrieves products based on a CategoryCode
     * @param {string} categoryCode The selected categoryCode
     * @param {int} onlineStatus
     * @param {function} OnCompleteFuncName This is the callback function after the web service returns the result data
     */
    this.GetCategoryProductsByOnlineStatus=function(RetailerCode, CategoryCode, onlineStatus, variantsWanted,OnCompleteFuncName)  {
        if(!IsAjaxLoaded()) {return false;}

        try
        {
           MicrosoftFrance.MCS.Commerce.WS.AJAXProject.ProductWebService.GetCategoryProductsByOnlineStatus(RetailerCode, CategoryCode, onlineStatus, variantsWanted, eval(OnCompleteFuncName),onError);
        }
        catch (e)
        {
            DoDefault();
            window.status = e.message;
        }
        return false;
    }

     /**
     * Retrieves Discontinued product information
     * @param {string} categoryCode The selected categoryCode
     * @param {int} onlineStatus
     * @param {function} OnCompleteFuncName This is the callback function after the web service returns the result data
     */
    this.GetCategoryProductsCodesByOnlineStatus=function(CategoryCode,onlineStatus,OnCompleteFuncName)  {
        if(!IsAjaxLoaded()) {return false;}

        try
        {
           DoWait();
           MicrosoftFrance.MCS.Commerce.WS.AJAXProject.ProductWebService.GetCategoryProductsCodesByOnlineStatus(CategoryCode, onlineStatus, eval(OnCompleteFuncName),onError);
        }
        catch (e)
        {
            DoDefault();
            window.status = e.message;
        }
        return false;
    }
        
    /**
     * Retrieves topic information
     * @param {string} TopicCode The selected topic code
     * @param {string} TopicType The topic type
     * @param {function} OnCompleteFuncName This is the callback function after the web service returns the result data
     */
    this.GetTopicInformation=function(TopicCode, TopicType, OnCompleteFuncName) {
        if(!IsAjaxLoaded()) {return false;}

        try {
            DoWait();
            MicrosoftFrance.MCS.Commerce.WS.AJAXProject.TopicWebService.GetTopicInformation(TopicCode, TopicType,  eval(OnCompleteFuncName),onError);
        }
        catch (e) {
            DoDefault();
            window.status = e.message;
        }
        return false;
    }

    /**
     * Retrieves the products associated to the selected <i>TopicCode</i> and <i>TopicType</i>
     * 
     * @param {string} TopicCode The selected topic code
     * @param {string} TopicType The topic type
     * @param {string} productSortExpression The  sort
     * @param {function} OnCompleteFuncName This is the callback function after the web service returns the result data
     */
    this.GetTopicProducts= function (TopicCode, TopicType,productSortExpression, OnCompleteFuncName)  {
        if(!IsAjaxLoaded()) {return false;}

        try {
            DoWait();
            MicrosoftFrance.MCS.Commerce.WS.AJAXProject.TopicWebService.GetTopicProducts(TopicCode, TopicType,productSortExpression,eval(OnCompleteFuncName),onError);

        }
        catch (e) {
            DoDefault();
            window.status = e.message;
        }
        return false;
    }
    
      /**
     * Retrieves the products associated to the selected <i>TopicCode</i> and <i>TopicType</i>
     * 
     * @param {string} TopicCode The selected topic code
     * @param {string} TopicType The topic type
     * @param {string} productSortExpression The  sort
     * @param {string} filterExpression The filter even by extended property
     * @param {function} OnCompleteFuncName This is the callback function after the web service returns the result data
     */
    this.GetFilteredTopicProducts= function (TopicCode, TopicType, productSortExpression, filterExpression, OnCompleteFuncName)  {
        if(!IsAjaxLoaded()) {return false;}

        try {
            DoWait();
            MicrosoftFrance.MCS.Commerce.WS.AJAXProject.TopicWebService.GetFilteredTopicProducts(TopicCode, TopicType,productSortExpression,filterExpression,eval(OnCompleteFuncName),onError);

        }
        catch (e) {
            DoDefault();
            window.status = e.message;
        }
        return false;
    }
       /**
     * Retrieves the product codes associated to the selected <i>TopicCode</i> and <i>TopicType</i>
     * @param {string} TopicCode The selected topic code
     * @param {string} TopicType The topic type
     * @param {function} OnCompleteFuncName This is the callback function after the web service returns the result data
     */
    this.GetTopicProductsCodes= function (TopicCode, TopicType, OnCompleteFuncName)  {
        if(!IsAjaxLoaded()) {return false;}

        try {
            DoWait();
            MicrosoftFrance.MCS.Commerce.WS.AJAXProject.TopicWebService.GetTopicProductsCodes(TopicCode, TopicType,eval(OnCompleteFuncName),onError);
        }
        catch (e) {
            DoDefault();
            window.status = e.message;
        }
        return false;
    }
    
   /**
     * Retrieves the product codes associated to the selected <i>TopicCode</i> and <i>TopicType</i>
     * for the selected <i>RootCateogryCode</i>
     * @param {string} TopicCode The selected topic code
     * @param {string} TopicType The topic type
     * @param {string} RootCategoryName The root category name
     * @param {function} OnCompleteFuncName This is the callback function after the web service returns the result data
     */
    this.GetTopicProductsCodesByRootCategory = function (TopicCode, TopicType, RootCategoryName, OnCompleteFuncName) {
        if(!IsAjaxLoaded()) {return false;}

        try {
            DoWait();
            MicrosoftFrance.MCS.Commerce.WS.AJAXProject.TopicWebService.GetTopicProductsCodesByRootCategory(TopicCode, TopicType, RootCategoryName, eval(OnCompleteFuncName), onError);
        }
        catch (e) {
            DoDefault();
            window.status = e.message;
        }
        return false;
    }
    
       /**
     * Retrieves the product codes associated to the selected <i>TopicCode1,TopicCode2,TopcCodeN</i> 
     * @param {string} TopicList comma delimited list of toiccodes
      * @param {function} OnCompleteFuncName This is the callback function after the web service returns the result data
     */
    this.GetTopicProductsCodesByTopicList= function (TopicList,OnCompleteFuncName)  {
        if(!IsAjaxLoaded()) {return false;}
        try {
            DoWait();
            MicrosoftFrance.MCS.Commerce.WS.AJAXProject.TopicWebService.GetTopicProductsCodesByTopicList(TopicList,eval(OnCompleteFuncName),onError);
        }
        catch (e) {
            DoDefault();
            window.status = e.message;
        }
        return false;
    }
     
    /**
     * Used to remove a product from a customer's favorite list
     * @param {string} CustomerId The customer ID GUID
     * @param {int} FavoriteProductType The type of favorite list to retrieve
     * @param {string} RetailerCode The current retailer code
     * @param {string} ProductCode The product code to add to the customer's favorite list
     * @param {function} OnCompleteFuncName This is the callback function after the web service returns the result data
     */
    this.RemoveFromFavorites=function(CustomerId, FavoriteProductType, RetailerCode, ProductCode, OnCompleteFuncName) {
        if(!IsAjaxLoaded()) {return false;}

        try {
            DoWait();
            MicrosoftFrance.MCS.Commerce.WS.AJAXProject.FavoritesWebService.FavoriteListProductRemove(CustomerId, FavoriteProductType, RetailerCode, ProductCode,eval(OnCompleteFuncName),onError);
        }
        catch (e) {
            DoDefault();
            window.status = e.message;
        }
        return false;
    }
    
    /**
     * Used to remove a product from a customer's favorite list
     * @param {string} CustomerId The customer ID GUID
     * @param {string} Topic Code
     * @param {string} TopicType
     * @param {function} OnCompleteFuncName This is the callback function after the web service returns the result data
     */
    this.RemoveTopicFromFavorites=function(CustomerId, TopicCode, TopicType, OnCompleteFuncName) {
        if(!IsAjaxLoaded()) {return false;}

        try {
            DoWait();
            MicrosoftFrance.MCS.Commerce.WS.AJAXProject.FavoritesWebService.FavoriteTopicRemove(CustomerId, TopicCode, TopicType,eval(OnCompleteFuncName),onError);
        }
        catch (e) {
            DoDefault();
            window.status = e.message;
        }
        return false;
    }
    
    /**
     * Gets the topic information with the customer's rating information.
     * @param {string} CustomerId The customer ID GUID
     * @param {string} TopicCode The selected topic code
     * @param {string} TopicType The topic type
     * @param {function} OnCompleteFuncName This is the callback function after the web service returns the result data
     */
    this.GetTopicWithCustomerRating=function(CustomerId, TopicType, TopicCode, OnCompleteFuncName) {
        // Check to ensure the ATLAS module has been loaded before calling
        // the web service
        if(!IsAjaxLoaded()) {return false;}

        try {
            DoWait();
            MicrosoftFrance.MCS.Commerce.WS.AJAXProject.TopicWebService.GetTopicWithCustomerRating(CustomerId, TopicType, TopicCode,  eval(OnCompleteFuncName),onError);
        }
        catch (e) {
            DoDefault();
            window.status = e.message;
        }
        return false;
    }

    /**
     * Saves a customer's topic rating information
     * @param {string} CustomerId The customer ID GUID
     * @param {string} TopicCode The selected topic code
     * @param {string} TopicType The topic type
     * @param {string} TopicUrl The topic URL
     * @param {int} Rating The integer rating for the topic
     * @param {string} Comment The comment the customer has submitted related to this topic
     * @param {function} OnCompleteFuncName This is the callback function after the web service returns the result data
     */
    this.TopicCustomerRatingRecord=function(CustomerId, TopicType, TopicCode, TopicUrl, Rating, Comment, OnCompleteFuncName) {
        if(!IsAjaxLoaded()) {return false;}

        try {
            DoWait();
            MicrosoftFrance.MCS.Commerce.WS.AJAXProject.TopicWebService.TopicCustomerRatingRecord(CustomerId, TopicType, TopicCode, TopicUrl, Rating, Comment,eval(OnCompleteFuncName),onError);
        }
        catch (e) {
            DoDefault();
            window.status = e.message;
        }
        return false;
    }

    /**
     * Retrieves the customer's diagnosis products for a selected category.
     * @param {string} CustomerId The customer ID GUID
     * @param {string} DiagCode The diagnosis code
     * @param {string} CategoryCode The category code
     * @param {function} OnCompleteFuncName This is the callback function after the web service returns the result data
     */
    this.DiagnosisGetProductsByCategory=function(CustomerId, DiagCode, CategoryCode, OnCompleteFuncName) {
        if(!IsAjaxLoaded()) {return false;}

        try {
            DoWait();
            MicrosoftFrance.MCS.Commerce.WS.AJAXProject.DiagnosisWebService.GetProductsByCategory(CustomerId, DiagCode, CategoryCode, AJAX_DEFAULT_RTLCODE, eval(OnCompleteFuncName), onError);
        }
        catch (e) {
            DoDefault();
            window.status = e.message;
        }
        return false;
    }

}


/*
 * It registers the WebServiceAPI_Class using registerClass method of MS AJAX Library
 */
// if (IsTypeDefined) { Core.WebServiceAPI_Class.registerClass('Core.WebServiceAPI_Class', null); }
if (IsTypeDefined) { Core.WebServiceAPI_Class.registerClass('Core.WebServiceAPI_Class'); }



/**
 * @class CoreModalPopUp creates a modal pop up "bubble"
 */
Core.ModalPopUp= function () {
    /**
     *  The layer of the whole modal window (object)
     */
    var _backgroundElement=null;

    /**
     * The pop up that will show up (object)
     */
    this._foregroundElement=null;

    /**
     * the Id of the foregroundElement (string)
     */
    this._PopupControlID=null;
    
    /**
     * the name of the function to be called before the popup opens
     */
    this.beforeOpen=null; //null;
    
    /**
     * the name of the function to be called before the popup closes
     */
    this.beforeClose=null;
    
    this._IsforegroundElementLarge=false;
    
   

    /**
     * _Initialize
     */
    this._Initialize=function() {
        if (_backgroundElement==null) {
            _backgroundElement = document.createElement('div');
            _backgroundElement.style.display = 'none'; //none
            _backgroundElement.style.position = 'absolute';
            _backgroundElement.className = 'modalBackground';
            document.body.appendChild(_backgroundElement);
        }
    }

    /**
     *  _InitializeForeground
     */
    this._InitializeForeground=function() {
        this._foregroundElement = $get(this._PopupControlID);
        this._foregroundElement.style.display = 'none';
        this._foregroundElement.style.position = 'absolute';
        document.body.appendChild(this._foregroundElement);
    }

    /**
      * Show Modal
      */
    this.ShowModal=function () {
        if ((_backgroundElement==null) || (typeof(_backgroundElement)=='undefined') ) {
            this._Initialize()
        }

        if (this._PopupControlID !=null) {
            this._InitializeForeground();
        }
        
        // [AS] - Set the background here.
        var clientWidth = 0;
        var clientHeight = 0;
        if( typeof( window.innerWidth ) == 'number' ) {
            //Non-IE
            clientWidth = window.innerWidth;
            clientHeight = window.innerHeight;
            } 
        else if( document.documentElement && ( document.documentElement.clientWidth || document.documentElement.clientHeight ) ) {
            //IE 6+ in 'standards compliant mode'
            clientWidth = document.documentElement.clientWidth;
            clientHeight = document.documentElement.clientHeight;
        } 
        else if( document.body && ( document.body.clientWidth || document.body.clientHeight ) ) {
            //IE 4 compatible
            clientWidth = document.body.clientWidth;
            clientHeight = document.body.clientHeight;
        }

	    if (document.body.scrollHeight)
	    {
		    if (document.body.scrollHeight >= clientHeight)
		    {
			    clientHeight = document.body.scrollHeight;
		    }
		}
		
		_backgroundElement.style.left = '0px';
		_backgroundElement.style.top = '0px';
		_backgroundElement.style.width = document.body.clientWidth + 'px';
		_backgroundElement.style.height = clientHeight + 'px';
		_backgroundElement.style.display = 'block';

        // Reset for sizing the foreground element
        clientWidth =630;
        clientHeight=460;
        var scrollLeft = (document.documentElement.scrollLeft ? document.documentElement.scrollLeft : document.body.scrollLeft);
        var scrollTop = (document.documentElement.scrollTop ? document.documentElement.scrollTop : document.body.scrollTop);

        if (window.innerWidth) {
            clientWidth = (window.__safari ? window.innerWidth : Math.min(window.innerWidth, document.documentElement.clientWidth));
        }
        else {
            clientWidth = document.documentElement.clientWidth;
        }

        if (window.innerHeight) {
            clientHeight = (window.__safari ? window.innerHeight : Math.min(window.innerHeight, document.documentElement.clientHeight));
        }
        else {
            clientHeight = document.documentElement.clientHeight;
        }

        //show foreground element
        this._foregroundElement.style.display = 'block'; 
        //position it
        if (this._foregroundElement!=null) {
           this._foregroundElement.style.left = scrollLeft+((clientWidth-this._foregroundElement.offsetWidth)/2)+'px';
            //this._foregroundElement.style.top = scrollTop+((clientHeight-this._foregroundElement.offsetHeight-60)/2)+'px';
           //alert(this._IsforegroundElementLarge);
           if (this._IsforegroundElementLarge==true) {
           
              this._foregroundElement.style.top = scrollTop+((clientHeight-this._foregroundElement.offsetHeight)/4)+'px';
           
           }
           else {
             
             this._foregroundElement.style.top = scrollTop+((clientHeight-this._foregroundElement.offsetHeight)/2)+'px';
        
           }
             
                      
        }
        IS_MODELPOPUP_VISIBLE=true;
        if (this.beforeOpen!=null) {
             eval(this.beforeOpen + "();");
        
        }
     }

    /**
     * Hide with event
     */
    this.Hide=function() {
        this.HideModal();
        if (this.beforeClose!=null) {
             eval(this.beforeClose + "();");
        
        }
    }
    /**
     * Hide without event
     */
    this.HideModal=function() {
        if (_backgroundElement!=null) {
            _backgroundElement.style.display = 'none';
        }
        if (this._foregroundElement!=null) {
            this._foregroundElement.style.display = 'none';
        }
        IS_MODELPOPUP_VISIBLE=false;
        this._IsforegroundElementLarge=false;
    }
    

    /**
     * ResizeHandler 
     */
    this.ResizeHandler=function() {
//        [AS] - Disable the resize
//        if (_backgroundElement!=null && _backgroundElement.style.display != 'none' ){
//            this.ShowModal();
//        }
    }

    /** 
     * ScrollHandler    
     */
    this.ScrollHandler=function() {
//        [AS] - Disable the scroll
//        if (_backgroundElement!=null && _backgroundElement.style.display != 'none' ){
//            this.ShowModal();
//        }
    }
}
/*
 * It registers the WebServiceAPI_Class using registerClass method of MS AJAX Library
 */
 if (IsTypeDefined) { Core.ModalPopUp.registerClass('Core.ModalPopUp'); }

/**
 * @class StockNotification_Class, shows stock notification bubble and and adds it
 * 
 */
Core.StockNotification_Class=function() {
   this.StockNotificationID="StockNotification_MainContainerID";
   this.Html_Email_CtrlID="StockNotification_Email";
   this.PreviousPopUpControlID=null;
   this.Code="";
   
   //
   this.AddStockNotification=function() {
         
         var notificationEmail="";
         var objemail=$get(this.Html_Email_CtrlID);
         if (objemail!=null) {
             if (objemail.value!="") {
                notificationEmail=objemail.value;
                 if (checkemail(notificationEmail)) {
                    _CoreModalPopUp.Hide();
                  _WebServiceAPI.ProductStockNotificationSave(notificationEmail, this.Code, this.AddStockNotificationOnComplete);
                }
                else {
                alert('The email address supplied is invalid.');
                }
             }
         }
       
   }
   
   this.AddStockNotificationOnComplete=function(result) {
       DoDefault();
      _StockNotification.DoComplete(result);
 
   }
   
    this.DoComplete=function(result) {
     
        _CoreModalPopUp.Hide();
        if (this.PreviousPopUpControlID!=null) {
          _CoreModalPopUp._PopupControlID=this.PreviousPopUpControlID;
          _CoreModalPopUp.ShowModal();
        }
          if (result.ActivityStatus==true) {
           alert('Your email has been stored in our database.');
         }
       else  {
       
        alert(result.ErrorString);
                
        }
 
   }
   
   
   //
   this.ShowBubble=function(_code,preserveModal) {
     this.Code=_code;
     // alert( this.Code);
     // MM_showHideLayers(this.StockNotificationID,'','show','StockNotification_MainContainerID');
     
     if (preserveModal) {
       _CoreModalPopUp.Hide();
        this.PreviousPopUpControlID=_CoreModalPopUp._PopupControlID;
     }
     else {
        this.PreviousPopUpControlID=null;
     }
     _CoreModalPopUp._PopupControlID=this.StockNotificationID;
     _CoreModalPopUp.ShowModal();
   
   }


  this.Close=function() {
       _CoreModalPopUp.Hide();
        if (this.PreviousPopUpControlID!=null) {
          _CoreModalPopUp._PopupControlID=this.PreviousPopUpControlID;
          _CoreModalPopUp.ShowModal();
        }
  
  
  
  }

}
 if (IsTypeDefined) { Core.StockNotification_Class.registerClass('Core.StockNotification_Class'); }


/**
 * @class Quick shop class, shows and hides the quick shop image
 * that will be placed on top of the products.
 */
Core.QuickShop_Class=function (){
    /**
     * The HTML ID of the layer (div) for the quick shop class
     */
    this.QuickShop_DivID='QuickLook';

    /**
     * Code of cyrrent variant/product 
     */
    this.Code='';

    /**
     * Set to true if viewing a variant and set to false if viewing the whole product
     */
    this.IsVariant=true;
    
    this.VariantFilterExpression="";

    this.hasShades=false;
    
    this.FromProductBubble=false;
       
     this.timer;  
    /** 
     * Holds a reference to the parent control. If this value is present,
     * when attempting to show a new bubble, this control will attempt to hide
     * the parent
     */
    this.parentControlID=null;
        
    this.OutOfStock_ObjectID='OutOfStock_dhtmlObjectID';
    /**
     * This Method shows the quick look on top of a layer with id of RelativeObjectId
     * @param {string} RelativeObjectId The ID of the object where the quick look image/layer will be displayed as a hot spot
     * @param {string} Code ProductCode(SKU)
     * @param {bool} IsVariant true if it is variant, false otherwise
     */
    this.Show=function (RelativeObjectId,Code,IsVariant) {
         _ProductBubble_Class.FilterVariantList='';
        this.VariantFilterExpression="";
        this.Code=Code;
        this.IsVariant=IsVariant;
        MM_showHideLayers(this.QuickShop_DivID,'','show',RelativeObjectId);
    }
    /**
     * This Method shows the quick look on top of a dhtml object RelativeObject
     * If AbsoluteTop or Absoluteleft is let say 200 and 250, the displacement of quick look will
     * be 200 + plusTop and 250 + plusLeft. View the Code for more details
     * @param {string} RelativeObject Object where the quick look image (layer) will be displayed as a hot spot
     * @param {string} Code ProductCode(SKU)
     * @param {bool} IsVariant True if it is variant, false otherwise
     * @param {integer} plusTop integer like +20
     * @param {integer} plusLeft integer like +20
     * @hasShades {boolean} true if product has shades
     */
    this.ShowByObjectPosition=function (RelativeObject,Code,IsVariant,plusTop,plusLeft,hasShades) {
        this.VariantFilterExpression="";
        _ProductBubble_Class.FilterVariantList='';
        this.Code=Code;
        this.IsVariant=IsVariant;
        this.hasShades=hasShades;
        this.PositionLayerByRelativeObject(RelativeObject,$get(this.QuickShop_DivID),plusTop,plusLeft);
    }
    
   this.ShowOutOfSTockByObjectPosition=function (RelativeObject,Code,IsVariant,plusTop,plusLeft,hasShades) {
        this.VariantFilterExpression="";
        _ProductBubble_Class.FilterVariantList='';
        this.Code=Code;
        this.IsVariant=IsVariant;
        this.hasShades=hasShades;
        this.PositionLayerByRelativeObject(RelativeObject,$get(this.OutOfStock_ObjectID),plusTop,plusLeft);
    }
    
    
    this.PositionLayerByRelativeObject=function(RelativeObject,objid,plusTop,plusLeft) {
                  PositionLayerByRelativeObject(RelativeObject,objid,plusTop,plusLeft);
                  try {
                  clearTimeout(this.timer);
                  }
                  catch(err) {   }
                  this.timer=setTimeout("_QuickShop_Class.Hide();", 3000);
    }
        
     this.ShowIcon=function (RelativeObject,Code,IsVariant,plusTop,plusLeft,hasShades,StockWebNumber) {
        this.Hide();
        var StockItems=parseInt(StockWebNumber);
        var StockTresHold=1;
        try {
         StockTresHold=AJAX_GetTresHoldNumber();
        }
        catch (e) {   }
        
        if (AJAX_ENABLE_OUTOFSTOCK==false) {
            StockItems=100; //make the site allow the users to add items to stock. As long as it is greater then zero we're good.
        }
      
      
       if (StockItems>StockTresHold) {
            this.ShowByObjectPosition(RelativeObject,Code,IsVariant,plusTop,plusLeft,hasShades); 
  
       }
       else {
         this.ShowOutOfSTockByObjectPosition(RelativeObject,Code,IsVariant,plusTop,plusLeft,hasShades);
  
       }
      }
            
    this.ShowVariantFilterIcon=function (RelativeObject,Code,IsVariant,plusTop,plusLeft,hasShades,filterVariantList) {
        this.Code=Code;
        this.IsVariant=IsVariant;
        this.hasShades=hasShades;
        _ProductBubble_Class.FilterVariantList=filterVariantList;
         this.VariantFilterExpression="";
        this.PositionLayerByRelativeObject(RelativeObject,$get(this.QuickShop_DivID),plusTop,plusLeft); 
    }
    
       //THis method will be used when showing the product bubble but a filter expression is done based on extended properties
    // F.N 03.29.2007
    this.ShowProductFilterExpression=function (RelativeObject,Code,plusTop,plusLeft,hasShades,filterExpression) {
         _ProductBubble_Class.FilterVariantList="";
         this.VariantFilterExpression=filterExpression;
         this.Code=Code;
         this.IsVariant=false;
         this.hasShades=hasShades;
         this.PositionLayerByRelativeObject(RelativeObject,$get(this.QuickShop_DivID),plusTop,plusLeft); 
    }
    /**
     * Simply hides the quick shop image/layer
     */
    this.Hide=function() {
         //_ProductBubble_Class.FilterVariantList='';
         MM_showHideLayers( this.QuickShop_DivID,'','hide');
         MM_showHideLayers( this.OutOfStock_ObjectID,'','hide');
    }

    /**
     * When the quick shop bubble is shown, the user can click on that image.
     * This method is called when the user clicks on the image.
     * The method determines if it is a Variant or Product. Based on the requests, we
     * may need to do few more cases on this method.
     */
    this.ShowBubble=function() {
        if (this.IsVariant) {
            _ProductManager.LoadMakeupVariant(this.Code, this.parentControlID)
        }
        else {
            if(this.hasShades) {
             
               if (this.VariantFilterExpression=="" || typeof(this.VariantFilterExpression)=='undefined') {
                  _ProductManager.LoadMakeupProduct(this.Code, this.parentControlID);
                }
                else {
                   
                   //when passed filter exression on quick shop class
                   _ProductManager.LoadMakeupProductFilterVariants(this.Code, this.parentControlID,this.VariantFilterExpression);
                
                }
            }
            else {
                 if (this.VariantFilterExpression=="") {
                  _ProductManager.LoadSkinCareProduct(this.Code, this.parentControlID);
                }
                else {
                        //when passed filter exression on quick shop class
                     _ProductManager.LoadSkinCareFilterVariants(this.Code, this.parentControlID,this.VariantFilterExpression);
                
                }
            }
        }
    }
    
    
     /**
     * This method will be called from the bubbles to add a product on the
     *  favorites from quick shop
     */
    this.AddToFavoritesFromBubble=function() {
        if(CustomerSigned == true){
            var _prdType='Product';
            if (this.IsVariant) {
                _prdType='Variant';
            }
            //_CoreModalPopUp.Hide();
            _ProductManager.AddProductToFavorites(_prdType, AJAX_DEFAULT_RETAILER, this.Code);
        }else{
            _SignInBubble.ShowBubbleFromFavoritesBubble(this.Code);
        }
    }
    
    this.AddToFavorites=function(isVariant,Code) {
        this.FromProductBubble=true;
        this.IsVariant=isVariant;
        this.Code=Code;
        this.AddToFavoritesFromBubble();
    }
}

/*
 * It registers the QuickShop_Class using registerClass method of MS AJAX Library
 */
 if (IsTypeDefined) { Core.QuickShop_Class.registerClass('Core.QuickShop_Class'); }



/**
 * @class VariantBubble_Class
 *  This class is responsible into managing the Varianat Bubble Class
 * Please be aware that the properties of this class needs to be overridden based on the case that we will be using.
 *  The one which needs to be changed are
 *        this.VariantBubble_ImagePrefix   and    this.VariantBubble_ImageSuffix;
 * The other properties are DHTML Object IDs that needs to be populated with the data.....
 * In case there are other data that needs to be populated, we either need to support on this class or we need to prototype
 *  its methods.
 */

Core.VariantBubble_Class=function () {
    /**
     * The DHTML ID of the main layer of the Varianat bubble
     */
    this.VariantBubble_DivID="VariantBubble_Div";

    /**
     * The DHTML ID of the Product/Variant Image
     */
    this.VariantBubble_ImageID="VariantBubble_Image";

    /**
     * The DHTML ID of the quantity
     */
    this.VariantBubble_QuantityID="VariantBubble_Quantity";

    /**
     * The DHTML ID of the price label
     */
    this.VariantBubble_PriceID="VariantBubble_Price";

    /**
     * The DHTML ID of the product name label
     */
    this.VariantBubble_ProductNameID="VariantBubble_ProductName";
    /**
     * The DHTML ID of the product description label
     */
    this.VariantBubble_ProductDescID = "VariantBubble_ProductDesc";

    /**
     * The DHTML ID of the variant name label
     */
    this.VariantBubble_VariantNameID="VariantBubble_VariantName";
    /**
     * The DHTML ID of the variant name label
     */
    this.VariantBubble_VariantNameID2="VariantBubble_VariantName2";

    /**
     * The DHTML ID of the add to bag button on the bubble
     */
    this.VariantBubble_AddToBagID="VariantBubble_AddToBag";
     /**
     * The DHTML ID of the add to bag button on the bubble
     */
    this.VariantBubble_OutOfStockID="VariantBubble_OutOfStock";
    /**
     * The Prefix of the image
     */
    this.VariantBubble_ImagePrefix_LargeShade=IMAGES_RELATIVE_OR_ABSOLUTE_PATH +VARIANT_LARGE_SHADE_IMAGE_PREFIX;

    /**
     * The suffix of the image
     */
    this.VariantBubble_ImageSuffix_LargeShade=VARIANT_LARGE_SHADE_IMAGE_SUFFIX;
    
    this.VariantBubble_FavConfirmID = VAR_FAVORITE_CONFIRM_ID;
    this.VariantBubble_ProductInfoID = VAR_PRODUCT_INFO_ID;
    /**
     * Variant Code
     */
    this.Code="";
    /** 
     * Holds a reference to the parent control. If this value is present,
     * when attempting to show a new bubble, this control will attempt to hide
     * the parent
     */
    this.parentControlID=null;

    this.VIEWMOREDETAILS_ID="VARIANT_VIEWMOREDETAILS_OFPRODUCT";
    this.VIEWMOREDETAILS_INNERHTML_TEMPLATE="";

    /**
     * This method will attempt to hide the parent control (if present)
     */
    this.HideParentControl=function() {
        if (this.parentControlID!=null)
        {
            //MM_showHideLayers(this.parentControlID,'','hide');
            if (_ProductBubble_Class.PopUp != null)
            {
                _ProductBubble_Class.PopUp._PopupControlID=this.parentControlID;
                _ProductBubble_Class.PopUp.ShowModal();
            }
        }
    }
    
      /**
       * this method will hide add to bag and show outofstock item if the 
       * item is in stock or out of stock
       *
       */
    this.ManageStock=function(stockWeb) {
        if (AJAX_ENABLE_OUTOFSTOCK==true) {
           var stockqty=parseInt(stockWeb);
           var _bagObj=$get(this.VariantBubble_AddToBagID);
           var _outofstockobj=$get(this.VariantBubble_OutOfStockID);
           //
            var StockTresHold=1;
            try {
              StockTresHold=AJAX_GetTresHoldNumber();
            }
            catch (e) {   }
           //
           if (_outofstockobj!=null) {
              if (stockqty>StockTresHold) {
                
                _bagObj.style.display="";
                _outofstockobj.style.display="none";
              }
              else {
                 _bagObj.style.display="none";
                 _outofstockobj.style.display="";
              
              }
           }
         }
       }
    /**
     * This Method is called when the webservice is done with data retrieval
     * @param {object} result The data that comes into a JASON format from a web service
     */
    this.LoadVariantRequestComplete=function(result) {
        this.PopulateData(result);
    }

    /**
     * it resets the quantity to 1 if previously selected and it is not 1
     * 
     */
    this.ResetQuantity=function() {
      try {
                 var _qtyobj=$get( this.VariantBubble_QuantityID);
                 if (_qtyobj!=null)  {
                     for (var i=0; i< _qtyobj.options.length; i++) {
                              var str = _qtyobj.options[i].value;
                              if (str=="1") { 
                                  _qtyobj.options.selectedIndex=i;
                                   break;
                               }
                     }
                 
                 }
          }
        catch (err) {  } 
     }
    /**
     * This Method populates the variant bubble
     * @param {object} result The data that comes into a JASON format from a web service
     */
    this.PopulateData=function(result)  {
        this.HideParentControl();
        _QuickShop_Class.Hide();
        DoDefault();

        var obj=$get(this.VariantBubble_ImageID);
        if (obj!=null) {
      
        obj.src=this.VariantBubble_ImagePrefix_LargeShade + this.Code + this.VariantBubble_ImageSuffix_LargeShade;
           
       var Shade_HEX_Value=""; 
       var VariantShadeImage=""; 
          
    if(result.HasShades){    
      for(var i=0; i<result.Properties.length; i++) {
                      // alert(result.Properties[i].Name);
                       // alert(result.Properties[i].Value);
                        if (result.Properties[i].Name.toLowerCase()=='Shade_HEX_Value'.toLowerCase()) {
                          Shade_HEX_Value=result.Properties[i].Value;                        
                       obj.style.background=Shade_HEX_Value;
                          }
                          
                            if (result.Properties[i].Name.toLowerCase()=='VariantShadeImage'.toLowerCase()) {
                          VariantShadeImage=result.Properties[i].Value;                        
                           obj.src="/images/product/shades/"+VariantShadeImage;                          
                          }
       }
                   }
                   correctSinglePNG(obj);
    }
     
        var prodnameobj=$get(this.VariantBubble_ProductNameID);
        var prodDescObj = $get(this.VariantBubble_ProductDescID);
        var shadenameobj=$get(this.VariantBubble_VariantNameID);
        var shadenameobj2=$get(this.VariantBubble_VariantNameID2);
        var priceobj=$get(this.VariantBubble_PriceID);
        var viewmoredetailsobj=$get(this.VIEWMOREDETAILS_ID);
        var prodInfo = $get(this.VariantBubble_ProductInfoID);
        if (prodInfo!=null) {
          prodInfo.style.display = "block";
        }
        var confirmMsg = $get(this.VariantBubble_FavConfirmID);
        if (confirmMsg!=null) {
          confirmMsg.innerHTML='';
        }
  
        if (priceobj!=null) {
            priceobj.innerHTML="$ " + result.MainPrice;
        }
        if(prodnameobj!=null) {
            prodnameobj.innerHTML=result.ParentName;
        }
        if(prodDescObj != null){
            prodDescObj.innerHTML = result.ParentDescription;
        }
        if(shadenameobj!=null) {
            shadenameobj.innerHTML=result.Name;
        }
        if(shadenameobj2!=null) {
            shadenameobj2.innerHTML=result.Name;
        }
              
       
        this.ManageStock(result.StockWeb);
        //handle view more details
       if(viewmoredetailsobj!=null) {
       
         //var strviewmoredetails=viewmoredetailsobj.innerHTML;
          var strviewmoredetails=AJAX_BUBBLE_VARIANT_VIEWDETAIL_TEMPLATE;
            // url rewriting determination
                 var _urlrewritten=""
                 if (result.URLRewrittenHomePage) {
                    if (result.URLRewrittenHomePage!="") {
                      //on this case override the actual url with urlrewriting.
                       strviewmoredetails=AJAX_BUBBLE_VARIANT_VIEWDETAIL_TEMPLATE_URL_REWRITTEN;
                       _urlrewritten=result.URLRewrittenHomePage;
                    }
                 }
                 //
         if (this.VIEWMOREDETAILS_INNERHTML_TEMPLATE=="") {
            this.VIEWMOREDETAILS_INNERHTML_TEMPLATE=strviewmoredetails;//preserve for future clicks
         }
         else {
             strviewmoredetails=this.VIEWMOREDETAILS_INNERHTML_TEMPLATE;
         }
         strviewmoredetails=strviewmoredetails.replace("$$$AJAX_ParentProductCode$$$",result.ParentProductCode);
         strviewmoredetails=strviewmoredetails.replace("$$$AJAX_VariantCode$$$",this.Code);
         strviewmoredetails=strviewmoredetails.replace("$$$AJAX_ProductCategoryCode$$$",result.CategoryPath);
         strviewmoredetails=strviewmoredetails.replace("$$$AJAX_ProductRelativePath$$$",_ProductBubble_Class.GetRelativePath(result.CategoryHomePage));
          // url rewriting replacement
          if (_urlrewritten!="") {
            strviewmoredetails=strviewmoredetails.replace("$$$AJAX_ProductURLRewrittenHomePage$$$",_urlrewritten);
          }
                  //
         viewmoredetailsobj.innerHTML= strviewmoredetails.toString();;
       }
         MM_showHideLayers(this.VariantBubble_DivID,'','show','QuickLook');//revist this part in a better manner!
        _CoreModalPopUp._PopupControlID=this.VariantBubble_DivID;
        _CoreModalPopUp.ShowModal();
       
        //The line below sets the last item shopping Cart Item
        _LastShoppingCartItem.PopulateData(this.Code,result.Name,result.ParentProductCode,result.ParentName,result.MainPrice);
        try {
              _CoreAjaxCoremetrics.CreateProductViewTag(this.Code,result.ParentName + ' - ' + result.Name,result.CategoryCode,result.CategoryName);
           }
        catch (err) {  }   
        
        this.ResetQuantity();
    }

    /**
     * This method is called when add to bag is clicked on the variant bubble,
     * it determines the SKU, quantity and customer ID automatically and passes to a web service
     */
    this.AddSingleProductToCart=function () {
        var ItemQuantity=1;
        ItemQuantity=GetSelectedValue(this.VariantBubble_QuantityID);
        MM_showHideLayers(_VariantBubble_Class.VariantBubble_DivID,'','hide')
        _CoreModalPopUp.Hide();
        //Set the last Item Item Shopping Cart Item Quantity
         _LastShoppingCartItem.ItemQuantity=ItemQuantity;
         //
         CoreAjaxCookie_AddVariant(this.Code); //creeates a cookie to determine the product was added via quick shop
        // call webservice method
        _WebServiceAPI.AddSingleProductToCart (GetCurrentCustomerID(),this.Code,ItemQuantity,_ShoppingCartBubble_Class.AddSingleProductToCartResultHandler)
    }
    
    this.AddToCartFromProductDetails=function(_code,_quantity) {
       this.Code=_code;
        _LastShoppingCartItem.ItemQuantity=_quantity;
         _WebServiceAPI.AddSingleProductToCart (GetCurrentCustomerID(),this.Code,_quantity,_ShoppingCartBubble_Class.AddSingleProductToCartResultHandler)   
    }
}

/*
 * It registers the VariantBubble_Class using registerClass method of MS AJAX Library
 */
 if (IsTypeDefined) { Core.VariantBubble_Class.registerClass('Core.VariantBubble_Class'); }


/**
 * @class ProductBubble_Class
 * This class is responsible into managing the Product Bubble Class
 * Please be aware that the properties of this class needs to be overridden based on the case that we will be using.
 * The one which needs to be changed are
 *        this.VariantBubble_ImagePrefix   and    this.VariantBubble_ImageSuffix;
 * The other properties are DHTML Object IDs that needs to be populated with the data.....
 * In case there are other data that needs to be populated, we either need to support on this class or we need to prototype
 * its methods.
 *  this.RowSize=8 is a very important property, it manages how many variants will be shown in one row if
 * the product is a makeup product. It customizes building of shade table.
 */

Core.ProductBubble_Class=function() {
     /**
     * This property holds skus as comma delimited and determines to display only skus stored in 
     * the property below example prdcode1,prdcode2,prdcode3,prdcode4
     */
    this.FilterVariantList='';
    /**
     * The DHTML ID of the main layer of the Product bubble
     */
    this.Bubble_DivID="ProductBubble_Div";
    /**
     * The DHTML ID of the Product Image object
     */
    this.Bubble_ImageID="ProductBubble_Image";
    /**
     * The DHTML ID of the Quantity object
     */
    this.Bubble_QuantityID="ProductBubble_Quantity";
    /**
     * The DHTML ID   of the Product price label
     */
    this.Bubble_PriceID="ProductBubble_Price";
    /**
     * The DHTML ID   of the Product Name label
     */
    this.Bubble_ProductNameID="ProductBubble_ProductName";
    
     this.Bubble_ProductNameID2="ProductBubble2_ProductName";
    /**
     * The DHTML ID   of the Product description label
     */
    this.Bubble_ProductDescriptionID="ProductBubble_ProductDescription";
    /**
     * The DHTML ID   of the Variant Name label
     */
    this.Bubble_VariantNameID="ProductBubble_VariantName";
    /**
     * The DHTML ID   of the Add to bag object
     */
    this.Bubble_AddToBagID="ProductBubble_AddToBag"; //not used yet on js code
    
     /**
     * The DHTML ID   of the Out Of Stock Object (Optional);
     */
    this.Bubble_OutOfStockID="ProductBubble_OutOfStock"

    //Small Product Images
    /**
     * Small Image Prefix
     */
    this.Bubble_ImagePrefix_Product_Medium=IMAGES_RELATIVE_OR_ABSOLUTE_PATH + PRODUCT_MEDIUM_IMAGE_PREFIX;
    /**
     * Small Image Suffix
     */
    this.Bubble_ImageSuffix_Product_Medium=PRODUCT_MEDIUM_IMAGE_SUFFIX;

    //Small Shades
    /**
     * small shades prefix
     */
    this.Bubble_ImagePrefix_SmallShade=IMAGES_RELATIVE_OR_ABSOLUTE_PATH + VARIANT_SMALL_SHADE_IMAGE_PREFIX;
    /**
     * small shades suffix
     */
    this.Bubble_ImageSuffix_SmallShade=VARIANT_SMALL_SHADE_IMAGE_SUFFIX;

    //thumbnails
    /**
     * product thumbnails prefix
     */
    this.Bubble_ImagePrefix_MediumShade=IMAGES_RELATIVE_OR_ABSOLUTE_PATH + VARIANT_MEDIUM_SHADE_IMAGE_PREFIX;
    /**
     * product thumbnails suffix
     */
    this.Bubble_ImageSuffix_MediumShade=VARIANT_MEDIUM_SHADE_IMAGE_SUFFIX;

    /**
     * Product Code
     */
    this.Code="";
    /**
     *  The DHTML ID   of the drop down layer that lists all variants
     */
    this.Bubble_LayerDropDownListID="ProductBubble_VariantDropDownList";
    /**
     * The DHTML ID   of the drop down that lists all variants
     */
    this.Bubble_DropDownListID="DropDown_" + this.Bubble_LayerDropDownListID;
    /**
     * The DHTML ID   of small shades layer
     */
    this.ProductBubble_Small_ShadesID="ProductBubble_Small_Shades"
    /**
     * set to tru if has shades else set to false //check any valid property in db ???
     */
    this.IsMakeupProduct=false;
    /**
     * Number of elements per row
     */
    this.RowSize=7;        //Can be Changed
    /**
     * Current Index of the row
     */
    this.CurrentIndex=0;
    /**
     * temporary x postion of the mouse
     */
    this.tempX=0;
    /**
     * temporary y position of the mouse
     */
    this.tempY=0
    /**
     * The DHTML ID   of the variants thumbnail table
     */
    this.Variants_Main_All_Thumbnails='Ajax_Main_Bubble_All_Thumbnail_Shades';
    /**
     * The DHTML ID   of all variants
     */
    this.Variants_ThumbnailDivID='Ajax_allShades_layer';
    /**
     * set to true if multiple prices else set to false
     */
    this.HasMultiplePrices=false;
    /**
     * if all variants same price, this variable will hold the variant price
     */
    this.DistinctPrice=0;
     /**
     * if set to true, price will show on drop down if multiprice items
     */
    this.ShowPriceOnDropDown=false;
    
    this.ProductBubble_FavConfirmID = PRD_FAVORITE_CONFIRM_ID;
    this.ProductBubble_ProductInfoID = PRD_PRODUCT_INFO_ID;
    /**
     * If not null, this will hold a reference to the CoreModalPopup object to use
     * when show/hiding this object
     */
    this.PopUp=null;

    this.VIEWMOREDETAILS_ID="PRODUCT_BUBBLE_VIEWMOREDETAILS";
    this.VIEWMOREDETAILS_INNERHTML_TEMPLATE="";
    this.SelectShadeLabel="selectshadeLabel";
    this.DropDownShadeLabel="DropDownShadeLabel";
    this.DropDownSizeLabel="DropDownSizeLabel";
    //
    this.VIEWMOREDETAILS2_ID="PRODUCT_BUBBLE2_VIEWMOREDETAILS";
    this.VIEWMOREDETAILS_INNERHTML_TEMPLATE2="";
    this.lastClicked=null;
    /**
     * when product bubble is shown, preserve the category code and name
     * in case they are needed for the shades that will be selected from drop down
     * or from the color table of the bubble
     */
    this.CategoryCode="";
    this.CategoryName="";
    this.ProductName="";
    
    
    /**
     * This Method is called when the webservice is done with data retrieval
     * @param {object} result the data that comes into a JASON format from a web service
     */
    this.LoadProductRequestComplete=function(result) {
        this.PopulateData(result);
    }


    this.ReportSelectedVarToCoremetrics=function() {
    
    
    
    }
     /**
     * This Method is called when the users selects different options in size drop down
     *
     */
    this.SelectItem=function() {
       var priceobj=$get(this.Bubble_PriceID);
        
         //TODO Reset Image if needed later.
        // alert('1');
        var selectedvalue=this.GetSelectedItem();
        if (selectedvalue!="") {
            var sku="";
            var price="";
            var webStock=0;
            if (selectedvalue.indexOf("#") != -1){
		            var selectedvalue_array=selectedvalue.split("#");
		            sku=selectedvalue_array[0];
                    price=selectedvalue_array[1];
                    webStock=selectedvalue_array[2];
                    //alert(webStock);
                    this.ManageStock(webStock);
                    priceobj.innerHTML="$ " + price;
                    //if make up product with shades
                    //set the color image on
                    //set the image on
                    //set the shade name selected
                    if (this.IsMakeupProduct) { //F.N added on 4/4/2007
                            try {
                            // change image state
                             var selimg=$get('SM_' +  sku);
                             if (selimg!=null) {
                                     this.getswapimagesrc(selimg, 'on');
                             }
                            }
                            catch(e) {
                            
                            }
                            try {
                            //set image name on the bubble
                            this.SetVariantImageandName(sku,this.GetSelectedItemText());
                            }
                            catch(e) {
                            
                            }
                    }
	        }
	    }
      }
    
    
      /**
       * this method will hide add to bag and show outofstock item if the 
       * item is in stock or out of stock
       *
       */
       this.ManageStock=function(stockWeb) {
         if (AJAX_ENABLE_OUTOFSTOCK==true) {
           var stockqty=parseInt(stockWeb);
           var _bagObj=$get(this.Bubble_AddToBagID);
           var _outofstockobj=$get(this.Bubble_OutOfStockID);
            var StockTresHold=1;
            try { //placed try catch to handle any possible error on js because of js file caching, the AJAX_GetTresHoldNumber function was added on 5/29/2007
             StockTresHold=AJAX_GetTresHoldNumber();
            }
            catch (e) {   }
           if (_outofstockobj!=null) {
              if (stockqty>StockTresHold) {
                _bagObj.style.display="";
                _outofstockobj.style.display="none";
              }
              else {
                 _bagObj.style.display="none";
                 _outofstockobj.style.display="";
              
              }         
           }
         }
       }
    
    
     /**
       * this methods set as selected an option of variant drop down.
       * item is in stock or out of stock
       *
       */
     this.SetVariantDropDownItemSelected=function(dropDownID,valueToSelect) {
            var selectedstr=valueToSelect;
            var selectedVal;
            if (selectedstr.indexOf("#") != -1){
		        selectedstr=selectedstr.slice(0,sku.indexOf("#"));
	        }
            var options=document.getElementById(dropDownID)
            if (options!=null) {
                for (var i=0; i< options.length; i++) {
                    var str = options[i].value;
			        str = str.slice(0,str.indexOf("#"));
                    if (str==selectedstr) { //valueToSelect
                        options.selectedIndex=i;
                        selectedVal = options[i].text;
                        break;
                    }
                }
            }
        } 
       
    this.SetVariantImageandName=function(varSku, varName) {
        // change the shade image and shade name
        var imgObj=$get(this.Bubble_ImageID);
        var varNameobj = $get(this.Bubble_VariantNameID);
        if (imgObj != null)
            imgObj.src=this.Bubble_ImagePrefix_MediumShade + varSku + this.Bubble_ImageSuffix_MediumShade;
        if (varNameobj != null)
            varNameobj.innerHTML = varName;
         //report to coremetrics
             try {
                 _CoreAjaxCoremetrics.CreateProductViewTag(varSku, this.ProductName + ' - ' + varName,this.CategoryCode,this.CategoryName);
             }
             catch (err) {  }     
    }
      /**
     * This Method is called internaly to get the value of selected option
     *
     */
    this.GetSelectedItem=function() {
      var objdrp=$get(this.Bubble_DropDownListID);
      if (objdrp!=null) {
      return objdrp.options[objdrp.selectedIndex].value;
      }
      else {
        return "";
      }
    
    }
   this.GetSelectedItemText=function() {
      var objdrp=$get(this.Bubble_DropDownListID);
      if (objdrp!=null) {
    
      return objdrp.options[objdrp.selectedIndex].text;
      }
      else {
        return "";
      }
    
    }
    
    this.ContainsOneEmptyTextVariant=function() {
         var ContainsOneEmptyVariant=false;
         var objdrp=$get(this.Bubble_DropDownListID);
          if (objdrp!=null) {
              if (objdrp.options.length==1 ) {
                 if (objdrp.options[0].text=='') {
                   ContainsOneEmptyVariant=true;
                 }
              }
         }
        return ContainsOneEmptyVariant;
    }

this.getswapimagesrc=function(img, imgState)
{
    var imgSrc = '';
    var lastimgSrc = '';
    if (img != null)
    {
        var imgStateOn = "_on.";
        imgSrc = img.src;
        var imgPathAndFileName = imgSrc.slice(0, imgSrc.lastIndexOf(".") + 1);
        var imgFileExtension = imgSrc.slice(imgSrc.lastIndexOf(".") + 1, imgSrc.length);

        if (this.lastClicked != null)
        {
           if (this.lastClicked.src==img.src) return; //F.N: clicked on the same shade over and over, the if prevent by not changing the img src of the shade.
            lastimgSrc = this.lastClicked.src;
            var lastimgPathAndFileName = lastimgSrc.slice(0, lastimgSrc.lastIndexOf(".") + 1);           
            var lastimgFileExtension = lastimgSrc.slice(lastimgSrc.lastIndexOf(".") + 1, lastimgSrc.length);
	        lastimgSrc = lastimgPathAndFileName.slice(0, lastimgPathAndFileName.indexOf(imgStateOn)) + "." + lastimgFileExtension;
	        this.lastClicked.src = lastimgSrc
	        
        }
        if (imgState == 'on')
        {
	        imgSrc = imgPathAndFileName.slice(0, imgPathAndFileName.lastIndexOf(".")) + imgStateOn + imgFileExtension;
	        this.lastClicked = img;
	        img.src = imgSrc;
        }
    }
}	


     /**
     * it resets the quantity to 1 if previously selected and it is not 1
     * 
     */
    this.ResetQuantity=function() {
      try {
                 var _qtyobj=$get( this.Bubble_QuantityID);
                 if (_qtyobj!=null)  {
                     for (var i=0; i< _qtyobj.options.length; i++) {
                              var str = _qtyobj.options[i].value;
                              if (str=="1") { 
                                  _qtyobj.options.selectedIndex=i;
                                   break;
                               }
                     }
                 
                 }
          }
        catch (err) {  } 
     }
    /**
     * populates the product bubble
     * If it belongs to make up, it also builds the shade table with defautl 8 cells in one row.
     * @param {object} result the data that comes into a JASON format from a web service
     */
    this.PopulateData=function(result)  {
        if (result==null) {return false;}
        if (result.Variants==null) {return false;}               //product has no variants
        if (typeof(result)=='undefined') {return false;}
        if (typeof(result.Variants)=='undefined') {return false;} //product has no variants

        //check if the main layer exist. If it does not, return.
        
        var prodBubble=$get(this.Bubble_DivID);
        if ((prodBubble==null) || (prodBubble=='undefined')) {
            alert('The \"' + this.Bubble_DivID + '\" is not found.');
            return;
        }

        this.DetermineMultiplePrices(result.Variants);
        _QuickShop_Class.Hide();
        DoDefault();

        var obj=$get(this.Bubble_ImageID);
        var varNameobj = $get(this.Bubble_VariantNameID);
        // if the product is a Makeup product then show the first 
        // product swatch in the product imgage spot
        // add the Variant's Name under the image
        if (this.IsMakeupProduct) {
            // set the variant product image for the first variant
            if (obj!=null) {
                obj.src=this.Bubble_ImagePrefix_MediumShade + result.Variants[0].SKU + this.Bubble_ImageSuffix_MediumShade;
            }
            
            if (varNameobj != null)
                varNameobj.innerHTML = result.Variants[0].Name;  
        }else{
            // show the product image
            // blank out the variant name just in case
            if (obj!=null) {
                obj.src=this.Bubble_ImagePrefix_Product_Medium + this.Code + this.Bubble_ImageSuffix_Product_Medium;
                if (varNameobj != null)
                    varNameobj.innerHTML = "";
            }
        }

        var prodnameobj=$get(this.Bubble_ProductNameID);
        var prodnameobj2=$get(this.Bubble_ProductNameID2);
      
        var priceobj=$get(this.Bubble_PriceID);
        var dropdownlistObj=$get(this.Bubble_LayerDropDownListID);
        var productBubbleSmShadesObj =$get(this.ProductBubble_Small_ShadesID);
        var productdescrobj=$get(this.Bubble_ProductDescriptionID);
        var prodInfo = $get(this.ProductBubble_ProductInfoID);
        if (prodInfo!=null) {
          prodInfo.style.display = "block";
        }
        var confirmMsg = $get(this.ProductBubble_FavConfirmID);
        if (confirmMsg!=null) {
          confirmMsg.innerHTML='';
        }
        
        if (priceobj!=null) {
            //priceobj.innerHTML="$ " + result.MainPrice;
            if (this.DistinctPrice!=0) { //means same price variants
                priceobj.innerHTML="$ " + this.DistinctPrice;
            }
            else { //means multiple prices
                priceobj.innerHTML=""; 
            }
            //
            if(prodnameobj!=null) {
               
                prodnameobj.innerHTML=result.Name;
            }
            //
            if(prodnameobj2!=null) {
                prodnameobj2.innerHTML=result.Name;
            }
            //
            if (productdescrobj!=null) {
               productdescrobj.innerHTML=result.Description;
            }
            //
            var labelObj=$get( this.SelectShadeLabel);
            //
            var obj1=$get(this.DropDownShadeLabel);
            //
            var obj2=$get(this.DropDownSizeLabel);
           
            if (productBubbleSmShadesObj!=null) { //products with shades
                if (this.IsMakeupProduct) {
                    
                    if (labelObj!=null) {
                      labelObj.style.display="";
                    }
                    if (obj1!=null) {
                      obj1.style.display="";
                    }
                    if (obj2!=null) {
                      obj2.style.display="none";
                    }
                    
                     productBubbleSmShadesObj.innerHTML=this.GetShadeTableString(result,true);//'Makeup shades go here';
                     productBubbleSmShadesObj.style.display="";
             }
                else { //products with no shades
              
                     if (labelObj!=null) {
                      labelObj.style.display="none";
                     }
                       if (obj1!=null) {
                      obj1.style.display="none";
                    }
                     if (obj2!=null) {
                      obj2.style.display="";
                    }
                    productBubbleSmShadesObj.innerHTML="";
                    productBubbleSmShadesObj.style.display="none";
                }
            }
            
            if (dropdownlistObj!=null) {
                if (result.Variants!=null) {
                    var hasuniqueprices=false;
                    if (this.DistinctPrice!=0) {
                        hasuniqueprices=true;
                    }
                    dropdownlistObj.innerHTML=GenerateDropDownVariants(result.Variants,this.Bubble_DropDownListID,hasuniqueprices,this.ShowPriceOnDropDown,'_ProductBubble_Class.SelectItem();');
                    if (this.ContainsOneEmptyTextVariant()) { //hide if one empty variant with text=""
                       dropdownlistObj.style.visibility='hidden';
                       //hide labels for size and shade name
                        if (obj1!=null) {
                         obj1.style.display="none"; //shade name
                       }
                        if (obj2!=null) {
                          obj2.style.display="none"; //size
                        }
                    
                    }
                    else {
                    dropdownlistObj.style.visibility='visible'; //show the layer of the drop down
                    }
                    //dropdownlistObj.style.display='block';
                }
                else {
                    dropdownlistObj.style.visibility='hidden';
                    dropdownlistObj.style.display='none';
                }
            }
             var viewmoredetailsobj=$get(this.VIEWMOREDETAILS_ID);
             if(viewmoredetailsobj!=null) {
               
                 //var strviewmoredetails=viewmoredetailsobj.innerHTML;
                 var strviewmoredetails=AJAX_BUBBLE_PRODUCT_VIEWDETAIL_TEMPLATE;
                 // url rewriting determination
                 var _urlrewritten=""
                 if (result.URLRewrittenHomePage) {
                    if (result.URLRewrittenHomePage!="") {
                      //on this case override the actual url with urlrewriting.
                       strviewmoredetails=AJAX_BUBBLE_PRODUCT_VIEWDETAIL_TEMPLATE_URL_REWRITTEN;
                       _urlrewritten=result.URLRewrittenHomePage;
                    }
                 }
                 //
                 if (this.VIEWMOREDETAILS_INNERHTML_TEMPLATE=="") {
                    this.VIEWMOREDETAILS_INNERHTML_TEMPLATE=strviewmoredetails;//preserve for future clicks
                 }
                 else {
                     strviewmoredetails=this.VIEWMOREDETAILS_INNERHTML_TEMPLATE;
                 }
                  strviewmoredetails=strviewmoredetails.replace("$$$AJAX_ParentProductCode$$$",this.Code);
                  strviewmoredetails=strviewmoredetails.replace("$$$AJAX_ProductCategoryCode$$$",result.CategoryPath);
                  strviewmoredetails=strviewmoredetails.replace("$$$AJAX_ProductRelativePath$$$",this.GetRelativePath(result.CategoryHomePage));
                  // url rewriting replacement
                  if (_urlrewritten!="") {
                     strviewmoredetails=strviewmoredetails.replace("$$$AJAX_ProductURLRewrittenHomePage$$$",_urlrewritten);
                  }
                  //
                  viewmoredetailsobj.innerHTML= strviewmoredetails.toString();
               }
              //Populate some of the LastShoppingCartItem object properties, be sure to handle the price upon the addtobag item
              _LastShoppingCartItem.PopulateData("","",this.Code,result.Name,this.DistinctPrice);
              //report coremetrics for the product
              //save category name and code for the shades of product if clicked
              this.CategoryCode=result.CategoryCode;
              this.CategoryName=result.CategoryName;
              this.ProductName=result.Name;
              try {
                  _CoreAjaxCoremetrics.CreateProductViewTag(this.Code,result.Name,result.CategoryCode,result.CategoryName);
              }
              catch (err) {  }   
           // if (this.DistinctPrice==0){
                    this.SelectItem();//set the first item as selected
           // }
            //MM_showHideLayers( this.Bubble_DivID,'','show','QuickLook'); //????
             $get(this.Bubble_DivID).style.visibility='visible'
            _CoreModalPopUp._PopupControlID=this.Bubble_DivID;
            _CoreModalPopUp.ShowModal();
            
             this.ResetQuantity(); //reset qty to one if reviously selected 2,3
           
        }
    }

    /**
     * determines if all variants has the same exact price or a diffrent one. It will be needed the way
     * variants are displayed
     * @param {object} _Variants the data that comes into a JASON format from a web service
     */
    this.DetermineMultiplePrices=function(_Variants) {
        this.DistinctPrice=0;
        this.HasMultiplePrices=false;
        var ComparePrice =-1;

        for(var i=0; i<_Variants.length; i++){
            if(_Variants[i].MainPrice !=ComparePrice &&  i > 0) {
                this.HasMultiplePrices=true;
                break;
            }
            ComparePrice=_Variants[i].MainPrice;
        }

        if (!this.HasMultiplePrices) {
            this.DistinctPrice=ComparePrice;
        }
    }

    /**
     * it manages to build up the shade table
     * @param {object} ProductObject the data that comes into a JASON format from a web service
     */
    this.DisplayShadeTable=function(ProductObject) {
        if (ProductObject.Result!=null  && ProductObject.Result.Variants!=null) {
            // Show Modal Popup?
            /*
            if (this.PopUp != null)
            {
                this.PopUp._PopupControlID = this.Variants_Main_All_Thumbnails;
                this.PopUp.ShowModal();
            }
             */
            var innerHTMlString = this.GetShadeTableString(ProductObject.Result,false);
           // var obj = $get(this.Variants_Main_All_Thumbnails);
           var obj = $get(this.Variants_ThumbnailDivID);
           
            if (obj!=null) {
                //alert(innerHTMlString);
                obj.innerHTML=innerHTMlString; 
            }
            var prodnameobj2=$get(this.Bubble_ProductNameID2);

            if(prodnameobj2!=null) {
                prodnameobj2.innerHTML= ProductObject.Result.Name;
            }
            //href
            var viewmoredetailsobj=$get(this.VIEWMOREDETAILS2_ID);
             if(viewmoredetailsobj!=null) {
       
                 //var strviewmoredetails=viewmoredetailsobj.innerHTML;
                 var strviewmoredetails=AJAX_BUBBLE_PRODUCTTHUMBNAIL_VIEWDETAIL_TEMPLATE;
                   // url rewriting determination
                 var _urlrewritten=""
                 if (ProductObject.Result.URLRewrittenHomePage) {
                    if (ProductObject.Result.URLRewrittenHomePage!="") {
                      //on this case override the actual url with urlrewriting.
                       strviewmoredetails=AJAX_BUBBLE_PRODUCTTHUMBNAIL_VIEWDETAIL_TEMPLATE_URL_REWRITTEN;
                       _urlrewritten=ProductObject.Result.URLRewrittenHomePage;
                    }
                 }
                 //
                 if (this.VIEWMOREDETAILS_INNERHTML_TEMPLATE2=="") {
                    this.VIEWMOREDETAILS_INNERHTML_TEMPLATE2=strviewmoredetails;//preserve for future clicks
                 }
                 else {
                     strviewmoredetails=this.VIEWMOREDETAILS_INNERHTML_TEMPLATE2;
                 }
                  strviewmoredetails=strviewmoredetails.replace("$$$AJAX_ParentProductCode$$$",this.Code);
                  strviewmoredetails=strviewmoredetails.replace("$$$AJAX_ProductCategoryCode$$$",ProductObject.Result.CategoryPath);
                  strviewmoredetails=strviewmoredetails.replace("$$$AJAX_ProductRelativePath$$$",this.GetRelativePath(ProductObject.Result.CategoryHomePage));
                  // url rewriting replacement
                  if (_urlrewritten!="") {
                     strviewmoredetails=strviewmoredetails.replace("$$$AJAX_ProductURLRewrittenHomePage$$$",_urlrewritten);
                  }
                  //
                  viewmoredetailsobj.innerHTML= strviewmoredetails.toString();
             }
            //coremetrics for product view
              this.CategoryCode=ProductObject.Result.CategoryCode;
              this.CategoryName=ProductObject.Result.CategoryName;
              this.ProductName=ProductObject.Result.Name;
              try {
                  _CoreAjaxCoremetrics.CreateProductViewTag(this.Code,ProductObject.Result.Name,ProductObject.Result.CategoryCode,ProductObject.Result.CategoryName);
              }
              catch (err) {  }  
            
            //
            this.ShowShades();
        }
    }
    
    
     /**
     * builds path for product details page from category page
     * @path {string} 
     */
    this.GetRelativePath=function(path) {
       var rel_path=path;
       var path_array=path.split("/");
       if (path_array[path_array.length-1].indexOf(".") != -1){
         rel_path=rel_path.replace(path_array[path_array.length-1],"")
       }
       return rel_path
    }
    /**
     * it manages to build up the string of the shade table
     * please be aware that this method uses the javascript
     * string builder class to improve the performance vs the regular string concatination
     * @param {object} result the data that comes into a JASON format from a web service
     * @param {bool} SmallShadesWanted true or false, if true, we build the thumbnails
     */
    this.GetShadeTableString=function(result,SmallShadesWanted) {
        if (result!=null  && result.Variants!=null) {
            var VariantsToBeDisplayed=result.Variants;
            var CurrentRowNumber=0;
            var CurrentCellInCurrentRow=0;
            var sb = new StringBuilder();
            var HasShadeSubGroup=false;
            var StartSubGroupConst='$#Begin#$';
            var PreviousSubGroupValue=StartSubGroupConst;
              var swatchW;
              var swatchH;
              if (SmallShadesWanted) {
                    swatchW=VARIANT_SMALL_SHADE_WIDTH;
                    swatchH=VARIANT_SMALL_SHADE_HEIGHT;
              }
              else {
              
                    swatchW=VARIANT_MEDIUM_SHADE_WIDTH;
                    swatchH=VARIANT_MEDIUM_SHADE_HEIGHT;
              }
            
            //alert(VariantsToBeDisplayed.Properties);
            if (typeof(SHADE_SUB_GROUP_FLD)!='undefined' || SHADE_SUB_GROUP_FLD!='') {
                   HasShadeSubGroup=true;
                   sb.append("<table border=0 cellspacing=1 cellpadding=1 width='100%'><tr><td colspan='2'><div class='BL_pink1px'></div></td></tr><tr><td  valign=\"top\" align=\"left\" width=\"50\"  style=\"padding-left: 10px; padding-top: 10px; padding-right: 50px;\">");
            }
            else {
                    sb.append("<table border=0 cellspacing=1 cellpadding=1><tr>");
            }
           
            var filter= this.FilterVariantList; //
            for(var i=0; i<VariantsToBeDisplayed.length; i++) {
            // if ((filter=='') || (filter.indexOf(VariantsToBeDisplayed[i].SKU)) !=-1)) {
              if (filter=='' || filter.indexOf(VariantsToBeDisplayed[i].SKU)!=-1) {
               if (HasShadeSubGroup==true) {
              //subgrouping get value
               var currenSubGroupValue="";
               if (VariantsToBeDisplayed[i].Properties!=null) {
                    var _Properties=VariantsToBeDisplayed[i].Properties;
                    for(var j=0; j<_Properties.length; j++) {
                        //alert(_Properties[j].Name);
                        //alert(_Properties[j].Value);
                        if (_Properties[j].Name.toLowerCase()==SHADE_SUB_GROUP_FLD.toLowerCase()) {
                          currenSubGroupValue=_Properties[j].Value;
                          //alert( currenSubGroupValue);
                          }
                    }
                }

                //subgrouping build table
                 if (PreviousSubGroupValue!=currenSubGroupValue && HasShadeSubGroup==true) {
                        if (PreviousSubGroupValue!=StartSubGroupConst) { //close subgrouping
                            if (CurrentRowNumber>0 && CurrentCellInCurrentRow<this.RowSize) {
                                for(var k=CurrentCellInCurrentRow; k<this.RowSize; k++)
                                {
                                    sb.append("<td><img src=\"" + SPACER_IMAGE + "\"" + " width=\"" + swatchW + "\" height=\"" +swatchH + "\" border=\"0\"></td>");
                                   
                                }
                             }
                            //sb.append("</tr></table>11</div></td></tr></table></div>" );
                            sb.append("</tr></table></div></td></tr><tr><td colspan='2'><div class='BL_pink1px'></div></td></tr><td valign=\"top\" align=\"left\" width=\"50\" style=\"padding-left: 10px; padding-top: 10px; padding-right: 50px;\">" );
                        }
                       // sb.append("<table border=0 cellspacing=1 cellpadding=1><tr height=\"1px\"><td  colspan=\"2\"><hr class=\"BL_pink1px\"></td></tr><tr><td width=\"29%\" class=\"Adrkpink10pxR\" >" );
                       // sb.append("<div class=\"BL_pink1px\"><table border=1 cellspacing=1 cellpadding=1><tr><td width=\"29%\" class=\"Adrkpink10pxR\" >" );
                       sb.append("<div style='margin-left:0px' class=\"Adrkpink10pxR\" >" );
                      
                        sb.append(currenSubGroupValue);
                        sb.append("</div></td><td align=\"left\" style=\"padding-right: 20px;\">" );
                        sb.append("<div class=\"Adrkpink10pxR\"><table border=0 cellspacing=1 cellpadding=1><tr>");
                        CurrentRowNumber+=1;
                        CurrentCellInCurrentRow=0;
                        PreviousSubGroupValue=currenSubGroupValue;
                
                    }
                 }
               
                //CurrentCellInCurrentRow = i -  CurrentRowNumber * this.RowSize - this.CurrentIndex;
               
                if (CurrentCellInCurrentRow >= this.RowSize ) {
                    sb.append("</tr><tr>");
                    CurrentRowNumber+=1;
                    CurrentCellInCurrentRow=0;
                }
            
                if (SmallShadesWanted) {
                   // sb.append("<td><img id='A_" + VariantsToBeDisplayed[i].SKU +"' src='" + this.Bubble_ImagePrefix_SmallShade + VariantsToBeDisplayed[i].SKU +  this.Bubble_ImageSuffix_SmallShade + "' onclick=\"javascript:SetDropDownItemSelected('" + this.Bubble_DropDownListID + "','" + VariantsToBeDisplayed[i].SKU +"');\" style=\"cursor:pointer\" ></td>");
                   // sb.append("<td><img id='A_" + VariantsToBeDisplayed[i].SKU +"' src='" + this.Bubble_ImagePrefix_SmallShade + VariantsToBeDisplayed[i].SKU +  this.Bubble_ImageSuffix_SmallShade + "' onclick=\"javascript:SetDropDownItemSelected('" + this.Bubble_DropDownListID + "','" + VariantsToBeDisplayed[i].SKU +"');\" style=\"cursor:pointer\""  + " width=\"" + swatchW + "\"  height=\"" +swatchH + "\"></td>");
                   sb.append("<td>");
                   sb.append("<img id='SM_" + VariantsToBeDisplayed[i].SKU +"' src='" + this.Bubble_ImagePrefix_SmallShade + VariantsToBeDisplayed[i].SKU +  this.Bubble_ImageSuffix_SmallShade + "' onclick=\"javascript:_ProductBubble_Class.getswapimagesrc(this,'on');_ProductBubble_Class.SetVariantDropDownItemSelected('" + this.Bubble_DropDownListID + "','" + VariantsToBeDisplayed[i].SKU + "');_ProductBubble_Class.SetVariantImageandName('" + VariantsToBeDisplayed[i].SKU + "', _ProductBubble_Class.GetSelectedItemText());_ProductBubble_Class.ManageStock(" + VariantsToBeDisplayed[i].StockWeb.toString() + ");\" style=\"cursor:pointer\""  + " width=\"" + swatchW + "\"  height=\"" +swatchH + "\"" + "alt=\"" + VariantsToBeDisplayed[i].Name + "\">");
                   sb.append("</td>");           
                }
                else {
                     // sb.append("<td><img id='A_" + VariantsToBeDisplayed[i].SKU +"' src='" +  this.Bubble_Thumbnail_ImagePrefix + VariantsToBeDisplayed[i].SKU +  this.Bubble_Thumbnail_ImageSuffix + "'       onmouseover=\"javascript:_QuickShop_Class.ShowByObjectPosition(this,'" + VariantsToBeDisplayed[i].SKU +"',true,5,5);\" style=\"cursor:pointer;\"  width=\"100\" height=\"100\"></td>");
                     // sb.append("<td><img id='A_" + VariantsToBeDisplayed[i].SKU +"' src='" +  this.Bubble_ImagePrefix_MediumShade + VariantsToBeDisplayed[i].SKU +  this.Bubble_ImageSuffix_MediumShade + "'       onmouseover=\"javascript:_QuickShop_Class.ShowByObjectPosition(this,'" + VariantsToBeDisplayed[i].SKU +"',true,5,5);\" style=\"cursor:pointer;\""  + " width=\"" + swatchW + "\"  height=\"" +swatchH + "\"></td>");
                     sb.append("<td valign=\"top\">");
                     if (VariantsToBeDisplayed[i].RecommendedByDiag == true)
                     {
                         sb.append("<div align=\"center\"><img src=\"" + DIAG_RECOMMENDATION_IMAGE + "\" width=\"" + DIAG_RECOMMENDATION_IMAGE_WIDTH + "\" height=\"" + DIAG_RECOMMENDATION_IMAGE_HEIGHT + "\" border=\"0\" alt=\"" + DIAG_RECOMMENDATION_IMAGE_ALT + "\" /></div>");
                     }
                     else
                     {
                         sb.append("<div align=\"center\"><img src=\"" + SPACER_IMAGE + "\"" + " width=\"" + DIAG_RECOMMENDATION_IMAGE_WIDTH + "\" height=\"" +DIAG_RECOMMENDATION_IMAGE_HEIGHT + "\" border=\"0\"></div>");
                     }
                     sb.append("<img id='A_" + VariantsToBeDisplayed[i].SKU +"' src='" +  this.Bubble_ImagePrefix_MediumShade + VariantsToBeDisplayed[i].SKU +  this.Bubble_ImageSuffix_MediumShade + "'       onmouseover=\"javascript:_QuickShop_Class.parentControlID='" + this.Variants_Main_All_Thumbnails + "';_QuickShop_Class.ShowIcon(this,'" + VariantsToBeDisplayed[i].SKU +"',true,5,5,true," +  VariantsToBeDisplayed[i].StockWeb.toString() + ");\" style=\"cursor:pointer;\""  + " width=\"" + swatchW + "\"  height=\"" +swatchH + "\"" + "alt=\"" + VariantsToBeDisplayed[i].Name + "\"><div align=\"center\" class=\"Ablack9pxRLH\">" + VariantsToBeDisplayed[i].Name  + "</div>");
                     sb.append("</td>");
                }
                 CurrentCellInCurrentRow+=1;
             }
            }
             //end of for loop
             if (CurrentRowNumber>0 && CurrentCellInCurrentRow<this.RowSize) {
                    for(var i=CurrentCellInCurrentRow; i<this.RowSize; i++)
                    {
                       // sb.append("<td>&nbsp;</td>");
                       sb.append("<td><img src=\"" + SPACER_IMAGE + "\"" + " width=\"" + swatchW + "\" height=\"" +swatchH + "\" border=\"0\"></td>");
                                   
                    }
             }
             //
             sb.append("</tr></table>");
             
             //
             if (HasShadeSubGroup) {
                sb.append("</div></td></tr></table></div></td></tr></table>" );
             }
             if (CurrentRowNumber>5) {
               _CoreModalPopUp._IsforegroundElementLarge=true;
             }
             else {
               _CoreModalPopUp._IsforegroundElementLarge=false;
             }
             
            //alert(sb.toString());
            return sb.toString();
        }
        return "";
    }

    /**
     * set the shade table visible
     */
    this.ShowShades=function () {
        var obj= $get(this.Variants_Main_All_Thumbnails);
        
        if (obj!=null) {
            obj.style.visibility='visible';
            _CoreModalPopUp._IsforegroundElementLarge=true;
            _CoreModalPopUp._PopupControlID=this.Variants_Main_All_Thumbnails;
            _CoreModalPopUp.ShowModal();

            var scrollLeft = (document.documentElement.scrollLeft ? document.documentElement.scrollLeft : document.body.scrollLeft);
            var scrollTop = (document.documentElement.scrollTop ? document.documentElement.scrollTop : document.body.scrollTop);
            scrollLeft=scrollLeft+(document.documentElement.offsetWidth-obj.children[0].offsetWidth)/2;
            scrollTop=(document.documentElement.offsetHeight-obj.children[0].offsetHeight)/2;
            
            obj.style.visibility='visible';
            obj.style.top=scrollTop + "px";
            obj.style.left=scrollLeft +"px";
            // obj.style.top=this.tempY + "px";
            // obj.style.left=this.tempX +"px";
        }
    }

    /**
     * hides shades/variants
     */
    this.HideShades=function() {
        var obj= $get(this.Variants_Main_All_Thumbnails);
        if (obj!=null) {
            obj.style.visibility='hidden';
        }
        
        if (this.PopUp != null)
        {
            this.PopUp.Hide();
        }
        
        _QuickShop_Class.Hide();
    }

    /**
     * saves the current cursor coordinates when clicked on a particular link
     * needed when we want to display the bubble relative with cursor position clicked
     */
    this.LockCoordinates=function() {
        this.tempX=GetMouseCoordinateX();
        this.tempY=GetMouseCoordinateY();
    }

     /**
     * returns the current variant code from the drop down.
     * 
     */
    this.GetSelectedVariantCode=function() {
     
         var ItemCode="";
             ItemCode=GetSelectedValue(this.Bubble_DropDownListID);
           if(ItemCode!=null) {
               if(ItemCode!="") {
                   if (ItemCode.indexOf("#") != -1){
                      var my_array=ItemCode.split("#");
                      itemPrice=my_array[1];
		              ItemCode=my_array[0]; 
	               }
	            }
	       }
	       return ItemCode;
     }
    /**
     * Adds an item in the bag, the function determines the selected sku and calls the webservice method
     * to add item to the bag
     */
    this.AddSingleProductToCart=function () {
         var ItemQuantity=1;
         ItemQuantity=GetSelectedValue(this.Bubble_QuantityID);
         var ItemCode="";
         var itemPrice=0;
         ItemCode=GetSelectedValue(this.Bubble_DropDownListID);
           if(ItemCode!=null) {
               if(ItemCode!="") {
                   if (ItemCode.indexOf("#") != -1){
                      var my_array=ItemCode.split("#");
                      itemPrice=my_array[1];
		              ItemCode=my_array[0]; 
	    	          
	    	          //alert(itemPrice);
		              //alert(ItemCode);
	               }
	            }
	       }
	      var variantName=GetSelectedText(this.Bubble_DropDownListID);
          //alert(ItemCode);
          MM_showHideLayers(this.Bubble_DivID,'','hide') 
          //set shopping cart last item properties
          _LastShoppingCartItem.ItemQuantity=ItemQuantity; //save the quantity for later retrival
          _LastShoppingCartItem.ItemCode=ItemCode;         //save variant code
          _LastShoppingCartItem.ItemPrice=0;
          _LastShoppingCartItem.ItemName=variantName;
          if (itemPrice!=0) {
              _LastShoppingCartItem.ItemPrice=itemPrice; 
          }
       // hide modal
        _CoreModalPopUp.Hide();
        //adds the var code to cookie to determine for coremetrics on checkout coming from quick shop
        CoreAjaxCookie_AddVariant(ItemCode);
        //call web service methods
        _WebServiceAPI.AddSingleProductToCart (GetCurrentCustomerID(),ItemCode,ItemQuantity,_ShoppingCartBubble_Class.AddSingleProductToCartResultHandler)
    }
}

/**
 * It registers the ProductBubble_Class using registerClass method of MS AJAX Library
 */
 if (IsTypeDefined) { Core.ProductBubble_Class.registerClass('Core.ProductBubble_Class'); }



/**
 * @class ProductBubble_Class
 * This class handles operation with shopping cart like add to baga, retrive shopping cart, display etc..
 * for more details, look at its method
 * P.S: This class has not been quite finished as it needs some more methods in order to hanadle most of our needs
 * @constructor 
 */
 Core.ShoppingCartBubble_Class=function () {
    //Properties
     /**
     *  The main dhtml layer for the shopping cart
     */
    this.ShoppingCartBubble_DivID='ShoppingCartBubble_Div';
    //IDS
    /**
     *  A dhtml layer where subtotal will be displayed
     */
    this.ShoppingCartBubble_SubTotalID='ShoppingCartBubble_SubTotal';
     /**
     *  A dhtml layer where subtotal will be displayed on the header outside of the bubble
     */
   this.ShoppingCartBubble_SubTotalID_Header='ShoppingCartBubble_SubTotal_header';
    /**
     *  A dhtml layer where total will be displayed
     */
    this.ShoppingCartBubble_TotalID='ShoppingCartBubble_Total';
    /**
     *  A dhtml layer where tax will be displayed
     */
    this.ShoppingCartBubble_TaxTotalID='ShoppingCartBubble_TaxTotal';
    /**
     *  A dhtml layer where shipping subtotal will be displayed
     */
    this.ShoppingCartBubble_ShippingSubTotalID='ShoppingCartBubble_ShippingSubTotal';
    //
    /**
     * A dhtml layer where total items will be displayed
     */
    this.ShoppingCartBubble_TotalItemsID='ShoppingCartBubble_TotalItems'
    /**
     * A dhtml layer where total items will be displayed outside of the bubble
     */
    this.ShoppingCartBubble_TotalItemsID_Header_Outside='ShoppingCartBubble_TotalItems_header'
    /**
     *  success layer, not used yet
     */
    this.ShoppingCartBubble_SuccessID='ShoppingCartBubble_Success';
    /**
     *  failure layer not used yet
     */
    this.ShoppingCartBubble_FailureID='ShoppingCartBubble_Failure';

 
    /**
     * It holds the DHTML Object ID for product Name of last item added
     */
    this.ShoppingCartBubble_ProductNameID="ShoppingCartBubble_ProductName";  
     /**
     * It holds the DHTML Object ID for product Image of last item added
     */
    this.ShoppingCartBubble_ProductImageID="ShoppingCartBubble_ProductImage";  
    /**
     * It holds the DHTML Object ID for Variant Name of last item added
     */
    this.ShoppingCartBubble_VariantNameID="ShoppingCartBubble_VariantName";  
    /**
     * It holds the DHTML Object ID for item unit price of last item added
     */
    this.ShoppingCartBubble_ItemPriceID="ShoppingCartBubble_ItemPrice";      
    /**
     * It holds the DHTML Object ID for item quantity of last item added
     */
    this.ShoppingCartBubble_ItemQuantityID="ShoppingCartBubble_ItemQuantity"; 
    /**
     * It holds the DHTML Object ID for last item total example: UnitPrice * Quantity
     */
    this.ShoppingCartBubble_LastItemTotalAmountID="ShoppingCartBubble_LastItemTotalAmount";
    
    /**
     *
     * Events
     */
     /**
     * the name of the function to be called before the popup opens
     */
    this.beforeOpen=null; 
    
    /**
     * the name of the function to be called before the popup closes
     */
    this.beforeClose=null;
    /**
     * Handles the callback from the web service AddSingleProductToCart
     * @param {object} result the data that comes into a JASON format from a web service
     */
    this.AddSingleProductToCartResultHandler=function(result)  {
          DoDefault();
        if (result != null) {
            if (result.ActivityStatus==true) { 
                //Display The Shopping Cart
                //var _WebServiceAPI=new  WebServiceAPI_Class();
                _WebServiceAPI.RetrieveShoppingCart(GetCurrentCustomerID(),_ShoppingCartBubble_Class.RetrieveShoppingCartResultHandler);
            }
            else  {
                       if (result.ErrorString.indexOf('The maximum amount of the shopping cart is reach')!=-1 &&  result.ErrorString.indexOf(':')!=-1) {
                        var error_array=result.ErrorString.split(':');
                        error_array[0]='The total amount of your order may not exceed $';
                        alert (error_array[0] + formatAsMoney(error_array[1].replace(" ","")));
                    }
                    else {
                     alert(result.ErrorString);
                    }
              }  
         }
    }

    /**
     * Handles the callback from the web service RetrieveShoppingCartLastItems
     * @param {object} result the data that comes into a JASON format from a web service
     */
    this.RetrieveShoppingCartLastItemsResultHandler=function (result) {
        DoDefault();
        if (result != null) {
            _ShoppingCartBubble_Class.DisplayShoppingCartAndLastItems(result);
        }
    }

    /**
     * Displays the shopping and last items
     */
    this.DisplayShoppingCartAndLastItems=function() {
        alert('this method is not finished yet, it is in progress');
        this.Show();
    }

    /**
     * Handles the callback from the web service RetrieveShoppingCart
     * @param {object} result the data that comes into a JASON format from a web service
     */
    this.RetrieveShoppingCartResultHandler=function (result) {
        DoDefault();
        if (result != null) {
            _ShoppingCartBubble_Class.DisplayShoppingCart(result);
        }
    }

    /**
     * Displays the shopping cart information
     * @param {object} result the data that comes into a JASON format from a web service
     */
    this.DisplayShoppingCart=function(result) {
        DoDefault();
        //display subtotal
        if ($get(this.ShoppingCartBubble_SubTotalID)!=null) {
            $get(this.ShoppingCartBubble_SubTotalID).innerHTML=result.SubTotal.toFixed(2);;
        }
        //populate header subtotal
        var obj_h=$get(this.ShoppingCartBubble_SubTotalID_Header);
        
        if (obj_h!=null) {
            obj_h.innerHTML=result.SubTotal.toFixed(2);
            obj_h.innerHTML="$" + obj_h.innerHTML;
        }
         
        //display total amount
        if ($get(this.ShoppingCartBubble_TotalID)!=null) {
            $get(this.ShoppingCartBubble_TotalID).innerHTML=result.Total.toFixed(2);
        }
        //display tax 
        if ($get(this.ShoppingCartBubble_TaxTotalID)!=null) {
            $get(this.ShoppingCartBubble_TaxTotalID).innerHTML=result.TaxTotal.toFixed(2);
        }
        //display shipping cost
        if ($get(this.ShoppingCartBubble_ShippingSubTotalID)!=null) {
         $get(this.ShoppingCartBubble_ShippingSubTotalID).innerHTML=result.ShippingSubTotal.toFixed(2);
        
        }
        //total items within bubble
        if ($get(this.ShoppingCartBubble_TotalItemsID)!=null) {
            $get(this.ShoppingCartBubble_TotalItemsID).innerHTML=result.Quantity;
        }
        //updating total items outside of bubble like header
         if ($get(this.ShoppingCartBubble_TotalItemsID_Header_Outside)!=null) {
            $get(this.ShoppingCartBubble_TotalItemsID_Header_Outside).innerHTML=result.Quantity;
        }
         this.DisplayShoppingCartLastItem(); //new
         this.Show();
    }

   /**
     * Displays the shopping cart information
     */
    this.DisplayShoppingCartLastItem=function() { //new method
        //product name
       if ($get(this.ShoppingCartBubble_ProductNameID)!=null) {
            $get(this.ShoppingCartBubble_ProductNameID).innerHTML=  _LastShoppingCartItem.ItemParentName;
        }
        
        var objimage=$get(this.ShoppingCartBubble_ProductImageID);
        if (objimage!=null) {
         objimage.src=IMAGES_RELATIVE_OR_ABSOLUTE_PATH + PRODUCT_SMALL_IMAGE_PREFIX  + _LastShoppingCartItem.ItemParentCode +  PRODUCT_SMALL_IMAGE_SUFFIX;
        }
        //variant name
        if ($get(this.ShoppingCartBubble_VariantNameID)!=null) {
            $get(this.ShoppingCartBubble_VariantNameID).innerHTML=  _LastShoppingCartItem.ItemName;
        }
        //variant price
        if ($get(this.ShoppingCartBubble_ItemPriceID)!=null) {
               $get(this.ShoppingCartBubble_ItemPriceID).innerHTML=  _LastShoppingCartItem.ItemPrice;//.toFixed(2);
        }
        //variant quantity
        if ($get( this.ShoppingCartBubble_ItemQuantityID)!=null) {
               $get( this.ShoppingCartBubble_ItemQuantityID).innerHTML=  _LastShoppingCartItem.ItemQuantity;
        }
     
        //total item for last item quantity * price
        if ($get( this.ShoppingCartBubble_LastItemTotalAmountID)!=null) {
                var _ItemTotalAmount=0
                _ItemTotalAmount=parseInt(_LastShoppingCartItem.ItemQuantity) * _LastShoppingCartItem.ItemPrice;
               $get( this.ShoppingCartBubble_LastItemTotalAmountID).innerHTML=  _ItemTotalAmount.toFixed(2);
        }
    
    
    }
    /**
     * Displays the shopping cart bubble
     */
    this.Show=function() {
        var obj=$get(this.ShoppingCartBubble_DivID);
        obj.style.visibility='visible';
        obj.style.display='';
        // slideContent(this.ShoppingCartBubble_DivID.toString(),10);
          if (this.beforeOpen!=null) {
             eval(this.beforeOpen + "();");
        
        }
    }

    /**
     * Hides the shopping cart bubble
     */
    this.Hide=function() {
        var obj=$get(this.ShoppingCartBubble_DivID);
        obj.style.visibility='hidden';
         obj.style.display='none';
        _QuickShop_Class.Hide();
        if (this.beforeClose!=null) {
             eval(this.beforeClose + "();");
        
        }
    }
}

 /**
 * It registers the ShoppingCartBubble_Class using registerClass method of MS AJAX Library
 */
 if (IsTypeDefined) { Core.ShoppingCartBubble_Class.registerClass('Core.ShoppingCartBubble_Class'); }

/**
 * @class ShoppingCartItem_Class
 * This class stores the information of the last item added to bag
 * @constructor 
 */
 Core.ShoppingCartItem_Class=function () {
    /**
     * Variant code of the item added to shopping cart
     */    
    this.ItemCode="";
    /**
     * Variant name
     */ 
    this.ItemName="";
    /**
     * Product code(parent product code of the variant)
     */ 
    this.ItemParentCode="";
    /**
     * Product Name(parent product name of the variant)
     */ 
    this.ItemParentName="";
    /**
     * quantity of the last add to bag
     */ 
    this.ItemQuantity=1;
    /**
     * item unit price
     */ 
    this.ItemPrice=0;
    
    /**
     * Populates the major data of the object
     @param {_ItemCode,_ItemName,_ItemParentCode,_ItemParentName,_ItemPrice} 
     */ 
    this.PopulateData=function(_ItemCode,_ItemName,_ItemParentCode,_ItemParentName,_ItemPrice){
                this.ItemCode=_ItemCode;
                this.ItemName=_ItemName;
                this.ItemParentCode=_ItemParentCode;
                this.ItemParentName=_ItemParentName;
                this.ItemPrice=_ItemPrice;
        
        }
}

/**
 * It registers the Core.ShoppingCartItem_Class using registerClass method of MS AJAX Library
 */
 if (IsTypeDefined) { Core.ShoppingCartItem_Class.registerClass('Core.ShoppingCartItem_Class'); }


/*
 *It handle the window on resize event
 */
 window.onresize =  OnResizeHandler; 
/*
 *It handle the window on scroll event
 */
  window.onscroll =  OnScrollHandler; 


/**
 * @class Product_Class
 * This class has only properties
 * Result will hold the data that comes from the webservices
 * in JSON format
 * When a product object is created, it is added in the collection by productmanager
 * with Loaded=false
 * when successful response comes from the web service, loaded is set to true
 * so next time, if the user will access the same product, and if ENABLE_PRODUCT_CACHING is
 * set to true, the data will be taken from the memory vs webservice call. This is done to improve the performance
 * and minimize the calls to the server.
 * @constructor 
 */

Core.Product_Class=function () {
    /**
     * Product Code which is prd_code in DB
     */    
    this.ProductCode="";
    /**
     *  The json object reurned via webservices
     */
    this.Result;

    /**
     * Product Name
     */
    this.Name="";

    /**
     * it is set to true if loaded and set to false otherwise.
     */
    this.Loaded=false;
}
/**
 * It registers the Product_Class using registerClass method of MS AJAX Library
 */
 if (IsTypeDefined) {Core.Product_Class.registerClass('Core.Product_Class'); }


/**
 * @class ProductManager_Class
 * This class Manages both Products and Variants
 * It adds a product/variant in the collection,
 * loads the data from webservice and caches the data locally
 * if caching is enabled for both Products and Variants
 * @constructor 
 */

 Core.ProductManager_Class=function() {
    /**
     * The collection of the products to be cached (visited previously by the user)
     */
    this.ProductCollection=new Array();
    /**
     * The collection of Variants Cached (visited previously by the user)
     */
    this.VariantCollection=new Array();
    /**
     * 0 build shade table 
     * 1 Skin Care
     */
    this.Action=0; 

    /** 
     * Holds a reference to the parent control. If this value is present,
     * when attempting to show a new bubble, this control will attempt to hide
     * the parent
     */
    this.parentControlID=null;
    
    this.UseConfirmBubble=false;
    
    this.ConfirmBubbleID="ProductConfirmFavorite_Bubble";
        
    /**
     * Adds a product to the internal product collection
     * @param {object} ProductObject The product object
     */
    this.AddProduct= function (ProductObject) {
        var exist=false;
        if (this.ProductCollection!=null) {
            for (var i=0; i<this.ProductCollection.length; i++) {
                if (this.ProductCollection[i].ProductCode==ProductObject.ProductCode) {
                    this.ProductCollection[i]=ProductObject;
                    exist=true;
                    break;
                }
            }

            if(exist==false) {
                this.ProductCollection[this.ProductCollection.length]=ProductObject;
            }
        }
    }

    /**
     * Retrieve a product to the internal product collection
     * @param {string} ProductCode The product code of the product to retrieve from the ProductCollection
     */
    this.GetProduct=function (ProductCode) {
        for (var i=0;i<this.ProductCollection.length;i++) {
            if (this.ProductCollection[i].ProductCode==ProductCode) {
                  return this.ProductCollection[i];
             }
        }
    }

    /**
     * This method below checks if a copy exist on the Memory, if it does, no need to call web service
     * @param {string} ProductCode The product code of the product to retrieve
     */
    this.LoadProduct=function (ProductCode) {
        _ProductBubble_Class.LockCoordinates();
        _ProductBubble_Class.HideShades();
        _WebServiceAPI.LoadProduct(ProductCode,true,this.OnRequestComplete);
     }

    /**
     * This method will load the product data along with any product recommendations for a diag.
     * @param {string} CurrentCustomerID The current customer ID (GUID)
     * @param {string} ProductCode Product Code(SKU)
     * @param {string} DiagCode The diagnosis code 
     * @param {string} CategoryCode The category code
     * @param {string} RetailerCode The retailer code
     * @param {string} FilterExpression The retailer code
     
     */
    this.LoadProductAndDiag=function (CurrentCustomerID, ProductCode, DiagCode, CategoryCode, RetailerCode,FilterExpression) {
        _ProductBubble_Class.LockCoordinates();
        _ProductBubble_Class.HideShades();
        _WebServiceAPI.LoadProductWithDiagnosisInformation(CurrentCustomerID, ProductCode, DiagCode, CategoryCode, RetailerCode,(typeof(FilterExpression)=='undefined')? "" : FilterExpression, this.OnRequestComplete);
   
    }

    /**
     * Loads the product thumbsnail and also retrieves the diagnosis information to see if these
     * products have been recommended to the customer
     * @param {string} RelativeObjectID The ID of the object to use for relative positioning of the new table
     * @param {int} plusTop The offset for the result object from the top of the RelativeObjectID
     * @param {int} plusLeft The offset for the result object from the left of the RelativeObjectID
     * @param {string} CurrentCustomerID The current customer ID
     * @param {string} ProductCode The product code of the product to retrieve
     * @param {string} DiagCode The diag code to use to determine if this product is recommended
     * @param {string} CategoryCode The cateogyr code 
     * @param {string} RetailerCode The retailer code
     * @param {string} FilterExpression filter criteria
     
     */
    this.LoadProductThumbnailsWithDiag=function(RelativeObjectID, plusTop, plusLeft, CurrentCustomerID, ProductCode, DiagCode, CategoryCode, RetailerCode,FilterExpression) {
        this.Action=0;
        if (DiagCode == null)
        {
            if (typeof(FilterExpression)=='undefined' || FilterExpression=="") {
                this.LoadProduct(ProductCode);
            }
            else {
            
                this.LoadProductFilterVariants(ProductCode,FilterExpression);
            }
            
        }
        else
        {
          
            this.LoadProductAndDiag(CurrentCustomerID, ProductCode, DiagCode, CategoryCode, RetailerCode,FilterExpression);
        }
       // var relativeObject = $get(RelativeObjectID);
       // var bubble = $get(_ProductBubble_Class.Variants_Main_All_Thumbnails);
       // PositionLayerByRelativeObject(relativeObject,bubble,plusTop,plusLeft);
    }

    /**
     * Loads the product thumbsnail
     * @param {string} RelativeObjectID The ID of the object to use for relative positioning of the new table
     * @param {int} plusTop The offset for the result object from the top of the RelativeObjectID
     * @param {int} plusLeft The offset for the result object from the left of the RelativeObjectID
     * @param {string} ProductCode The product code of the product to retrieve
     */
    this.LoadProductThumbnails=function(RelativeObjectID, plusTop, plusLeft, ProductCode) {
        this.LoadProductThumbnailsWithDiag(RelativeObjectID, plusTop, plusLeft, null, ProductCode, null, null, AJAX_DEFAULT_RETAILER,"");
    }

    /**
     * TODO
     * @param {string} ProductCode The product code of the product to retrieve
     */
    this.LoadSkinCareProduct=function(ProductCode, ParentControlID) {
        this.Action=1;
        this.parentControlID = ParentControlID;
        this.LoadProduct(ProductCode);
    }

    /**
     * 
     * @param {string} ProductCode The product code of the product to retrieve
     */
    this.LoadMakeupProduct=function(ProductCode, ParentControlID) {
        this.Action=2;
        this.parentControlID = ParentControlID;
        this.LoadProduct(ProductCode);
    }
   //
   this.LoadMakeupProductFilterVariants=function(ProductCode, ParentControlID,FilterExpression) {
        this.Action=2;
        this.parentControlID = ParentControlID;
         this.LoadProductFilterVariants(ProductCode,FilterExpression);
    }
   //
   this.LoadSkinCareFilterVariants=function(ProductCode, ParentControlID,FilterExpression) {
        this.Action=1;
        this.parentControlID = ParentControlID;
        this.LoadProductFilterVariants(ProductCode,FilterExpression);
    }
   //Loads product from web services  and filter variants
   this.LoadProductFilterVariants=function (ProductCode,FilterExpression) {
        _ProductBubble_Class.LockCoordinates();
        _ProductBubble_Class.HideShades();
        _WebServiceAPI.LoadProductWithFilteredVariants(ProductCode,FilterExpression,this.OnRequestComplete);
    
    }
    /**
     * This method is called after a web Service Call is Completed
     * @param {string} result The result object returned from the web service
     */
    this.OnRequestComplete= function (result) {
        DoDefault();
        if (result != null)    {
                var  _Product=new Core.Product_Class();
                _Product.ProductCode=result.SKU;
                _Product.Result=result;
                _Product.Loaded=true;
                _ProductManager.DoBranching(_Product);
        }
    }


    /**
     * TODO
     * @param {ProductBubble_Class} _Product The product bubble
     */
    this.DoBranching=function(_Product) {
        _ProductBubble_Class.IsMakeupProduct=true;

        switch(this.Action){
            case 0 :
                //this.DisplayShadeTable(_Product);
                 _ProductBubble_Class.Code=_Product.ProductCode;
                 _ProductBubble_Class.PopUp = _CoreModalPopUp;
                _ProductBubble_Class.DisplayShadeTable(_Product);
                break;
            case 1 :
                _ProductBubble_Class.IsMakeupProduct=false;
                _ProductBubble_Class.Code=_Product.ProductCode;
                _ProductBubble_Class.LoadProductRequestComplete(_Product.Result)
                break;
            case 2 :
                _ProductBubble_Class.IsMakeupProduct=true;
                _ProductBubble_Class.Code=_Product.ProductCode;
                _ProductBubble_Class.LoadProductRequestComplete(_Product.Result)
                break;
            default :
                //this.DisplayShadeTable(_Product);
                 _ProductBubble_Class.Code=_Product.ProductCode;
                _ProductBubble_Class.DisplayShadeTable(_Product);
                break;
        }
    }


    // Variant methods:

    /**
     * Adds a variant to the VariantCollection array
     * @param {object} VariantObject The variant object
     */
    this.AddVariant= function (VariantObject) {
        var exist=false;
        if (this.VariantCollection!=null) {
            for (var i=0;i<this.VariantCollection.length;i++) {
                if (this.VariantCollection[i].ProductCode==VariantObject.ProductCode) {
                    this.VariantCollection[i]=VariantObject;
                    exist=true;
                    break;
                }
            }
            if(exist==false) {
                this.VariantCollection[this.VariantCollection.length]=VariantObject;
            }
        }
    }

    /**
     * Retrieves a variant to the VariantCollection array
     * @param {string} VariantCode The variant code to find
     */
    this.GetVariant=function (VariantCode) {
        for (var i=0;i<this.VariantCollection.length;i++) {
            if (this.VariantCollection[i].ProductCode==VariantCode) {
                return this.VariantCollection[i];
            }
        }
    }

    /**
     * Retrieves the variant either from the web service or cache (if enabled) 
     * @param {string} VariantCode The variant code to find
     */
    this.LoadVariant=function (VariantCode) {
        if (ENABLE_VARIANT_CACHING) {
            var _Variant=this.GetVariant(VariantCode)
            if ((_Variant==null) || (typeof(_Variant)=='undefined') || (_Variant.Loaded=false)){
                _Variant=new Core.Product_Class();
                _Variant.ProductCode=VariantCode;
                this.AddVariant(_Variant);
                _WebServiceAPI.LoadProduct(VariantCode,false,this.VariantOnRequestComplete)
            }
            else {
                // this.DisplayShadeTable(_Product);
                this.DoVariantBranching(_Variant);
            }
        }
        else {
            _WebServiceAPI.LoadProduct(VariantCode,false,this.VariantOnRequestComplete)
        }
    }
           
    /**
     * Callback handler from LoadVariant
     * @param {object} result The resulting product object
     */
    this.VariantOnRequestComplete = function (result) {
        DoDefault();
        if (result != null) {
            if (ENABLE_VARIANT_CACHING) {
                var _Variant=_ProductManager.GetVariant(result.SKU);//later use the productid
                _Variant.Result=result;
                _Variant.Loaded=true;
                _ProductManager.AddVariant(_Variant);
                _ProductManager.DoVariantBranching(_Variant);
            }
            else {
                var  _Variant=new Core.Product_Class();
                _Variant.ProductCode=result.SKU;
                _Variant.Result=result;
                _ProductManager.DoVariantBranching(_Variant);
            }
        }
    }

    /**
     * Do variant branching
     * @param {object} _Variant The variant object
     */
    this.DoVariantBranching=function(_Variant) {
        _VariantBubble_Class.parentControlID=this.parentControlID;    
        _VariantBubble_Class.Code=_Variant.ProductCode;
        _VariantBubble_Class.PopulateData(_Variant.Result);
    }

    /**
     * Loads a shade in a bubble
     * @param {string} VariantCode Loads the variant for display
     */
    this.LoadMakeupVariant=function(VariantCode, ParentControlID) {
        this.Action=0;
        this.parentControlID = ParentControlID;
        this.LoadVariant(VariantCode);
    }
       
      /**
     * Used to add a product to a customer's favorite list
     * @param {string} CustomerId The customer ID GUID
     * @param {int} FavoriteProductType The type of favorite list to retrieve
     * @param {string} RetailerCode The current retailer code
     * @param {string} ProductCode The product code to add to the customer's favorite list
     */
     this.AddProductToFavorites=function(FavoriteProductType, RetailerCode, ProductCode) {
       _WebServiceAPI.AddToFavorites(CurrentCustomerID, this.ConvertTypeToInteger(FavoriteProductType), RetailerCode, ProductCode, this.AddProductToFavoritesOnComplete);
     }
     
     /**
     * AddProductToFavoritesOnComplete
     * @param {object} result that comes from web service
     */
     this.AddProductToFavoritesOnComplete=function(result) {
        if (result!=null) {
            if(result==true) {
                var confirmMsgObj=null;
                var productInfoObj=null;
                var confirmMessage=null;

                if (_QuickShop_Class.FromProductBubble != true){
                    confirmMsgObj = $get(VAR_FAVORITE_CONFIRM_ID);
                    productInfoObj = $get(VAR_PRODUCT_INFO_ID);
                    confirmMessage = VAR_FAVORITE_CONFIRM_MESSAGE
                    // ADDED for DT733 to display bubble from MyTips Page as well
                    _CoreModalPopUp._PopupControlID = "ProductConfirmFavorite_Bubble";
                    _CoreModalPopUp.ShowModal();                    
                }else{
                    if(_ProductManager.UseConfirmBubble == true){
                            // use the bubble
                            _CoreModalPopUp._PopupControlID=_ProductManager.ConfirmBubbleID;
                            _CoreModalPopUp.ShowModal();
                            // reset the variable
                            _ProductManager.UseConfirmBubble = false;
                    }else{
                        confirmMsgObj = $get(PRD_FAVORITE_CONFIRM_ID);
                        productInfoObj = $get(PRD_PRODUCT_INFO_ID);                
                        confirmMessage = PRD_FAVORITE_CONFIRM_MESSAGE;
                    }
                }

                // use the inline message
                if(confirmMsgObj != null){
                    confirmMsgObj.style.display = "block";
                    confirmMsgObj.innerHTML = confirmMessage;
                }
                
                if(productInfoObj != null){
                    productInfoObj.style.display = "none";
                }
                
            }else {
                alert('Your request failed to complete. Please try again.');
            }
        }
    }
    
    // GDH 4-20-2007 changed to use the CORE values - they differ from the product types
     this.ConvertTypeToInteger=function(value) {
         switch(value){
            case 'Product':
                return 0;
                break;
            case 'Variant':
                return 0;
                break;
            default:
                return 0;
                break;
        }
     }     
//     this.ConvertTypeToInteger=function(value) {
//        switch(value){
//           case 'Product':
//                    return 1;
//                    break;
//		   case 'Variant':
//		            return 2;
//                    break;
//		  case   'Sample':
//		            return 3;
//                   break;
//		  case    'BoxSet':
//		            return 4;
//                   break;
//		  case     'Packaging':
//		           return 5;
//                   break;
//		 case      'eGift':
//		            return 6;
//                   break;
//		 case      'Document':
//		            return 7;
//                   break;
//		 case      'Message':
//		             return 8;
//                   break;
//		 case      'Flyer':
//		             return 9;
//                    break;
//       default:
//                return 1;
//                break;
//
//        }
//     }
     
}
 /**
 * It registers the  ProductManager_Class using registerClass method of MS AJAX Library
 */
 if (IsTypeDefined) { Core.ProductManager_Class.registerClass('Core.ProductManager_Class'); }

/**
 * @class Topic_Class
 * 
 * 
 * 
 * 
 * 
 */
Core.Topic_Class=function () {
    /**
     * Topic Code which is prd_code in DB
     */    
    this.TopicCode="";

    /**
     *  The json object reurned via webservices
     */
    this.Result;

    /**
     * Topic Types
     */
    this.TopicType="";

    /**
     * it is set to true if loaded and set to false otherwise.
     */
    this.Loaded=false;
}
/**
 * It registers the Topic_Class using registerClass method of MS AJAX Library
 */
 if (IsTypeDefined) {Core.Topic_Class.registerClass('Core.Topic_Class'); }


/**
 * @class Core.TopicManager_Class
 *
 * 
 * 
 * 
 * @constructor 
 */

 Core.TopicManager_Class=function() {
   
    this.tempArrayLookUp=new Array();
    this.GetTopicProductsCodes= function (TopicCode, TopicType,FilterLevel)  {
      // _WebServiceAPI.GetTopicProductsCodes(TopicCode,TopicType,this.GetTopicProductsCodesOnComplete);
       _WebServiceAPI.GetTopicProductsCodes(TopicCode,TopicType,(FilterLevel=='1') ? this.GetTopicProductsCodesOnComplete: this.GetTopicParentProductsCodesOnComplete);
    
    }
    
    /**
     * This function will return all of the topic products filtered by the root category code.
     */
    this.GetTopicProductsCodesByRootCategory = function (TopicCode, TopicType, RootCategoryCode)
    {
        _WebServiceAPI.GetTopicProductsCodesByRootCategory(TopicCode, TopicType, RootCategoryCode, this.GetTopicProductsCodesByRootCategoryOnComplete);
    }
    
    /**
     * This function will handle the results of the GetTopicProductsCodesByRootCategory function
     */
    this.GetTopicProductsCodesByRootCategoryOnComplete = function (result)  
    {
         DoDefault();     
         if (result!=null) {
            if (AJAX_IS_TOPIC_PRODUCT_SLIDER_ON) 
            {
                 var constructedData=_TopicManager.GetConstruct(result);
                 // alert(constructedData);
                 if (constructedData==null || constructedData.length==0)
                 {
                    alert ("No results for this category.");
                 }
                 else 
                 {
                  _TopicManager.GetTopicProductsCodesOnComplete(constructedData);
                }
            }
            else 
            {
                _NavigatorManager.FilteredData=result;
                _NavigatorManager.DoMainFilterInitialization(MAIN_LAYER_PARENT_CONTAINS); 
            }
         }
         else 
         { 
            alert ("No results for this category.");
         }  
    }
    
    this.GetTopicProductsCodesOnComplete= function (result)  {
        DoDefault();
         if (result!=null) {
            _NavigatorManager.FilteredData=result;
            _NavigatorManager.DoFilterInitialization(VARIANT_LAYER_PARENT_CONTAINS);
         }
         else { 
            alert ("No Results for this Filter Combination.");
         }
    }
    
   
      this.GetConstruct=function (res) {
         var constructedData=new Array();
          for (var i = 0; i < res.length ; i++) {
              res[i]=res[i].replace(":","")
          }
          for (var i = 0; i < res.length ; i++) {
          
              for (var j = 0; j < this.tempArrayLookUp.length ; j++) {
                 
                   if (this.tempArrayLookUp[j].indexOf(res[i]) !=-1) {
                          var selectedvalue_array=this.tempArrayLookUp[j].split(":");
	                      res[i]=selectedvalue_array[0] + ":" +  res[i];
	                     // alert(res[i]);
                          break;
                   }
              }
          }
          for (var i = 0; i < res.length ; i++) {
             if (res[i].indexOf(":")!=-1) {
               constructedData[constructedData.length]=res[i];
             }
            
          }
         // alert(constructedData);
          return constructedData;
       }
    
    
   this.GetTopicParentProductsCodesOnComplete= function (result)  {
         DoDefault();
         
         if (result!=null) {
            if (AJAX_IS_TOPIC_PRODUCT_SLIDER_ON) {
                 var constructedData=_TopicManager.GetConstruct(result);
                 // alert(constructedData);
                 if (constructedData==null || constructedData.length==0) {
                    alert ("No Results for this Filter Combination.");
                 }
                 else {
                  //_TopicManager.GetTopicProductsCodesOnComplete(_TopicManager.GetConstruct(result));
                  _TopicManager.GetTopicProductsCodesOnComplete(constructedData);
         
                }
            }
            else {
                 _NavigatorManager.FilteredData=result;
                 _NavigatorManager.DoMainFilterInitialization(MAIN_LAYER_PARENT_CONTAINS); 
            }
         }
         else { 
         alert ("No Results for this Filter Combination.");
         }
   
   }
    
   this.GetTopicProductsCodesByTopicList=function(TopicList,TopicType,FilterLevel){
          try {
            _NavigatorManager.ClearFilter(); //clear prev filter
         }
         catch(e){
          //do nothing
         }
         if (typeof(TopicList)=='undefined' || TopicList=="") {return false;}
         if (TopicList.indexOf(',') ==-1){
                this.GetTopicProductsCodes(TopicList,TopicType,FilterLevel);
        }
        else {
              


                _WebServiceAPI.GetTopicProductsCodesByTopicList(TopicList,(FilterLevel=='1') ? this.GetTopicProductsCodesOnComplete: this.GetTopicParentProductsCodesOnComplete);
        }
   }
 
   
   /**
     * Saves a topic to customer profile. OnCompleteFuncName is not passed or is it empty, the control is passed
     * on this.SaveTopicOnComplete otherwise the custom call back function will be called.
     * @param {string} TopicCode 
     * @param {string} TopicType 
     * @param {object} OnCompleteFuncName (optional)
     */
   this.SaveTopic=function(TopicCode,TopicType,OnCompleteFuncName) {
      if (typeof(OnCompleteFuncName)=='undefined' || (OnCompleteFuncName=="")) {
	   _WebServiceAPI.TopicCustomerRatingRecord(CurrentCustomerID, TopicType, TopicCode, 'tips', 5, 'n/a', this.SaveTopicOnComplete);
	
	  }
	  else {
	 
	   _WebServiceAPI.TopicCustomerRatingRecord(CurrentCustomerID, TopicType, TopicCode, 'tips', 5, 'n/a',OnCompleteFuncName);
	
	  }
	
	}
	
  
   /**
     * On complete function when topic is saved.
     * @param {object} result
     */
    this.SaveTopicOnComplete=function(result) {
                DoDefault();
 		     if (result.ActivityStatus==true) {
                    alert("your topic has been saved");
		     }
   
     }
	
	 /**
     * removes a topic to customer profile. OnCompleteFuncName is not passed or is it empty, the control is passed
     * on this.RemoveFavTopicOnComplete otherwise the custom call back function will be called.
     * @param {string} TopicCode 
     * @param {string} TopicType 
     * @param {object} OnCompleteFuncName (optional)
     */
    this.RemoveFavTopic=function(TopicCode,TopicType,OnCompleteFuncName)  {
       if (typeof(OnCompleteFuncName)=='undefined' || (OnCompleteFuncName=="")) {
	   _WebServiceAPI.RemoveTopicFromFavorites(CurrentCustomerID, TopicCode, TopicType, this.RemoveFavTopicOnComplete);
	  
	   }
	   else {
	    _WebServiceAPI.RemoveTopicFromFavorites(CurrentCustomerID, TopicCode,TopicType, OnCompleteFuncName);
	  
	   }
	}
	
	 /**
     * On complete function when topic is removed.
     * @param {object} result
     */
	this.RemoveFavTopicOnComplete=function(result) {
	            DoDefault();
 		     if (result.ActivityStatus==true) {
                    alert("your topic has been removed");
		     }
	}
 
}

/**
 * It registers the  Core.TopicManager_Class using registerClass method of MS AJAX Library
 */
 if (IsTypeDefined) { Core.TopicManager_Class.registerClass('Core.TopicManager_Class'); }

/**
 * @class DhtmlPaginator
 * Paginator Class is used to dynamically handle the paging Next, Previous based on properties set for this object.
 * The values set are default, but they should be reset based on where it gets used
 * @constructor 
 */
 
Core.DhtmlPaginator=function () {
    /**
     * Part of substring of the main layer we are interested into applying paging
     */
    this.KeywordLayerContain='Category:Product:List'; //'
    /**
     * tag name
     */
    this.TagName='div';
    /**
     * size (number of elemnts displayed in one page)
     */
    this.PageSize=5;
    /**
     * total pages within a layer/product/category
     */
    this.TotalPages=0;
    /**
     *  array where results will be saved
     */
    this.NavigateArray=new Array();
    /**
     * current page where the user is navigating
     */
    this.CurrentPage=0;
    /**
     * the layer id of the parent
     */
    this.ParentID='';
    /**
     * if true the buttons will be managed autimatically
     */
    this.SetNavigationLabels=true;
    /**
     * The id of next button on the header
     */
    this.NextButtonID="nextpage";
    /**
     * The id of next button on the footer
     */
    this.NextButtonID_Footer="nextpage_footer";
    /**
     * the id of previous on the header
     */
    this.PreviousID="Previous";
    
    /**
     * the id of previous on the header
     */
    this.PreviousID_Footer="Previous_Footer";
    /**
     * the layer where total number of pages will be displayed(optional)
     */
    this.DisplayPageNumberID="currentpageof";
     /**
     * the layer where total number of pages will be displayed(optional)on the footer
     */
    this.DisplayPageNumberID_Footer="currentpageof_footer";
    
    /**
     *  if GeneratePageNumbers=true, the page numbers will be generated
     */
    this.GeneratePageNumbers=false;
     /**
     *  This layer holds all other buttons like next, prev, 1,2,3, view all etc.. and it will
     * be marked as hidden if there is only one page.
     */
    this.MainPaginatorLayerID="AJAX_PAGINATOR_LAYER";
    this.MainPaginatorLayerID_FOOTER="AJAX_PAGINATOR_LAYER_FOOTER";
     /**
     * Layer id where the numbers will be displayedon the header
     */
    this.PageNumberLayerID="Ajax_Page_Numbers"
    
    /**
     * Layer id where the numbers will be displayedon the footer
     */
    this.PageNumberLayerID_Footer="Ajax_Page_Numbers_Footer";
     /**
     * html for links opening tag for numbers
     */
     this.PageNumberOpeningTag=CORE_AJAX_PAGING_NUMBERS_STYLESHEET;
    
     /**
     * html for closing tags for numbers
     */
     this.PageNumberClosingTag=CORE_AJAX_PAGING_NUMBERS_CLOSING_TAG;
     
     /**
     * html for opening tag for current page
     */
     this.CurrentPageOpeningTag=CORE_AJAX_CURRENT_PAGE_STYLESHEET;
    
     /**
     * html for closing tag for current page
     */
     this.CurrentPageClosingTag=CORE_AJAX_CURRENT_PAGE_CLOSING_TAG;
   /**
     * Saves current to be shown
     */
    this.CurrentItemsToShow=new Array();
    /**
     *  Saves current to be Hidden
     */
    this.CurrentItemsToHide=new Array;
    
    /**
     *  all variants
     */
    this.AllVariantsBtnID="ajax_all_variants";
     /**
     * Text to be displayed on view all btn
     */
    this.ViewAllLabel="view all";
      
    /**
     *  Saves Filtered Data 
     */
    this.FilteredData=null;
    this.IsFilterOn=false;
    
    /**
     *  Generates page numbers for both header and footer
     *  if the GeneratePageNumbers is set to true and at least one layer for header or footer exist
     *
     */
    this.DoGeneratePageNumbers=function(){
     if(this.GeneratePageNumbers==false) return;
      var sb = new StringBuilder();
       if (this.TotalPages>=1) {
          for (var i = 1; i <= this.TotalPages ; i++) {
             // if there are over 20 pages add a break for every 20 pages
             if ((i%20) == 0)
                sb.append("<br/>");
                
             if (this.CurrentPage==i) {
              // sb.append(this.PageNumberOpeningTag + i.toString() +this.PageNumberClosingTag+ "&nbsp;");
                sb.append(this.CurrentPageOpeningTag + i.toString() +this.CurrentPageClosingTag+ "&nbsp;&nbsp;");
       
             }
             else {
              sb.append("<a " + " onclick=\"_NavigatorManager.DoPageByIndex('" + this.ParentID + "'," +i.toString() + ")\" style=\"cursor:pointer\";>" + this.PageNumberOpeningTag + i.toString() +this.PageNumberClosingTag+ "</a>&nbsp;&nbsp;");
            }
          }
          
           if (this.TotalPages>1) {
               if (this.CurrentPage==-1) {
                  sb.append(this.CurrentPageOpeningTag + this.ViewAllLabel +this.CurrentPageClosingTag+ "&nbsp;");
       
               }
               else {
                  sb.append("<a " + " onclick=\"_NavigatorManager.DoPageByIndex('" + this.ParentID + "',0)\" style=\"cursor:pointer\";>" + this.PageNumberOpeningTag + this.ViewAllLabel + this.PageNumberClosingTag+ "</a>&nbsp;");
             }
           }
          
           var pageNumbersObj_Header=$get(this.PageNumberLayerID);
           if (pageNumbersObj_Header!=null) {
                  pageNumbersObj_Header.innerHTML=sb.toString();
           }
           
           var pageNumbersObj_Footer=$get(this.PageNumberLayerID_Footer);
           if (pageNumbersObj_Footer!=null) {
                 pageNumbersObj_Footer.innerHTML=sb.toString();
           }
       }
       
    }
    /**
     * Initializes the object
     */
    this.Initialize=function() {
        var list;
         this.NavigateArray=new Array();
        if (this.ParentID!='') {
        //alert(typeof($));
            var parentObj=$get(this.ParentID);
            // if (parentObj==null || typeof(parentObj)='undefined') return;
            list=parentObj.getElementsByTagName(this.TagName);
        }
        else {
            list = document.body.getElementsByTagName(this.TagName);
            //var list = document.body.getElementsByTagName(this.TagName);
        }

        for (var i = 0; i < list.length ; i++) {
            if (list[i].id.indexOf(this.KeywordLayerContain) !=-1) {
                //this.NavigateArray[this.NavigateArray.length]=list[i].id;
                this.NavigateArray[this.NavigateArray.length]=list[i];
            }
        }

        if ((this.NavigateArray !=null) && (this.PageSize>0)) {
            this.TotalPages=Math.ceil(parseInt(this.NavigateArray.length)/parseInt(this.PageSize));
        }
        this.CurrentPage=0;
        
    }
    
    this.InitializeFilter=function() {
        this.HideAll(); //hide previous page!
         var list;
         this.NavigateArray=new Array();
        if (this.ParentID!='') {
             var parentObj=$get(this.ParentID);
             list=parentObj.getElementsByTagName(this.TagName);
        }
        else {
            list = document.body.getElementsByTagName(this.TagName);
        }
     
        for (var i = 0; i < list.length ; i++) {
            for (var j = 0; j < this.FilteredData.length ; j++) {
                 if (list[i].id.indexOf(this.FilteredData[j]) !=-1) {           //make sure productcode is part of
                      if(list[i].id.indexOf(this.KeywordLayerContain) !=-1){    //make sure it has the contain layer id
                         this.NavigateArray[this.NavigateArray.length]=list[i];
                       }
                  }
            }
        }

        if ((this.NavigateArray !=null) && (this.PageSize>0)) {
            this.TotalPages=Math.ceil(parseInt(this.NavigateArray.length)/parseInt(this.PageSize));
        }
        this.CurrentPage=0;
        this.DoNext();
        
    }


    /**
     * hides all pages
     */
    this.HideAll=function(){
        if (this.NavigateArray  !=null) {
            for (var i=0;i<this.NavigateArray.length;i++) {
                if (typeof(this.NavigateArray[i])=='object'){
                    this.NavigateArray[i].style.display='none';
                }
                else {
                    var divid=this.NavigateArray[i];
                    var oDiv = document.getElementById(divid);
                    oDiv.style.display='none';
                }
            }
        }
    }

    /**
     * shows all pages
     */
    this.ShowAll=function(){
        if (this.NavigateArray !=null ) {
            for (var i=0;i<this.NavigateArray.length;i++) {
                if (typeof(this.NavigateArray[i])=='object'){
                    // this.NavigateArray[i].style.display='block';
                    this.NavigateArray[i].style.display='';
                }
                else {
                    var divid=this.NavigateArray[i];
                    var oDiv = document.getElementById(divid);
                    oDiv.style.display='block';
                }
            }
        }
    }
    
    /*
     * this method supports navigating to a particular page by index
    */
    this.DoPageByIndex=function(index) {
        this.CurrentPage=parseInt(index)-1;
        if (this.CurrentPage>=0) {
             this.DoNext();
        }
        else {
           this.DoGeneratePageNumbers();
           this.EraseFooterLabel();
           this.ShowAll();
        }
    }
    
    this.EraseFooterLabel=function() {
             //display page x of y on a label for the current page on the footer
            var tempObj=$get(this.DisplayPageNumberID);
            if (tempObj!=null) {
                tempObj.innerHTML="";
            }
            //display page x of y on a label for the current page on the footer
            var tempObj_Footer=$get(this.DisplayPageNumberID_Footer);
             if (tempObj_Footer!=null) {
                tempObj_Footer.innerHTML="";
            }
    
    
    }
    /**
     * naviates to the next page
     */
    this.DoNext=function() {
        if (this.CurrentPage>=this.TotalPages) return false;
        if (this.CurrentPage<=this.TotalPages)  this.HideAll();
        if (this.CurrentPage<=0) this.CurrentPage=0;

        this.CurrentPage=this.CurrentPage+1;
        var startI=(this.CurrentPage-1) * this.PageSize;
        var endI=this.CurrentPage * this.PageSize;

        this.SetLabels();
        this.DoGeneratePageNumbers();
        this.CurrentItemsToShow=new Array();
        for (var i=startI;i<endI;i++) {
            if (i<this.NavigateArray.length) {
                 this.CurrentItemsToShow[ this.CurrentItemsToShow.length]=this.NavigateArray[i]
                if (typeof(this.NavigateArray[i])=='object'){
                    // this.NavigateArray[i].style.display='block';
                    this.NavigateArray[i].style.display='';
                }
                else {
                    var divid=this.NavigateArray[i];
                    var oDiv = document.getElementById(divid);
                    oDiv.style.display='block';
                }
            }
        }
    }

 
      /**
     * naviates to the next page in a slide
     */
    this.DoNextSlide=function() {
        if (this.CurrentPage>=this.TotalPages) return false;
        if (this.CurrentPage<=0) this.CurrentPage=0;
        this.CurrentPage=this.CurrentPage+1;
        var startI=(this.CurrentPage-1) * this.PageSize;
        var endI=this.CurrentPage * this.PageSize;
        this.SetLabels();
        this.DoGeneratePageNumbers();
        //initialize array
        this.CurrentItemsToHide=new Array();
        //copy array
        for (var i = 0; i < this.CurrentItemsToShow.length; i++)   {
            this.CurrentItemsToHide[this.CurrentItemsToHide.length]=this.CurrentItemsToShow[i];

        }
        //initialize array
        this.CurrentItemsToShow=new Array();
        for (var i=startI;i<endI;i++) {
             if (i<this.NavigateArray.length) {
                 this.CurrentItemsToShow[ this.CurrentItemsToShow.length]=this.NavigateArray[i];
             }
        }
        //initialize array
        CurrentItemsToShow=new Array();
        //initialize array
        CurrentItemsToHide=new Array();
         //copy array to global variable
        for (var i = 0; i < this.CurrentItemsToShow.length; i++)   {

            CurrentItemsToShow[CurrentItemsToShow.length]=this.CurrentItemsToShow[i];

        }
         //copy array to global variable
        for (var i = 0; i < this.CurrentItemsToHide.length; i++)   {

            CurrentItemsToHide[CurrentItemsToHide.length]=this.CurrentItemsToHide[i];

        }
       
       //initialize index of item to be shown first
       ToShowIndex=0;
       //initialize index of item to be hidden first
       ToHideIndex=0;
       DoCoreSlideNext();
    }
    /**
     * navigates to Previous page
     */
    this.DoPrev=function() {
        if (this.CurrentPage<=1) return false;
        if (this.CurrentPage<=this.TotalPages)  this.HideAll();
        if (this.CurrentPage==this.TotalPages) this.CurrentPage=this.TotalPages;

        this.CurrentPage=this.CurrentPage-1;

        var startI=(this.CurrentPage-1) * this.PageSize;
        var endI=this.CurrentPage * this.PageSize;

        this.SetLabels();
        this.DoGeneratePageNumbers();
        for (var i=startI;i<endI;i++) {
            if (i<this.NavigateArray.length) {
                if (typeof(this.NavigateArray[i])=='object') {
                    this.NavigateArray[i].style.display='';
                }
                else {
                    var divid=this.NavigateArray[i];
                    var oDiv = document.getElementById(divid);
                    oDiv.style.display='block';
                }
            }
        }
    }

    /**
     * navigates to Previous page in a slide
     */
    this.DoPrevSlide=function() {
        if (this.CurrentPage<=1) return false;
        if (this.CurrentPage==this.TotalPages) this.CurrentPage=this.TotalPages;

        this.CurrentPage=this.CurrentPage-1;

        var startI=(this.CurrentPage-1) * this.PageSize;
        var endI=this.CurrentPage * this.PageSize;

        this.SetLabels();
        this.DoGeneratePageNumbers();
        //initialize
        this.CurrentItemsToHide=new Array();
        //copy current shown to array of to be hidden
        for (var i = 0; i < this.CurrentItemsToShow.length; i++)   {
            this.CurrentItemsToHide[this.CurrentItemsToHide.length]=this.CurrentItemsToShow[i];

        }
         //initialize
        this.CurrentItemsToShow=new Array();
        
        for (var i=startI;i<endI;i++) {
            if (i<this.NavigateArray.length) {
                //save the reference for further processing in a slide
                this.CurrentItemsToShow[ this.CurrentItemsToShow.length]=this.NavigateArray[i];
             }
        }
        //initialize
         CurrentItemsToShow=new Array();
         //initialize
         CurrentItemsToHide=new Array();
          //copy array to global variable
         for (var i = 0; i < this.CurrentItemsToShow.length; i++)   {

            CurrentItemsToShow[CurrentItemsToShow.length]=this.CurrentItemsToShow[i];

          }
         
         //copy array to global variable
         for (var i = 0; i < this.CurrentItemsToHide.length; i++)   {

            CurrentItemsToHide[CurrentItemsToHide.length]=this.CurrentItemsToHide[i];

        }
        //set initial index for items to be shown
         ToShowIndex=CurrentItemsToShow.length - 1;
         //set initial index for items to be hidden
         ToHideIndex=CurrentItemsToHide.length -1;
         //call the slide function
         DoCoreSlidePrev();
    }
    
     /**
     * This function hides the main layer of paginator if there is less or equal one page and shows otherwise
     * 
     * 
     */
    this.ManagePaginatorMainLayers=function() {
         var temp_objMainPaginatorLayerID=$get( this.MainPaginatorLayerID );
            
         var temp_objMainPaginatorLayerID_FOOTER=$get( this.MainPaginatorLayerID_FOOTER );
         
          if (temp_objMainPaginatorLayerID!=null) {
                if (this.TotalPages>1) {
                        temp_objMainPaginatorLayerID.style.visibility="visible";
                         }
                else {
                        temp_objMainPaginatorLayerID.style.visibility="hidden";  
                }
          }
          
           if (temp_objMainPaginatorLayerID_FOOTER!=null) {
                if (this.TotalPages>1) {
                        temp_objMainPaginatorLayerID_FOOTER.style.visibility="visible";
                         }
                else {
                        temp_objMainPaginatorLayerID_FOOTER.style.visibility="hidden";  
                }
          }
    
    }
    /**
     * This function manages the next, previous buttons both on header and footer,
     * it also manages the Off btns. They are all optional and the code handles the run time error if any
     * of them is missing
     */
     
    this.SetLabels=function(){
        
         var _off="_OFF";
         //Next
         var tempObj_Next=$get(this.NextButtonID);
         var tempObj_OFF_Next=$get(this.NextButtonID +_off);
          //Next footer 
         var tempObj_Next_Footer=$get(this.NextButtonID_Footer);
         var tempObj_OFF_Next_Footer=$get(this.NextButtonID_Footer +_off);
         
         //Prev
         var tempObj_Prev=$get(this.PreviousID);
         var tempObj_OFF_Prev=$get(this.PreviousID +_off);
         //Prev Footer
         var tempObj_Prev_Footer=$get(this.PreviousID_Footer);
         var tempObj_OFF_Prev_Footer=$get(this.PreviousID_Footer +_off);
         //all variants btn
         var tempobj_AllVariantsBtnID=$get(this.AllVariantsBtnID);
         
         
          this.ManagePaginatorMainLayers();
         if (this.SetNavigationLabels) {
             
            //handle all shades btn
              if (tempobj_AllVariantsBtnID!=null) {
                  if (this.TotalPages>1) {
                        tempobj_AllVariantsBtnID.style.visibility="visible";
                        tempobj_AllVariantsBtnID.style.display="";
                }
                else {
                        tempobj_AllVariantsBtnID.style.visibility="hidden";  
                }
            }
            
            
            //Hide all OFF Buttons on header and footer navigations
            if ( tempObj_OFF_Next!=null) {
                        tempObj_OFF_Next.style.display="none";
            }
            
            if ( tempObj_OFF_Prev!=null) {
                        tempObj_OFF_Prev.style.display="none";
            }
            
            if ( tempObj_OFF_Next_Footer!=null) {
                        tempObj_OFF_Next_Footer.style.display="none";
            }
            
            if ( tempObj_OFF_Prev_Footer!=null) {
                        tempObj_OFF_Prev_Footer.style.display="none";
            }
            
            //display page x of y on a label for the current page
            var tempObj=$get(this.DisplayPageNumberID);
            
            if (tempObj!=null) {
                tempObj.innerHTML=PAGE_PAGExOFy + this.CurrentPage + OFF_PAGExOFy + this.TotalPages +  DISPLAY_PAGExOFy;
            }
            //display page x of y on a label for the current page on the footer
            var tempObj_Footer=$get(this.DisplayPageNumberID_Footer);
             if (tempObj_Footer!=null) {
                tempObj_Footer.innerHTML=PAGE_PAGExOFy + this.CurrentPage + OFF_PAGExOFy + this.TotalPages + DISPLAY_PAGExOFy;;
            }
            
            // tempObj=$get(this.PreviousID);
             if (tempObj_Prev!=null) {
                  if (this.TotalPages>1) {
                       tempObj_Prev.style.visibility="visible";
                       tempObj_Prev.style.display="";
                }
                else {
                      tempObj_Prev.style.visibility="hidden";  //handle if there is one page only
                }
            }
            //handle prev button initially on footer
            
             if (tempObj_Prev_Footer!=null) {
                  if (this.TotalPages>1) {
                        tempObj_Prev_Footer.style.visibility="visible";
                        tempObj_Prev_Footer.style.display="";
                }
                else {
                      tempObj_Prev_Footer.style.visibility="hidden";  
                }
            }
            
            //tempObj=$get(this.NextButtonID);
            //
            if (tempObj_Next!=null) {
                 if (this.TotalPages>1) {
                   tempObj_Next.style.visibility="visible";
                     tempObj_Next.style.display="";
                                 
                }
                else {
                   tempObj_Next.style.visibility="hidden"; //handle if there is one page only
                }
            }
             
             //handle next button initially on footer
            
             if (tempObj_Next_Footer!=null) {
                  if (this.TotalPages>1) {
                        tempObj_Next_Footer.style.visibility="visible";
                        tempObj_Next_Footer.style.display="";
                }
                else {
                        tempObj_Next_Footer.style.visibility="hidden";  
                }
            }
            //
              if (this.TotalPages>1) { // if more than one page do the following.
                    if (this.CurrentPage>=this.TotalPages) {
                       
                        //show previous header and/or footer
                        if (tempObj_Prev!=null) {
                            tempObj_Prev.style.visibility="visible";
                            tempObj_Prev.style.display="";
                        }
                        if ( tempObj_Prev_Footer!=null) {
                             tempObj_Prev_Footer.style.visibility="visible";
                             tempObj_Prev_Footer.style.display="";
                        }
                       
                        //hide OFF previous 
                        if ( tempObj_OFF_Prev!=null) {
                             tempObj_OFF_Prev.style.display="none";
                        }
                        if ( tempObj_OFF_Prev_Footer!=null) {
                              tempObj_OFF_Prev_Footer.style.display="none";
                        }
                        
                        
                        // Hide NEXT
                        if (tempObj_Next!=null) {
                            tempObj_Next.style.visibility="hidden";
                            tempObj_Next.style.display="none";
                        }
                        if (tempObj_Next_Footer!=null) {
                            tempObj_Next_Footer.style.visibility="hidden";
                            tempObj_Next_Footer.style.display="none";
                        }
                       
                        // Show NEXT DISABLED
                       if ( tempObj_OFF_Next!=null) {
                             tempObj_OFF_Next.style.display="";
                        }
                        
                        if ( tempObj_OFF_Next_Footer!=null) {
                             tempObj_OFF_Next_Footer.style.display="";
                        }
                        
                    }

                    if (this.CurrentPage<=1) {
                        //hide next
                       
                        if (tempObj_Prev!=null) {
                            tempObj_Prev.style.visibility="hidden";
                             tempObj_Prev.style.display="none";
                        }
                        
                         if (tempObj_Prev_Footer!=null) {
                            tempObj_Prev_Footer.style.visibility="hidden";
                            tempObj_Prev_Footer.style.display="none";
                        }
                        
                        //show previous disabled
                        if ( tempObj_OFF_Prev!=null) {
                             tempObj_OFF_Prev.style.display="";
                        }
                        if ( tempObj_OFF_Prev_Footer!=null) {
                             tempObj_OFF_Prev_Footer.style.display="";
                        }
                        //show next
                        if (tempObj_Next!=null) {
                            tempObj_Next.style.visibility="visible";
                            tempObj_Next.style.display="";
                        }
                        
                        if (tempObj_Next_Footer!=null) {
                            tempObj_Next_Footer.style.visibility="visible";
                            tempObj_Next_Footer.style.display="";
                        }
                        
                         // hide NEXT DISABLED
                        if ( tempObj_OFF_Next!=null) {
                             tempObj_OFF_Next.style.display="none";
                        }
                         if ( tempObj_OFF_Next_Footer!=null) {
                             tempObj_OFF_Next_Footer.style.display="none";
                        }
                    }
            }
        }
    }
   
 }
/**
 * It registers the  DhtmlPaginator using registerClass method of MS AJAX Library
 */
 if (IsTypeDefined) { Core.DhtmlPaginator.registerClass('Core.DhtmlPaginator'); }

 /* End of Paginator Class */

/**
 * @class NavigatorManager
 * NavigatorManager  Class is used to dynamically iterate the DHTML Object and add next/prev buttons based
 * the values that are passed on the Initialize method
 * It Also keep the reference of such DHTML Object for the sake of bookmarking/navigations
 * Here is an example how I used this class and initialized it on topic page
 *       var _NavigatorManager=new NavigatorManager();
 *       _NavigatorManager.Initialize('Topic:Product:List','div','Topic_Product','td',5,false);
 * @constructor 
 */

 Core.NavigatorManager=function () {
    /**
     * collection of navigators
     */
    this._NavigatorCollection=new Array();
    this.FilteredData;
    
     this.DoMainFilterInitialization=function(ParentLayerContains) {
        var productCodesArray=new Array();
        var lastProductCodeFethched=""
        this.FilteredData.sort();
         for (var i=0;i<this.FilteredData.length;i++) {
            var currentRecord_Array=this.FilteredData[i].split(":"); 
            if (currentRecord_Array[1]!="" && currentRecord_Array[1]!=lastProductCodeFethched){
                lastProductCodeFethched=currentRecord_Array[1];
                productCodesArray[productCodesArray.length]=currentRecord_Array[1];
            }
            // productCodesArray[productCodesArray.length]=currentRecord_Array[1];
         }
         if (productCodesArray.length>0) {
              var currentNavigator=this.GetNavigator(ParentLayerContains);
               currentNavigator.IsFilterOn=true;
               currentNavigator.FilteredData=productCodesArray;
               currentNavigator.InitializeFilter();
         }
     }
    
    this.DoFilterInitialization=function(ParentLayerContains) {
        var currentPrdCode="";
        var currentParentPrdCode="";
        var currentNavigator=null;
        var variantsByProduct=new Array();
        var allDistinctFilteredProducts=new Array();
        var noMatchIDs=new Array();
        this.FilteredData.sort();
        for (var i=0;i<this.FilteredData.length;i++) {
            var currentRecord_Array=this.FilteredData[i].split(":"); 
                if (currentRecord_Array[0]!=currentParentPrdCode) {
                    if (currentNavigator!=null) { 
                        currentNavigator.FilteredData=variantsByProduct ;
                        currentNavigator.InitializeFilter();
                        
                     }
                     
                 variantsByProduct=new Array();
                 currentParentPrdCode=currentRecord_Array[0];
                 allDistinctFilteredProducts[allDistinctFilteredProducts.length]=currentRecord_Array[0];
                 // var tempParentID="Category:Product:List:" + currentParentPrdCode;
                 var tempParentID=ParentLayerContains + currentParentPrdCode;
                 currentNavigator=this.GetNavigator(tempParentID);
                 if (currentNavigator!=null || typeof(currentNavigator)!='undefined') {
                   
                       currentNavigator.FilteredData=new Array();;
                       currentNavigator.IsFilterOn=true;
                 }
              }
              if (currentRecord_Array[1]!=currentPrdCode) { //array is sorted and this condition is placed to remove any duplicate!
                 currentPrdCode=currentRecord_Array[1];
                 variantsByProduct[variantsByProduct.length]=currentPrdCode;
                
              }
        }
         //last product of the array
          if (currentNavigator!=null) { 
                        currentNavigator.FilteredData=variantsByProduct ;
                        currentNavigator.InitializeFilter();
                        
          }
      
        //hide the variants of those who does not have a match
        for (var i=0;i<this._NavigatorCollection.length;i++) {
        
             var blnExist=false;
              var tempObj=this.GetNavigator(this._NavigatorCollection[i].ParentID);
           
              if ( tempObj.ParentID.indexOf(ParentLayerContains)!=-1 ){
                          for (var j=0;j<allDistinctFilteredProducts.length;j++) {
                            var tempNavigatorID=ParentLayerContains + allDistinctFilteredProducts[j];
                              if (tempObj.ParentID==tempNavigatorID) {
                                         blnExist=true;
                                        break;
                               }
                   
                           }
                // alert(tempObj.ParentID);
                  if (blnExist==false) {
                       noMatchIDs[noMatchIDs.length]=tempObj.ParentID;
                      tempObj.IsFilterOn=true; //but no match
                      tempObj.HideAll();
                      tempObj.TotalPages=0;
                 }
              }
            
         }
         //
         var FilteredParent=new Array(); //removed the products that come from database but has no match on the page.
         for (var i=0;i<allDistinctFilteredProducts.length;i++) {
                for (var j=0;j<noMatchIDs.length;j++)  {
                   if ( noMatchIDs[j].indexOf(allDistinctFilteredProducts[i])!=-1 ) {
                     allDistinctFilteredProducts[i]="";
                     
                   }
                }
          }
          //
          for (var i=0;i<allDistinctFilteredProducts.length;i++) {
              if (allDistinctFilteredProducts[i]!="") {
                FilteredParent[FilteredParent.length]=":" + allDistinctFilteredProducts[i];
              }
          }       
          //
          if (allDistinctFilteredProducts.length>0) {
           this.FilteredData=FilteredParent;
           this.DoMainFilterInitialization(MAIN_LAYER_PARENT_CONTAINS);
          }
      
    }
    
    //
    this.ClearFilter=function() {
      for (var i=0;i<this._NavigatorCollection.length;i++) {
            if (this._NavigatorCollection[i].IsFilterOn==true) {
                    this._NavigatorCollection[i].Initialize();
                    this._NavigatorCollection[i].DoNext();
          
           }
       }
    }
    /**
     * adds a navigator in the collection
     * @param {object} NavigatorObject TODO
     */
    this.AddNavigator= function (NavigatorObject) {
        var exist=false;
        if (this._NavigatorCollection!=null) {
            for (var i=0;i<this._NavigatorCollection.length;i++) {
                if (this._NavigatorCollection[i].ParentID==NavigatorObject.ParentID) {
                    this.NavigatorObject[i]=NavigatorObject;
                    exist=true;
                    break;
                }
            }
            if(exist==false) {
                this._NavigatorCollection[this._NavigatorCollection.length]=NavigatorObject;
            }
        }
    }

    /**
     * returns an elemnt within a collection based on parentid which has to be unique
     * @param {string} ParentID where the object is contained
     */
    this.GetNavigator=function (ParentID) {
        for (var i=0;i<this._NavigatorCollection.length;i++) {
            if (this._NavigatorCollection[i].ParentID==ParentID) {
                return this._NavigatorCollection[i];
            }
        }
    }
    
    this.DoPageByIndex=function(ParentID,index) {
       var CurrentNavigator=this.GetNavigator(ParentID);
       CurrentNavigator.DoPageByIndex(index);
    }
    /**
     * naviates to the next page
     * @param {string} ParentID 
     * @param {object} NextObject 
     */
    this.DoNext=function(ParentID,NextObject,DoSlide) {
        var CurrentNavigator=this.GetNavigator(ParentID);
        CurrentNavigator.NextButtonID=NextObject.id;
        if (DoSlide) {
                CurrentNavigator.DoNextSlide();
        }
        else {
           CurrentNavigator.DoNext();
        }
    }
    
    /**
     * naviates to the next page from the footer
     * @param {string} ParentID 
     * @param {object} NextFooterObject 
     */
    this.DoNextFromFooter=function(ParentID,NextFooterObject) {
        var CurrentNavigator=this.GetNavigator(ParentID);
        CurrentNavigator.NextButtonID_Footer=NextFooterObject.id;
        CurrentNavigator.DoNext();
    }
    /**
     * Shows all pages
     * @param {string} ParentID 
     */
    this.ShowAll=function(ParentID) {
        var CurrentNavigator=this.GetNavigator(ParentID);
        CurrentNavigator.ShowAll();
    }

    /**
     * Navigates to previous page
     * @param {string} ParentID for prev button
     * @param {object} PreviousObject 
     */
    this.DoPrev=function(ParentID,PreviousObject,DoSlide) {
        var CurrentNavigator=this.GetNavigator(ParentID);
        CurrentNavigator.PreviousID=PreviousObject.id;
        if(DoSlide) {
          CurrentNavigator.DoPrevSlide();
        }
        else {
        CurrentNavigator.DoPrev();
        }
    }
    
      /**
     * Navigates to previous page from the footer
     * @param {string} ParentID of the whole container for pages
     * @param {object} PreviousFooterObject
     */
    this.DoPrevFromFooter=function(ParentID,PreviousFooterObject) {
        var CurrentNavigator=this.GetNavigator(ParentID);
        CurrentNavigator.PreviousID_Footer=PreviousFooterObject.id;
        CurrentNavigator.DoPrev();
    }
    /**
     * This is a very important method
     * which first retrievs from document object all the tags with name ParenTagName like "div", span", "td", "tr" etc....
     * Then it iterates via such object and searches only those that have as part of the ID the substring
     * ParentContains which could be like Topic:Product:List
     * If an object meets that criteria, then we are intersted from objects within that parent
     * that has their tags as ChildTagName and contains on their ID the value ChildContains.
     * @param {string} ParentContains Substring of DHTML Object we are interested. <b>Importnat, try to keep such value unique based on what we need to process</b>
     * @param {string} ParenTagName Tag name of parents like div, span, td, tr etc...
     * @param {string} ChildContains Substring of DHTML Object we are interested. <b>Importnat, try to keep such value unique based on what we need to process</b>
     * @param {string} ChildTagName Tag name of parents like div, span, td, tr etc...
     * @param {int} PageSize How manay elements of childcontain wanted to be visible at a certain time
     * @param {bool} BoolNavigationBtnsWanted It determines if we want to manage the buttons next and prev 
     * @param {bool} BoolGeneratePageNumbers if set to true, generates the page numbers like 1,2,3,4 etc..
      */
    this.Initialize=function(ParentContains, ParenTagName, ChildContains, ChildTagName, PageSize, BoolNavigationBtnsWanted,AssumeNavigationBtns,BoolGeneratePageNumbers) {
        var list = document.body.getElementsByTagName(ParenTagName);
        for (var i = 0; i < list.length ; i++) {
            if (list[i].id.indexOf(ParentContains) !=-1) {
                var _TempNavigator= new Core.DhtmlPaginator();
                _TempNavigator.PageSize=PageSize;
                _TempNavigator.SetNavigationLabels=BoolNavigationBtnsWanted;
                _TempNavigator.KeywordLayerContain=ChildContains; // //'
                _TempNavigator.TagName=ChildTagName;
                _TempNavigator.ParentID=list[i].id;
                //navigation buttons
                if(AssumeNavigationBtns!=null) {
                    if (AssumeNavigationBtns) {
                         _TempNavigator.NextButtonID="Next_" + list[i].id.replace(ParentContains,'');
                         _TempNavigator.PreviousID="Prev_" + list[i].id.replace(ParentContains,'');
                         //
                         _TempNavigator.AllVariantsBtnID="ajax_all_variants_" + list[i].id.replace(ParentContains,'');
                         //
                         _TempNavigator.NextButtonID_Footer=_TempNavigator.NextButtonID_Footer + "_" +list[i].id.replace(ParentContains,'');
                         _TempNavigator.PreviousID_Footer=_TempNavigator.PreviousID_Footer + "_" +list[i].id.replace(ParentContains,'');
                         _TempNavigator.DisplayPageNumberID=_TempNavigator.DisplayPageNumberID + "_" +list[i].id.replace(ParentContains,'');
                         _TempNavigator.DisplayPageNumberID_Footer=_TempNavigator.DisplayPageNumberID_Footer + "_" +list[i].id.replace(ParentContains,'');
                        //
                         _TempNavigator.ViewAllPagesHeader="viewall_header" + list[i].id.replace(ParentContains,'');
                         _TempNavigator.ViewAllPagesFooter="viewall_footer"  + list[i].id.replace(ParentContains,'');
                        
                        //
                         _TempNavigator.MainPaginatorLayerID="AJAX_PAGINATOR_LAYER"  + list[i].id.replace(ParentContains,'');
                         _TempNavigator.MainPaginatorLayerID_FOOTER="AJAX_PAGINATOR_LAYER_FOOTER"  + list[i].id.replace(ParentContains,'');
                        //
                        
                        _TempNavigator.SetNavigationLabels=true;
                    }
                 }
                   
                _TempNavigator.GeneratePageNumbers=BoolGeneratePageNumbers;
                _TempNavigator.Initialize();
                _TempNavigator.DoNext();
                this.AddNavigator( _TempNavigator);
            }
        }
    }
}
 /**
 * It registers the  Core.NavigatorManager using registerClass method of MS AJAX Library
 */
 if (IsTypeDefined) { Core.NavigatorManager.registerClass('Core.NavigatorManager'); }


/* End of Navaigator Manager Class */
/**
 * @class SignInBubble_Class
 * This class is responsible for managing the Ajax signin module
 */

Core.SignInBubble_Class=function() {
    this.PopupPath = POPUPPATHSIGNIN;
    this.PopupHeight = POPUPSIGNINHIEGHT;
    this.PopupWidth = POPUPSIGNINWIDTH;
    this.TopicType = "";
    this.newWindow = "";

    /**
     * Shows the Sign in bubble from the Favorites 
     */    
    this.ShowBubbleFromFavoritesBubble=function(objCode){
        
        if (this.newWindow && !this.newWindow.closed)	{
		    this.newWindow.close();
	    }	
		
	    var winl = (screen.width - this.PopupWidth) / 2;
	    var wint = (screen.height - this.PopupHeight) / 2;
	    if (this.TopicType == ""){
	        this.newWindow = open(this.PopupPath + "?objCode=" + objCode, 'FavoritePopup', ("toolbar=no,location=no,directories=no,status=yes,menubar=no,scrollbars=no,resizable=no,copyhistory=no,top=" + wint + ",left=" + winl + ",width=" + this.PopupWidth + ",height=" + this.PopupHeight + "\""));
	    }else{
	        this.newWindow = open(this.PopupPath + "?objCode=" + objCode + "&TopicType=" + this.TopicType, 'FavoritePopup', ("toolbar=no,location=no,directories=no,status=yes,menubar=no,scrollbars=no,resizable=no,copyhistory=no,top=" + wint + ",left=" + winl + ",width=" + this.PopupWidth + ",height=" + this.PopupHeight + "\""));
	    }
	    this.newWindow.focus();
    }

    /**
     * Shows the Sign in bubble from the Favorites 
     */    
    this.ShowBubble=function(){    
        if (this.newWindow && !this.newWindow.closed)	{
		    this.newWindow.close();
	    }	
		
	    var winl = (screen.width - this.PopupWidth) / 2;
	    var wint = (screen.height - this.PopupHeight) / 2;
    
        this.newWindow = open(this.PopupPath, 'SigninPopup', ("toolbar=no,location=no,directories=no,status=yes,menubar=no,scrollbars=no,resizable=no,copyhistory=no,top=" + wint + ",left=" + winl + ",width=" + this.PopupWidth + ",height=" + this.PopupHeight + "\""));

	    this.newWindow.focus();    
    
    }
    
}
/**
* It registers the  SignInBubble_Class using registerClass method of MS AJAX Library
*/
if (IsTypeDefined) { Core.SignInBubble_Class.registerClass('Core.SignInBubble_Class'); }
 


/**
 * @class StringBuilder
 * Models a simple string builder class
 * @param {string} value The value to append to the array
 * @constructor
 */
function StringBuilder(value) {
    this.strings = new Array("");
    this.append(value);
}

/**
 * Appends the given value to the end of this instance.
 */
StringBuilder.prototype.append = function (value) {
    if (value) {
        this.strings.push(value);
    }
}

/**
 * Clears the string buffer
 */
StringBuilder.prototype.clear = function () {
    this.strings.length = 1;
}

/**
 * Converts this instance to a String.
 */
StringBuilder.prototype.toString = function () {
    return this.strings.join("");
}

/* End of StringBuilder  Class */

/**
 * Stores object reference to those to be shown in a slide
 */
 var CurrentItemsToShow=null;
 /**
 * Stores object reference to those to be hidden in a slide
 */
 var CurrentItemsToHide=null;
 /**
 * Stores item index of current item  to be shown in a slide
 */
 var ToShowIndex=0;
 /**
 * Stores item index of current item  to be hidden in a slide
 */
 var ToHideIndex=0;
 /**
 * set time out speed
 */
 var CoreSlideSpeed=110;
 
 /**
 * Slides Next
 */
 function DoCoreSlideNext() {
    if (ToShowIndex<CurrentItemsToShow.length) {
       CurrentItemsToShow[ToShowIndex].style.display='';
       ToShowIndex++;
     }
    if (ToHideIndex<CurrentItemsToHide.length) {
            CurrentItemsToHide[ToHideIndex].style.display='none';
            ToHideIndex++;
    }
    if ((ToShowIndex<CurrentItemsToShow.length) ||(ToHideIndex<CurrentItemsToHide.length)) {
            setTimeout("DoCoreSlideNext()",CoreSlideSpeed);
     }
 
 }

 /**
 * Slides Prev
 */
 function DoCoreSlidePrev() {
   if (ToShowIndex>=0) {
       CurrentItemsToShow[ToShowIndex].style.display='';
       ToShowIndex--;
     }
    if (ToHideIndex>=0) {
            CurrentItemsToHide[ToHideIndex].style.display='none';
            ToHideIndex--;
    }
    if ((ToShowIndex>=0) ||(ToHideIndex>=0)) {
            setTimeout("DoCoreSlidePrev()",CoreSlideSpeed);
     }
 
 }
 
/**
 * OnResizeHandler
 */
function OnResizeHandler(){
    _QuickShop_Class.Hide(); //added on 3/23/07 to fix bug 194 on lancome
    if (!IS_MODELPOPUP_VISIBLE) return;
    _CoreModalPopUp.ResizeHandler();
    
}


/**
 * OnScrollHandler 
 */
function OnScrollHandler(){
    if (!IS_MODELPOPUP_VISIBLE) return;
    _CoreModalPopUp.ScrollHandler();
}

/**
 * This function is executed whenever a web service raises a run time error
 * If JAVASCRIPT_DEBUG is set to true an alert will be displayed with the actual message.
 * @param {object} result The JSON object returned by web service
 */



function onError(result) {
    DoDefault();
    window.status = "Web Service Error";
    if (result != null) {

       if (result.get_timedOut()) {
           alert('Your request timed out. Please try again');
       }
       else {
            var message = result.get_message();
            var stackTrace = result.get_stackTrace();
            var exceptionType = result.get_exceptionType();
            if (JAVASCRIPT_DEBUG) {
                alert(message + "..." + stackTrace + "...." + exceptionType );
            }
            else {
              alert("your request was not complete. Please try again" );
            }
        }
    }
}    

/**
 * This function is executed whenever a web service is timed out
 * If JAVASCRIPT_DEBUG is set to true an alert will be displayed.
 * @param {object} result The JSON object returned by web service
 */ 
function onTimeout(result) {
            DoDefault();
           // window.status = "web service call timed out";
            if (JAVASCRIPT_DEBUG) {
                        alert('web service call timed out. Please try again');
            }
}


/**
 * This function returns the customer ID that is assigned to a user
 * If Customer ID is missing and If JAVASCRIPT_DEBUG is set to true an alert
 * will be displayed with the actual message.
 */
function GetCurrentCustomerID() {
    if (CurrentCustomerID== null ||   typeof(CurrentCustomerID)=='undefined') {
        if (JAVASCRIPT_DEBUG)
                 alert('Customer ID is missing');
         return '';
    }
  return CurrentCustomerID;
}

/**
 * Some preliminary work for Mouse coordinates and browser type
 */
var tempX = 0;
var tempY = 0;

var IE = document.all?true:false;
if (!IE) document.captureEvents(Event.MOUSEMOVE)


/**
 * Attaching getMouseXY function onmousemove  event
 */
document.onmousemove = getMouseXY;

/**
 * Attaching HideQuick function onmouseup event
 */
document.onmouseup = HideQuick;

/**
 * This function is used onmouseup event to hide the quick shop bubble
 */
function HideQuick(){
    _QuickShop_Class.Hide();
   
}


/**
 * This function stores in 2 global variable the mouse x coordinate and y Coordinate
 * @param {object} e Event object
 */
function getMouseXY(e) {
        if (IE) { // grab the x-y pos.s if browser is IE
            //if  (document.readyState != 'complete') return;
            if (!document) return;
            if(!document.body) return;
            tempX = parseInt(event.clientX) + parseInt(document.body.scrollLeft);
            tempY = parseInt(event.clientY) + parseInt(document.body.scrollTop);
        }
        else {  // grab the x-y pos.s if browser is NS
                tempX = e.pageX;
                tempY = e.pageY;
        }
        if (tempX < 0){tempX = 0;}
        if (tempY < 0){tempY = 0;}
        return true;
}

/**
 * Returns the temporary coordinate X of the Mouse
 */
function GetMouseCoordinateX() {
   return tempX;
}

/**
 * Returns the temporary coordinate Y of the Mouse
 */
function GetMouseCoordinateY() {
   return tempY;
}

/* End Mouse Coordinates */

/**
 * This function returns the Value attribute of a selected elemnt in a drop down.
 * @param {string} DropDownObjectID The ID of a drop down
 */
function GetSelectedValue(DropDownObjectID) {
        var x=document.getElementById(DropDownObjectID)
        //return (x.options[x.selectedIndex].text)
        return (x.options[x.selectedIndex].value)
}

/**
 * This function returns the text attribute of a selected element in a drop down.
 * @param {string} name DropDownObjectID The ID of a drop down
 */
function GetSelectedText(DropDownObjectID) {
        var x=document.getElementById(DropDownObjectID)
        return (x.options[x.selectedIndex].text)
}

/**
 * This function generataes the Option of a drop down based on JASON formatted Object Variants
 * Important Note: I am not using this function because I found a thread on the web
 * that this method raises IE error memory can not be referenced. Instead I am using a classic way
 * of building it via innerHTML of a DHTML element like div, span, etc....
 * I am currently using function "GenerateDropDownVariants"
 * @param {object} Variants JSON Serilized Object that Comes via web services Results
 * @param {string} ObjectToAppend The ID of a drop down to generate the options
 */
function BuildDropDownVariants(Variants,ObjectToAppend)
{
    if (Variants !=null )
    {
        for(i=0; i<Variants.length; i++)
        {
            var  option = new Option(Variants[i].Name + " - $ " + Variants[i].MainPrice ,Variants[i].SKU);
            ObjectToAppend.options[i] =option;
        }
    }
}

/**
 * This function builds the Drop Down. Be aware that I am using the javascrpt string builder class instead of
 * string concatinations.
 * @param {object} Variants JSON Serilized Object that Comes via web services Results
 * @param {string} DropDownID The ID of a drop down to generate the options
 */
function GenerateDropDownVariants(Variants,DropDownID,HasUniquePrices,ShowPriceOnDropDown,onchangeFuncCall)      
{
    var filter= _ProductBubble_Class.FilterVariantList;
    var sb = new StringBuilder();
    sb.append("");
    if (Variants != null ) {
        sb.append("<select id=\"");
        sb.append(DropDownID);
       // sb.append("\" class=\"Ablack11pxB\">");
      // sb.append("\" class=\"Ablack11pxB\" onchange=\"_ProductBubble_Class.SelectItem();\">");
        sb.append("\" class=\"Ablack11pxB\" onchange=\"" + onchangeFuncCall +"\">");
        
        for(i=0; i<Variants.length; i++)  {
          if (filter=='' || filter.indexOf(Variants[i].SKU)!=-1) {
            sb.append("<option value=\"");
            sb.append(Variants[i].SKU);
            sb.append("#");
            sb.append(Variants[i].MainPrice);
            sb.append("#");
            sb.append(Variants[i].StockWeb.toString());
            sb.append("\">");
            if (HasUniquePrices==true || ShowPriceOnDropDown==false) { //all vars same price
              sb.append(Variants[i].Name); 
           
            }
            else {//different variants different prices
              sb.append(Variants[i].Name   + " - $ " + Variants[i].MainPrice );
            }
            sb.append("</option>");
           }
        }
        sb.append("</select>")
    }
    //alert(sb.toString());
    return sb.toString();
}

/**
 * This function set selects a particular option of a drop down
 * @param {string} dropDownID The ID of a drop down
 * @param {string} valueToSelect Value to compare in order to select it
 */
function SetDropDownItemSelected(dropDownID,valueToSelect) {
    var selectedstr=valueToSelect;
    if (selectedstr.indexOf("#") != -1){
		selectedstr=selectedstr.slice(0,sku.indexOf("#"));
	}
    var options=document.getElementById(dropDownID)
    if (options!=null) {
        for (var i=0; i< options.length; i++) {
            var str = options[i].value;
			str = str.slice(0,str.indexOf("#"));
            if (str==selectedstr) { //valueToSelect
                options.selectedIndex=i;
                break;
            }
        }
    }
}

/**
 * This Function Determines the absolute coordinate X (Left) of any DHTML Object
 * @param {object} obj Obj is any DHTML Object for which we need to determine the absolute Coordinate X (Left)
 */
function findPosX(obj){
    var curleft = 0;

    if (obj.offsetParent){
        while(1){
            curleft += obj.offsetLeft;
            if (!obj.offsetParent)
            {
                break;
            }
            obj = obj.offsetParent;
        }
    }
    else if(obj.x){ curleft+=obj.x }

    return curleft;
}

/**
 * This Function Determines the absolute coordinate Y (Top) of any DHTML Object
 * @param {object} obj Obj is any DHTML Object for which we need to determine the absolute Coordinate Y (Top)
 */
function findPosY(obj){
    var curtop = 0;

    if (obj.offsetParent){
        while(1) {
            curtop += obj.offsetTop;
            if (!obj.offsetParent)
            {
                break;
            }
            obj = obj.offsetParent;
        }
    }
    else if(obj.y) { curtop+=obj.y }

    return curtop;
}

/**
 * This Function is used when on top of any DHTMl Object will be placed another DHTMl Object
 * It is used when I display the QuickShop Layer on top of the Product Image.
 * @param {object} RelativeObject This is any dhtml object, on our case it is a product Image
 * @param {object} ObjectToShow This is the Quick Shop DHTML Layer
 * @param {int} plusTop This will be an integer which will tell us the Top Position of the ObjectToShow
 * @param {int} plusLeft This will be an integer which will tell us the Left Position of the ObjectToShow
 */
function PositionLayerByRelativeObject(RelativeObject,ObjectToShow,plusTop,plusLeft) {
    var _xcoordinate=parseInt(findPosX(RelativeObject));
    var _ycoordinate=parseInt(findPosY(RelativeObject));
    
    if (!isNaN(plusLeft)){
        _xcoordinate=parseInt(_xcoordinate) + parseInt(plusLeft);
    }
    if (!isNaN(plusTop)){
        _ycoordinate=parseInt(_ycoordinate) + parseInt(plusTop);
    }

    ObjectToShow.style.visibility='visible';
    ObjectToShow.style.position='absolute';
    ObjectToShow.style.top=_ycoordinate + 'px';
    ObjectToShow.style.left=_xcoordinate + 'px';
}


/**
 * DoWait 
 */
function DoWait() {
        window.status = "";
       document.body.style.cursor='wait';
       TogglePleaseWait('visible',false)
}


/** 
 * DoDefault 
 */
function DoDefault() {
     document.body.style.cursor='default';
     TogglePleaseWait('hidden',false)
}

function DoDefaultWithoutEvent() {
     document.body.style.cursor='default';
     TogglePleaseWait('hidden',true)
}

function TogglePleaseWait(_Visibility, RaiseEvent) {
    var _pleaseWaitObject=$get(CORE_AJAX_PLEASEWAIT_DHTMLOBJECT_ID);
    if (_pleaseWaitObject!=null) {
        if (IS_MODELPOPUP_VISIBLE)
        {
            _CoreModalPopUp.Hide();
        }
        
        _pleaseWaitObject.style.visibility=_Visibility;
        if(CORE_AJAX_LOAD_PLEASEWAIT_ASMODAL) {
            _CoreModalPopUp._PopupControlID=CORE_AJAX_PLEASEWAIT_DHTMLOBJECT_ID;
            if (_Visibility=='visible') {
                _CoreModalPopUp.ShowModal();
            }
            else {
                if (RaiseEvent) {
                _CoreModalPopUp.HideModal();
            }
        else {
            _CoreModalPopUp.Hide();
        }
    }
}

    }
}

/**
 * IsAjaxLibraryLoaded is a boolean indicating wether the AJAX JavaScript
 * libraries have been loaded
 */
var IsAjaxLibraryLoaded=false;

/**
 * Fires when Atlas is loaded
 */
function AjaxOnload() {
       IsAjaxLibraryLoaded=true;
}

/** 
 * Determines if ATLAS has been loaded
 */
function IsAjaxLoaded() {
   return IsAjaxLibraryLoaded;
}


function pageLoad() {
  IsAjaxLibraryLoaded=true;
   MicrosoftFrance.MCS.Commerce.WS.AJAXProject.TopicWebService.set_timeout(WEB_SERVICE_TIMEOUT);
   MicrosoftFrance.MCS.Commerce.WS.AJAXProject.FavoritesWebService.set_timeout(WEB_SERVICE_TIMEOUT);
   MicrosoftFrance.MCS.Commerce.WS.AJAXProject.ProductWebService.set_timeout(WEB_SERVICE_TIMEOUT);
 //MicrosoftFrance.MCS.Commerce.WS.AJAXProject.CustomerWebService.set_timeout(WEB_SERVICE_TIMEOUT);
   MicrosoftFrance.MCS.Commerce.WS.AJAXProject.ShoppingCartWebService.set_timeout(WEB_SERVICE_TIMEOUT);
   MicrosoftFrance.MCS.Commerce.WS.AJAXProject.TopicWebService.set_timeout(WEB_SERVICE_TIMEOUT);
 //MicrosoftFrance.MCS.Commerce.WS.AJAXProject.CustomerWebService.set_path("http://" + location.host + "/ws/ajax/Customer.asmx");
}

function checkemail(value){
  var filter=/^.+@.+\..{2,3}$/
  return (filter.test(value))
}



/* ...... Functions below needs to be revisited ......  */

function MM_findObj(n, d) { //v4.01
        var p,i,x;  if(!d) d=document; if((p=n.indexOf("?"))>0&&parent.frames.length) {
        d=parent.frames[n.substring(p+1)].document; n=n.substring(0,p);}
        if(!(x=d[n])&&d.all) x=d.all[n]; for (i=0;!x&&i<d.forms.length;i++) x=d.forms[i][n];
        for(i=0;!x&&d.layers&&i<d.layers.length;i++) x=MM_findObj(n,d.layers[i].document);
        if(!x && d.getElementById) x=d.getElementById(n); return x;
    }


function MM_showHideLayers() { //v3.0
  var i,p,v,obj,args=MM_showHideLayers.arguments;
  for (i=0; i<(args.length-2); i+=3)
	if ((obj=MM_findObj(args[i]))!=null)
	{
		v=args[i+2];
		if (obj.style)
		{
			obj=obj.style; v=(v=='show')?'visible':(v='hide')?'hidden':v;
		}
		obj.visibility=v;
	}
	//If there's a popup...
	//alert(args[3]);
	if(args[3] != null)
	{
		var layer = MM_findObj(args[0]);
		var popuptxt = MM_findObj(args[3]);
		var oBo = cBB (popuptxt);
		var oBp = cBB (layer);
		var left=0;
		var top=0;
		left=parseInt(oBo.l) + parseInt(popuptxt.offsetWidth) - 50;
		top=parseInt(oBo.t) - parseInt(layer.offsetHeight) + 15;
		if (isNaN(parseInt(left))) return false;
		if (isNaN(parseInt(top))) return false;
		layer.style.left = left + 'px';//40
    	layer.style.top = top +'px';
	}
}

function bx(x,y,w,h)
{
	this.l=x;
	this.r=x+w;
	this.t=y;
	this.b=y+h;
}

function cBB(o)
{
	var b=new bx(0,0,0,0);
	if(!o) return b;
	var x=0,y=0,p=o;
	while(p)
		{
		x+=p.offsetLeft;
		y+=p.offsetTop;
		p=p.offsetParent;
		}
	b.l=x;
	b.t=y;
	b.r=x+o.offsetWidth;
	b.b=y+o.offsetHeight;
	return b;
}
 
 
function formatAsMoney(mnt) {
    mnt -= 0;
    mnt = (Math.round(mnt*100))/100;
    return (mnt == Math.floor(mnt)) ? mnt + '.00' 
              : ( (mnt*10 == Math.floor(mnt*10)) ? 
                       mnt + '0' : mnt);
}

function AJAX_GetTresHoldNumber() {
   var StockTresHold=5;
   if (typeof(OOS_THRESHOLD)!='undefined') { //placed this condition because the treshold was added after the site went live and in case the users have old version of js, the site will still run ok with no js errors.
               StockTresHold=parseInt(OOS_THRESHOLD);
   } 
   return StockTresHold;
}