//-----------------------------------------------------------------
// Licensed Materials - Property of IBM
//
// WebSphere Commerce
//
// (C) Copyright IBM Corp. 2008 All Rights Reserved.
//
// US Government Users Restricted Rights - Use, duplication or
// disclosure restricted by GSA ADP Schedule Contract with
// IBM Corp.
//-----------------------------------------------------------------

/************************************************************************************
 * Common Context Declarations
 * @fileOverview This file provides the common render context variables and functions, 
 * and defines all the render contexts needed throughout the store.
 */

dojo.require("wc.render.common");

/** 
 * @class The CommonContextsJS class defines all the common variables and functions 
 * for the render contexts across all store pages.
 */
CommonContextsJS = {
	/**
	 * This variable stores the ID of the language that the store is currently using.
	 * @private
	 */
	langId: "-1",

	/**
	 * This variable stores the ID of the current store.
	 * @private
	 */	
	storeId: "",

	/**
	 * This variable stores the ID of the catalog that is used in the store.
	 * @private
	 */	
	catalogId: "",

	/** 
	 * Sets the common ids used in the store - language id, store id, and catalog id.
	 * 
	 * @param {string} langId The id of the store language.
	 * @param {string} storeId The id of the store.
	 * @param {string} langId The id of the catalog used in the store.
	 */
	setCommonParameters:function(langId,storeId,catalogId){
			this.langId = langId;
			this.storeId = storeId;
			this.catalogId = catalogId;
	},

	/** 
	 * Updates the specified context's property and assign it the desired value.
	 * 
	 * @param {string} contextId The id of the render context 
	 * @param {string} property The name of the context's property to update
	 * @param {string} value The value to update the specified property to
	 */
	setContextProperty:function(contextId,property,value){
		wc.render.getContextById(contextId).properties[property] = value;
	}

}

/**
 * Declares a new render context for the Shipping Method Selector.
 */
wc.render.declareContext("ShippingMethodSelectorContext",null,""),

/*
 * Declares a new render context for the Mini Shopping Cart.
 */
wc.render.declareContext("MiniShoppingCartContext",{curItemNum: "0"},""),

/**
 * Declares a new render context for Existing addresses in the Shipping and Billing display.
 */
wc.render.declareContext("DSIExistingShipAddrContext",null,""),
/**
 * Declares a new render context for Shipsets display in the multishipping page
 */
wc.render.declareContext("orderItemsByShipSetDisplayContext",null,""),

wc.render.declareContext("ShoppingCartItemDisplayContext",null,""),

wc.render.declareContext("ShoppingCartTotalDisplayContext",null,""),

wc.render.declareContext("ShoppingCartPromoDisplayContext",null,""),

wc.render.declareContext("ShoppingCartFragmentTotalDisplayContext",null,""),

wc.render.declareContext("BillingAddressBookContext",null,""),

wc.render.declareContext("ShipAsBillContext",null,""),

wc.render.declareContext("ShippingAddressBookContext",null,"")

/************************************************************************************
 * Common Controller Declarations
 * @fileOverview This file provides the common controller variables and functions, 
 * and links these controllers to listen to the defined render contexts in CommonContextsDeclarations.js.
 */

/** 
 * @class The CommonControllersDeclarationJS class defines all the common variables and functions 
 * for the controllers of the defined render contexts across all store pages.
 */
CommonControllersDeclarationJS = {
       /**
        * This variable stores the ID of the language that the store is currently using.
        * @private
        */
       langId: "-1",
       
       /**
        * This variable stores the ID of the current store.
        * @private
        */       
       storeId: "",
       
       /**
        * This variable stores the ID of the catalog that is used in the store.
        * @private
        */           
       catalogId: "",
       
       /**
        * This variable indicates whether the Ajax CheckoutOut flex flow is enabled or not.
        * @private
        */           
       ajaxCheckOut: true,
       
       /**
        * Sets the common ids used in the store - language id, store id, and catalog id.
        * 
        * @param {string} langId The id of the store language.
        * @param {string} storeId The id of the store.
        * @param {string} langId The id of the catalog used in the store.
        */
       setCommonParameters:function(langId,storeId,catalogId){
              this.langId = langId;
              this.storeId = storeId;
              this.catalogId = catalogId;
       },
       
       /**
        * Sets the URL of the specified controller.
        * 
        * @param {string} controllerId The id of the target controller.
        * @param {string} url The link to specify for the controller.
        */       
       setControllerURL:function(controllerId,url){
              wc.render.getRefreshControllerById(controllerId).url = url;
       },
       
       setControllerRefreshInfo:function(controllerId,div,msg){
         wc.render.getRefreshControllerById(controllerId).refreshDiv = div;
         wc.render.getRefreshControllerById(controllerId).refreshMsg = msg;
       }

}

/** 
 * Declares a new refresh controller for the Mini Shopping Cart.
 */
wc.render.declareRefreshController({
       id: "miniShopcartTotalAreaController",
       renderContext: wc.render.getContextById("MiniShoppingCartContext"),
       url: "",
       formId: ""
       
       ,renderContextChangedHandler: function(message, widget) {
              var controller = this;
              var renderContext = this.renderContext;

// refresh the mini-cart when user selects another item to view within the mini-cart
			if (controller.testForChangedRC(["curItemNum"])) {
				widget.refresh({"curItemNum":renderContext.properties["curItemNum"]});
			}
       }
       
       /** 
        * Refreshs the mini shopping cart.
        * If a new order item is added via an Ajax service call, set the mini shopping cart to display the new order item in the dropdown.
        * Otherwise, only refresh the contents of mini shopping cart to the updated order information.
        * This function is called when a modelChanged event is detected. 
        * 
        * @param {string} message The model changed event message
        * @param {object} widget The registered refresh area
        */
       ,modelChangedHandler: function(message, widget) {
              var controller = this;
              var renderContext = this.renderContext;
			  var shipOMeterFlag = "false";
//              if(message.actionId in order_updated){
// refresh the mini-cart when user adds an item anywhere or deletes an item from the mini-cart

		        if (typeof(isShipOMeterActive) != "undefined" && isShipOMeterActive ){
		        	shipOMeterFlag = "true";
		        }

				if (message.actionId == "DSIAjaxOrderItemAdd") {
					widget.refresh({"showAdded2Cart":"true","isShipOMeterActive":shipOMeterFlag});
				} else if (message.actionId == "DSIAjaxOrderItemDelete" || message.actionId == "DSIAjaxLogon" ) {
					widget.refresh({"isShipOMeterActive":shipOMeterFlag});
				}								
//              }
       }

       /** 
        * Destroys the old mini shopping cart dialog with previous order information.
        * If order item was added, display the mini shopping cart dropdown with the new order item added contents.
        * This function is called after a successful refresh. 
        * 
        * @param {object} widget The registered refresh area
        */
       ,postRefreshHandler: function(widget) {
              var controller = this;
              var renderContext = this.renderContext;

// below are function calls like ones in slide_config.js to support mini-cart slide panels
				$('.slide1').slidePanel();
				$('.slide_button1').slidePanel({target:'.cartBox', role:'dep', status:'open'});
				$('.slide_button2').slidePanel({target:'.cartBox', role:'master'});
				$('.cartSlide').slidePanel();
// open mini-cart, slidePanel-status:'open' attribute does not work when display:none
				if (eval(document.getElementById("cartBox"))) {
					document.getElementById("cartBox").style.display="block";
				}
//re-enable the add to cart buttons on single and grouped product page and quickview pane
				if( eval(document.getElementById("add2CartButton")) ){
					document.getElementById("add2CartButton").disabled = false;
				}
				if( eval(document.getElementById("add2CartButton1")) ){
					document.getElementById("add2CartButton1").disabled = false;
				}
				if( eval(document.getElementById("add2CartButton2")) ){
					document.getElementById("add2CartButton2").disabled = false;
				}						
// re-enable add to cart function				
				busy = false; 
// re-enable add to cart button				
				removeCartLoad(); 
// add event listener to the minicart button
	miniCartButton = document.getElementById('cartOpenBtn');
	
	if (typeof miniCartButton.addEventListener != 'undefined' ){
	miniCartButton.addEventListener( "click", miniCartButtonClick, false );
	} else {
	// IE support
	miniCartButton.attachEvent( "onclick", miniCartButtonClick );
	}					
	
	callShipOMeter();    
    }

}),

/** 
 * Declares a new refresh controller for the shipping method selector.
 */
wc.render.declareRefreshController({
       id: "ShippingMethodSelectorController",
       renderContext: wc.render.getContextById("ShippingMethodSelectorContext"),
       url: "",
       formId: "",
       refreshDiv: "",
       refreshMsg: ""

       ,renderContextChangedHandler: function(message, widget) {
              var controller = this;
              var renderContext = this.renderContext;
              displayLoadingImage( this.refreshDiv, this.refreshMsg );
              widget.refresh(renderContext.properties);
       }

       ,modelChangedHandler: function(message, widget) {
              var controller = this;
              var renderContext = this.renderContext;

							if ((message.actionId == "DSIAjaxAddressUpdate" && !message.requestProperties.doUpdateOrderItemsAddresses) ||
              		message.actionId == "DSIAjaxUpdateOrderItemsAddressesCtrl" || 
              		message.actionId == "DSIAjaxSetAddressFieldsForAddress") {
              		// avoid refreshing the selector when it is going to redirect to the Billing page 
              		// this is to avoid calling OrderCalculate again to ensure the order will not be unlocked
              		if (typeof message.requestProperties.continueToBilling == "undefined" || !message.requestProperties.continueToBilling) {
              				// avoid refreshing the selector if it is setting a country due to an AjaxAddressAdd
										var doRefresh = true;
										if (message.actionId == "DSIAjaxSetAddressFieldsForAddress" && typeof message.requestProperties.setToDefaultCountry != "undefined") {
											doRefresh = false;
										}
										if (doRefresh) {
			    						displayLoadingImage( this.refreshDiv, this.refreshMsg );                              	        
		              		widget.refresh(renderContext.properties);
	              		}
	            		}
              }
       }
       
       ,postRefreshHandler: function(widget) {
              var controller = this;
              var renderContext = this.renderContext;
              
              selectShippingMethod();
       }
}),

/** 
 * Declares a new refresh controller for the Existing Shipping Address display.
 */
wc.render.declareRefreshController({
       id: "existingShipAddrAreaController",
       renderContext: wc.render.getContextById("DSIExistingShipAddrContext"),
       url: "",
       formId: "",
       refreshDiv: "",
       refreshMsg: ""
       
       ,renderContextChangedHandler: function(message, widget) {
              var controller = this;
              var renderContext = this.renderContext;
       }

      /** 
        * Refreshs the address book in the shipping address refresh area when an update to the address book is made 
        * This function is called when a modelChanged event is detected. 
        * 
        * @param {string} message The model changed event message
        * @param {object} widget The registered refresh area
        */
       ,modelChangedHandler: function(message, widget) {
              var controller = this;
              
              var renderContext = this.renderContext;

							if ((message.actionId == "DSIAjaxAddressUpdate" && !message.requestProperties.doUpdateOrderItemsAddresses) ||
              		message.actionId == "DSIAjaxUpdateOrderItemsAddressesCtrl") {
	              displayLoadingImage( this.refreshDiv, this.refreshMsg );
	              widget.refresh(renderContext.properties);
              } else if (message.actionId == "DSIAjaxAddressAdd") {
              	if (typeof curBillingAddressId != "undefined") {
									widget.refresh(renderContext.properties);
								}	
              }
       }

       ,postRefreshHandler: function(widget) {
              var controller = this;
              var renderContext = this.renderContext;
       
					if (typeof curShipSetSelectedAddressId != "undefined") {
						// curShipSetSelectedAddressId is defined in the DSIMultiShippingAddressesDisplay.jsp
						// re-select the radio button, since the address book area selects only the first addressId from the orderItems
						checkRadioOfExistingAddressId(curShipSetSelectedAddressId);
						changeShippingMethodSelector(curShipSetSelectedAddressId, true, true);
						
						postExistingAddressRefreshHandler();
					}
					if (typeof curBillingAddressId != "undefined") {
						postExistingAddressRefreshHandler();
					}
       }
}),

/** 
 * Declares a new refresh controller for the Existing Shipping Address display.
 */
wc.render.declareRefreshController({
       id: "shippingAddressBookController",
       renderContext: wc.render.getContextById("ShippingAddressBookContext"),
       url: "",
       formId: "",
       refreshDiv: "",
       refreshMsg: ""
       
       ,renderContextChangedHandler: function(message, widget) {
              var controller = this;
              var renderContext = this.renderContext;

       }

      /** 
        * Refreshs the address book in the shipping address refresh area when an update to the address book is made 
        * This function is called when a modelChanged event is detected. 
        * 
        * @param {string} message The model changed event message
        * @param {object} widget The registered refresh area
        */
       ,modelChangedHandler: function(message, widget) {
       				
              var controller = this;
              
              var renderContext = this.renderContext;

							//if ((message.actionId == "DSIAjaxAddressUpdate" && !message.requestProperties.doUpdateOrderItemsAddresses) ||	message.actionId == "DSIAjaxUpdateOrderItemsAddressesCtrl") {
							if (message.actionId == "DSIAjaxAddressUpdate") {
								//alert("Hello");
								//renderContext.properties["selectedAddressId"] = singleShipAddressId;
								//alert(message.requestProperties);
								displayLoadingImage( this.refreshDiv, this.refreshMsg );
								ShowAndRequire.selectedShippingAddress = message.requestProperties.newAddressId;
	              widget.refresh(renderContext.properties);
              }
       }

       ,postRefreshHandler: function(widget) {
              var controller = this;
              var renderContext = this.renderContext;
            
            	jQuery.livequery.run();
       }
       
}),

/** 
 * Declares a new refresh controller for the  Billing Address display on Quick Checkout
 */
wc.render.declareRefreshController({
       id: "billingAddressBookController",
       renderContext: wc.render.getContextById("BillingAddressBookContext"),
       url: "",
       formId: "",
       addressEntryFormName: "",
       refreshDiv: "",
       refreshMsg: ""
       
       ,renderContextChangedHandler: function(message, widget) {
              var controller = this;
              var renderContext = this.renderContext;

       }

      /** 
        * Refreshs the address book in the shipping address refresh area when an update to the address book is made 
        * This function is called when a modelChanged event is detected. 
        * 
        * @param {string} message The model changed event message
        * @param {object} widget The registered refresh area
        */
       ,modelChangedHandler: function(message, widget) {
              var controller = this;
              
              var renderContext = this.renderContext;
							if (message.actionId == "DSIAjaxAddressUpdate") {
								if (typeof message.requestProperties.continueToBilling == "undefined" || !message.requestProperties.continueToBilling) {
					        displayLoadingImage( this.refreshDiv, this.refreshMsg );
					        ShowAndRequire.selectedBillingAddress = message.requestProperties.newAddressId;
	              	widget.refresh(renderContext.properties);
	              }
							} else if (message.actionId == "DSIAjaxAddressAdd") {
								if (typeof message.requestProperties.continueToBilling != "undefined" && message.requestProperties.continueToBilling) {
									if (message.requestProperties.formName == 'newBillAddrForm') {
						        displayLoadingImage( this.refreshDiv, this.refreshMsg );
						        ShowAndRequire.selectedBillingAddress = message.requestProperties.newAddressId;
										this.addressEntryFormName = 'newBillAddrForm';
	
		              	widget.refresh(renderContext.properties);
	              	}
	              }
							}
       }

       ,postRefreshHandler: function(widget) {
              var controller = this;
              var renderContext = this.renderContext;
              jQuery.livequery.run();

							if (typeof this.addressEntryFormName != "undefined" && this.addressEntryFormName == 'newBillAddrForm') {
								// When a new billing address is added after shopper clicks 'Continue" in the Quick Cart page
								ShowAndRequire.hideNewBillingAddress();
								ShowAndRequire.showExistingBillingAddress();
								ShowAndRequire.lastStateBillingAddress = 'exist';
								selectExistingBillingAddress(ShowAndRequire.selectedBillingAddress);
								pw_showPanelConditional(proceedToPayment(document.forms['quickCartForm']));
							}

       }
}),

wc.render.declareRefreshController({
       id: "shipAsBillController",
       renderContext: wc.render.getContextById("ShipAsBillContext"),
       url: "",
       formId: ""
	   
	   ,renderContextChangedHandler: function(message, widget) {
              var controller = this;
              var renderContext = this.renderContext;

       }   
       
       ,modelChangedHandler: function(message, widget) {
              var controller = this;
              
              var renderContext = this.renderContext;
  			  if (message.actionId == "DSIAjaxAddressUpdate") {
				  if (typeof message.requestProperties.continueToBilling == "undefined" || !message.requestProperties.continueToBilling) {					        
	               	  widget.refresh(renderContext.properties);
                  }
			  }
       }
       
       ,postRefreshHandler: function(widget) {
              var controller = this;
              var renderContext = this.renderContext;
              jQuery.livequery.run();
              syncShippingAddrInfo();
            
       }
}),

/** 
 * Declares a new refresh controller for the shipSets display in the multishipping page.
 */
wc.render.declareRefreshController({
       id: "orderItemsByShipSetDisplayController",
       renderContext: wc.render.getContextById("orderItemsByShipSetDisplayContext"),
       url: "",
       formId: "",
       refreshDiv: "",
       refreshMsg: ""
       
       ,renderContextChangedHandler: function(message, widget) {
              var controller = this;
              var renderContext = this.renderContext;
       }

      /** 
        * This function is called when a modelChanged event is detected. 
        * 
        * @param {string} message The model changed event message
        * @param {object} widget The registered refresh area
        */
       ,modelChangedHandler: function(message, widget) {
            var controller = this;
            var renderContext = this.renderContext;

			if (message.actionId == "DSIAjaxOrderCalculate") {
				if (typeof currentStep != "undefined" && currentStep == "3") {
	              	displayLoadingImage( this.refreshDiv, this.refreshMsg );
	              	widget.refresh(renderContext.properties);
	           	}
            }
       }

       ,postRefreshHandler: function(widget) {
              var controller = this;
              var renderContext = this.renderContext;       
       }
}),
/** 
 * Declares a new refresh controller for the Shopping Cart.
 */
wc.render.declareRefreshController({
       id: "shoppingCartItemDisplayController",
       renderContext: wc.render.getContextById("ShoppingCartItemDisplayContext"),
       url: "",
       formId: "",
       refreshDiv: "",
       refreshMsg: "" 

       
       /** 
        * Refreshs the shopping cart.
        * 
        * @param {string} message The model changed event message
        * @param {object} widget The registered refresh area
        */
       ,modelChangedHandler: function(message, widget) {
              var controller = this;
              var renderContext = this.renderContext;

//              if(message.actionId in order_updated){
// refresh the mini-cart when user adds an item anywhere or deletes an item from the mini-cart
//if((message.actionId == 'DSIAjaxOrderCalculate') || (message.actionId = 'DSIAjaxMultiOrderItemDelete')){
				if(message.actionId == 'DSIAjaxOrderCalculate'){
						displayLoadingImage( this.refreshDiv, this.refreshMsg );
						
						var params = [];
						params["storeId"] = message.storeId;
						params["catalogId"] = message.catalogId;
						params["langId"] = message.langId;
						params["orderId"]		= message.orderId;
						widget.refresh(params);									
				}
       }
       
       ,postRefreshHandler: function(widget) {
       		jQuery.livequery.run();
       		if (document.getElementById("topLoginButton") != null && document.getElementById("bottomLoginButton") != null) {
       			editLoginButtons();
       		}
      	}
}),

/** 
 * Declares a new refresh controller for the Shopping Cart.
 */
wc.render.declareRefreshController({
       id: "shoppingCartFragmentTotalDisplayController",
       renderContext: wc.render.getContextById("ShoppingCartFragmentTotalDisplayContext"),
       url: "",
       formId: "",
       refreshDiv: "",
       refreshMsg: ""
              
       /** 
        * Refreshs the shopping cart.
        * 
        * @param {string} message The model changed event message
        * @param {object} widget The registered refresh area
        */
       ,modelChangedHandler: function(message, widget) {
            var controller = this;
            var renderContext = this.renderContext;

//              if(message.actionId in order_updated){
// refresh the mini-cart when user adds an item anywhere or deletes an item from the mini-cart
//if((message.actionId == 'DSIAjaxOrderCalculate') || (message.actionId = 'DSIAjaxMultiOrderItemDelete')){
			if(message.actionId == 'DSIAjaxOrderCalculate'){
				var params = [];
				params["storeId"] = message.storeId;
				params["catalogId"] = message.catalogId;
				params["langId"] = message.langId;
				params["orderId"]		= message.orderId;
				displayLoadingImage( this.refreshDiv, this.refreshMsg );
				widget.refresh(params);								
			}							
       }
       
       ,postRefreshHandler: function(widget) {
       		//jQuery.livequery.run();
      	}
}),

/** 
 * Declares a new refresh controller for the Shopping Cart.
 */
wc.render.declareRefreshController({
       id: "shoppingCartTotalDisplayController",
       renderContext: wc.render.getContextById("ShoppingCartTotalDisplayContext"),
       url: "",
       formId: ""
              
       /** 
        * Refreshs the shopping cart.
        * 
        * @param {string} message The model changed event message
        * @param {object} widget The registered refresh area
        */
       ,modelChangedHandler: function(message, widget) {
            var controller = this;
            var renderContext = this.renderContext;

//              if(message.actionId in order_updated){
// refresh the mini-cart when user adds an item anywhere or deletes an item from the mini-cart
// if((message.actionId == 'DSIAjaxOrderCalculate') || (message.actionId = 'DSIAjaxMultiOrderItemDelete')){
		 	if(message.actionId == 'DSIAjaxOrderCalculate'){	
				var params = [];
				params["storeId"] = message.storeId;
				params["catalogId"] = message.catalogId;
				params["langId"] = message.langId;
				params["orderId"]		= message.orderId;
				widget.refresh(params);								
			}								
       }
       
       ,postRefreshHandler: function(widget) {
       		jQuery.livequery.run();
			callShipOMeter();
      	}       
}),

/** 
 * Declares a new refresh controller for the Shopping Cart Promo Display.
 */
wc.render.declareRefreshController({
       id: "shoppingCartPromoDisplayController",
       renderContext: wc.render.getContextById("ShoppingCartPromoDisplayContext"),
       url: "",
       formId: ""       
       
       /** 
        * Refreshs the shopping cart.
        * 
        * @param {string} message The model changed event message
        * @param {object} widget The registered refresh area
        */
       ,modelChangedHandler: function(message, widget) {
            var controller = this;
            var renderContext = this.renderContext;

//              if(message.actionId in order_updated){
// refresh the mini-cart when user adds an item anywhere or deletes an item from the mini-cart
			if(message.actionId == 'DSIAjaxOrderCalculate'){									
				var params = [];
				params["storeId"] = message.storeId;
				params["catalogId"] = message.catalogId;
				params["langId"] = message.langId;
				params["orderId"]		= message.orderId;
				widget.refresh(params);								
			}								
       }
       
       ,postRefreshHandler: function(widget) {
       		jQuery.livequery.run();
      	}           
})

/************************************************************************************
 * Services Declarations
 * @fileOverview This class contains declarations of AJAX services
 */

dojo.require("wc.service.common");

/**
 * @class This class stores common parameters needed to make the service call.
 */
ServicesDeclarationJS = {
	langId: "-1", /* language of the  store */
	storeId: "", /*numeric unique identifier of the store */
	catalogId: "", /*catalog of the store that is currently in use */

	/**
	 * Sets common parameters used by the services
	 * @param (int) langId The language of the store.
	 * @param (int) storeId The store currently in use.
	 * @param (int) catalogId The catalog of the store currently in use.
	 */
	setCommonParameters:function(langId,storeId,catalogId){
			this.langId = langId;
			this.storeId = storeId;
			this.catalogId = catalogId;
	}
}

	/**
	 * Add an item to a shopping cart in Ajax mode. A message is displayed after
	 * the service call.
	 * @constructor
	 */
	wc.service.declare({
		id: "DSIAjaxOrderItemAdd",
		actionId: "DSIAjaxOrderItemAdd",
		url: getAbsoluteURL() + "DSIAjaxOrderItemAdd",
		formId: ""

     /**
     * display a success message
     * @param (object) serviceResponse The service response object, which is the
     * JSON object returned by the service invocation
     */

		,successHandler: function(serviceResponse) {
		  $('#cluetip').hide();
			if (document.cookie.indexOf("osc_scOpen=") < 0){document.cookie = "osc_scOpen=1;expires=";scOpen=',scOpen';}else{document.cookie = "osc_scOpen=0;expires=";scOpen='';}
				s_omni.temp_linkTrackVars=s_omni.linkTrackVars;
				s_omni.temp_linkTrackEvents=s_omni.linkTrackEvents;
				s_omni.linkTrackVars=s_omni.linkTrackVars+',events';
				s_omni.linkTrackEvents='scAdd'+scOpen;
		        s_omni.events=s_omni.linkTrackEvents;
				s_omni.products=serviceResponse.oscTag_pr;
				s_omni.prop4="minicart";
				s_omni.tl(this, 'o', 'AddToMiniCart');
				s_omni.linkTrackVars=s_omni.temp_linkTrackVars;
				s_omni.linkTrackEvents=s_omni.temp_linkTrackEvents;	
				var params = [];
				params["storeId"] = serviceResponse.requestProperties["storeId"];
				params["catalogId"] = serviceResponse.requestProperties["catalogId"];
				params["langId"] = serviceResponse.requestProperties["langId"];
				params["orderId"]		= serviceResponse.requestProperties["orderId"];
				params["calculationUsageId"] = "-1";
				//params["doPrice"] = "Y";
				wc.service.invoke("DSIAjaxOrderCalculate", params);			
		}
     /**
     * display an error message
     * @param (object) serviceResponse The service response object, which is the
     * JSON object returned by the service invocation
     */
		,failureHandler: function(serviceResponse) {
			showErrorMessage(serviceResponse.dsiErrorMessage, "errMsgArea");
// re-enable the add to cart buttons on single and grouped product page and quickview pane
			if( eval(document.getElementById("add2CartButton")) ){
				document.getElementById("add2CartButton").disabled = false;
			}
			if( eval(document.getElementById("add2CartButton1")) ){
				document.getElementById("add2CartButton1").disabled = false;
			}
			if( eval(document.getElementById("add2CartButton2")) ){
				document.getElementById("add2CartButton2").disabled = false;
			}						
// re-enable add to cart function
			busy = false;
// re-enable add to cart button			
			removeCartLoad();								
		}

	}),

	/**
	 * Update cart via Ajax
	 * TODO: this may be replaced/merged by the definition used by Craig/Rita since success/failure handlers may be different based on which page we are on. maybe makes sense to define separate service, but re-use same Ajax command
	 */
	wc.service.declare({
		id: "DSIAjaxOrderItemUpdate",
		actionId: "DSIAjaxOrderItemUpdate",
		url: getAbsoluteURL() + "DSIAjaxOrderItemUpdate",
		formId: ""

     /**
     * display a success message
     * @param (object) serviceResponse The service response object, which is the
     * JSON object returned by the service invocation
     */

		,successHandler: function(serviceResponse) {
			if ((document.location.href.indexOf("DSIShoppingCartDisplay") > -1) && (serviceResponse.requestProperties.orderEmpty == '1')) {
				cursor_clear();
			} else {
				// cursor_clear() is done in DSIAjaxOrdreCalculate
				if(submitRequest()){
					// re-enable the cursor if it was not set in the previous action
					cursor_wait(false);
				}
			}
			
			if (typeof curShipSetSelectedAddressId != "undefined") {
				// Step 2 of the multishipping page
				postAjaxOrderItemUpdateFromStep2(true, serviceResponse.requestProperties.orderItemId);
			}
			
			var params = [];
			params["storeId"] = serviceResponse.requestProperties["storeId"];
			params["catalogId"] = serviceResponse.requestProperties["catalogId"];
			params["langId"] = serviceResponse.requestProperties["langId"];
			params["orderId"]		= serviceResponse.requestProperties["orderId"];
			params["calculationUsageId"] = "-1";
			//params["doPrice"] = "Y";
			
			if((document.location.href.indexOf("DSIShoppingCartDisplay") > -1) && (serviceResponse.requestProperties.orderEmpty == '1')){
				//alert("document.location.href: " + document.location.href);
				document.location.href = "DSIOrderItemDisplay?storeId=" + serviceResponse.requestProperties["storeId"] + "&catalogId=" + serviceResponse.requestProperties["catalogId"] + "&langId=" + serviceResponse.requestProperties["langId"] + "&orderId=.";
			}
			else{
					wc.service.invoke("DSIAjaxOrderCalculate", params);
			}
		}
     /**
     * display an error message
     * @param (object) serviceResponse The service response object, which is the
     * JSON object returned by the service invocation
     */
		,failureHandler: function(serviceResponse) {
			cursor_clear();
			showErrorMessage(serviceResponse.dsiErrorMessage, "errMsgArea");
		}

	}),

	/**
	 * Update orderitem without shipping validation via Ajax
	 */
	wc.service.declare({
		id: "AjaxOrderItemUpdate",
		actionId: "AjaxOrderItemUpdate",
		url: getAbsoluteURL() + "AjaxOrderItemUpdate",
		formId: ""

     /**
     * display a success message
     * @param (object) serviceResponse The service response object, which is the
     * JSON object returned by the service invocation
     */

		,successHandler: function(serviceResponse) {
			if (typeof curShipSetSelectedAddressId != "undefined") {
				// cursor_clear() is done in DSIAjaxOrdreCalculate
				//cursor_clear();
				var params = [];
				params["storeId"] = serviceResponse.requestProperties["storeId"];
				params["catalogId"] = serviceResponse.requestProperties["catalogId"];
				params["langId"] = serviceResponse.requestProperties["langId"];
				params["orderId"]		= serviceResponse.requestProperties["orderId"];
				params["calculationUsageId"] = "-1";
				//params["doPrice"] = "Y";
				wc.service.invoke("DSIAjaxOrderCalculate", params);
			}
		}
     /**
     * display an error message
     * @param (object) serviceResponse The service response object, which is the
     * JSON object returned by the service invocation
     */
		,failureHandler: function(serviceResponse) {
			showErrorMessage(serviceResponse.dsiErrorMessage, "errMsgArea");
		}

	}),

	/**
	 * Update orderitem without shipping validation via Ajax
	 */
	wc.service.declare({
		id: "DSIAjaxD23OrderItemCheck",
		actionId: "DSIAjaxD23OrderItemCheck",
		url: getAbsoluteURL() + "DSIAjaxD23OrderItemCheck",
		formId: ""

     /**
     * display a success message
     * @param (object) serviceResponse The service response object, which is the
     * JSON object returned by the service invocation
     */
		,successHandler: function(serviceResponse) {
			cursor_clear();
			if (typeof serviceResponse.requestProperties.pageId != "undefined") { 
				if (serviceResponse.requestProperties.pageId == 'shoppingCart') {
					proceedBeginCheckout();
				}
			}
		}

     /**
     * display an error message
     * @param (object) serviceResponse The service response object, which is the
     * JSON object returned by the service invocation
     */
		,failureHandler: function(serviceResponse) {
			cursor_clear();
			showErrorMessage(serviceResponse.dsiErrorMessage, "alertBox");
		}

	}),

	/**
	 * Split orderitem via Ajax
	 */
	wc.service.declare({
		id: "DSIAjaxOrderItemSplit",
		actionId: "DSIAjaxOrderItemSplit",
		url: getAbsoluteURL() + "DSIAjaxOrderItemSplit",
		formId: ""

     /**
     * display a success message
     * @param (object) serviceResponse The service response object, which is the
     * JSON object returned by the service invocation
     */

		,successHandler: function(serviceResponse) {
			var fromOrderItemId = serviceResponse.requestProperties.fromOrderItemId;
			var oderItemId = serviceResponse.requestProperties.orderItemId;

			cursor_clear();			
			if (typeof curShipSetSelectedAddressId != "undefined") {
				// Step 2 of multiship page
				postAjaxOrderItemSplit(serviceResponse.requestProperties.fromOrderItemId, serviceResponse.requestProperties.orderItemId)
			}
		}
     /**
     * display an error message
     * @param (object) serviceResponse The service response object, which is the
     * JSON object returned by the service invocation
     */
		,failureHandler: function(serviceResponse) {
			cursor_clear();
		}

	}),

	/**
	 * Logon shopper using Ajax.
	 * @constructor
	 */
	wc.service.declare({
		id: "DSIAjaxLogon",
		actionId: "DSIAjaxLogon",
		url: getAbsoluteURL() + "DSIAjaxLogon",
		formId: ""

     /**
     * display a success message
     * @param (object) serviceResponse The service response object, which is the
     * JSON object returned by the service invocation
     */
		,successHandler: function(serviceResponse) {
		}
     /**
     * display an error message
     * @param (object) serviceResponse The service response object, which is the
     * JSON object returned by the service invocation
     */
		,failureHandler: function(serviceResponse) {
		}

	}),

	/**
	 * Logon shopper using Ajax.
	 * @constructor
	 */
	wc.service.declare({
		id: "DSIAjaxUserRegistrationAdd",
		actionId: "DSIAjaxUserRegistrationAdd",
		url: getAbsoluteURL() + "DSIAjaxUserRegistrationAdd",
		formId: ""

     /**
     * display a success message
     * @param (object) serviceResponse The service response object, which is the
     * JSON object returned by the service invocation
     */
		,successHandler: function(serviceResponse) {
		}
     /**
     * display an error message
     * @param (object) serviceResponse The service response object, which is the
     * JSON object returned by the service invocation
     */
		,failureHandler: function(serviceResponse) {
		}

	}),

	/**
	 * Update address using Ajax.
	 * @constructor
	 */
	wc.service.declare({
		id: "DSIAjaxAddressUpdate",
		actionId: "DSIAjaxAddressUpdate",
		url: getAbsoluteURL() + "DSIAjaxAddressUpdate",
		formId: "",
		oldAddressId: "",
		continueToBilling: false,
		addressEntryFormName: "",
		formSuffix: ""

     /**
     * display a success message
     * @param (object) serviceResponse The service response object, which is the
     * JSON object returned by the service invocation
     */
		,successHandler: function(serviceResponse) {
			// remove the modal in the Shipping Address page
			tb_remove();
			if (typeof curBillingAddressId != "undefined") {
				// cursor_clear() perform after if the page does not require a refresh
			} else {
				cursor_clear();
			}

			if (document.getElementById("newShippingAddress")) {
				hideNewShipAddrForm(null,null);
			}
			if ((document.getElementById("addrBookArea")) || (document.getElementById("shippingAddressBookArea"))) {				
				if (typeof singleShipAddressId != "undefined") {
					// singleShipAddressId is defined in the DSISingleShippingAddressDisplay.jsp
					serviceResponse.requestProperties['continueToBilling'] = continueToBilling;
					if (singleShipAddressId != oldAddressId) {
						// addressId of orderitems have not been updated during the ajax call of DSIAjaxAddressUpdate
						// calling it explicitly
						serviceResponse.requestProperties['doUpdateOrderItemsAddresses'] = true;
						AjaxUpdateOrderItemsAddresses(singleShipAddressId, serviceResponse.requestProperties.newAddressId);
					} else {
						serviceResponse.requestProperties['doUpdateOrderItemsAddresses'] = false;
					}
					if (typeof defaultShipAddressId != "undefined" && defaultShipAddressId == oldAddressId) {
						defaultShipAddressId = serviceResponse.requestProperties.newAddressId;
					}
					singleShipAddressId = serviceResponse.requestProperties.newAddressId;
				} else if (typeof curShipSetSelectedAddressId != "undefined") {
					// curShipSetSelectedAddressId is defined in the DSIMultiShippingAddressesDisplay.jsp
					curShipSetSelectedAddressId = serviceResponse.requestProperties.newAddressId;
				}
			} else if (document.getElementById("addressBookArea")) {
				// addressBookArea is in the DSICartBillingDisplay page
				if (typeof curBillingAddressId != "undefined") {
					curBillingAddressId = serviceResponse.requestProperties.newAddressId;
					// refresh page when the updated address is an address for any orderitem in this order
					if (typeof shipSetAddressIds != "undefined") {
						
						var isEditedShippingAddress = false;
						for (var i=0; i < shipSetAddressIds.length; i++) {
							if (shipSetAddressIds[i] == oldAddressId) {
								isEditedShippingAddress = true;
								break;
							}
						}
						if (isEditedShippingAddress) {
							replaceShipSetAddressIds(oldAddressId, curBillingAddressId)
							document.location.href = getBillingURL()+"&curBillingAddressId="+curBillingAddressId;
						} else {
							cursor_clear();
						}
					}
				}
			}
			busy = false;
			
			if((typeof ShowAndRequire != "undefined" && typeof ShowAndRequire.selectedBillingAddress != "undefined") && (ShowAndRequire.selectedBillingAddress == serviceResponse.requestProperties.oldAddressId)){
				ShowAndRequire.selectedBillingAddress = serviceResponse.requestProperties.newAddressId;
			}
			
			if(typeof ShowAndRequire != "undefined" && typeof ShowAndRequire.selectedShippingAddress != "undefined"){
				ShowAndRequire.selectedShippingAddress = serviceResponse.requestProperties.newAddressId;
			}
			
			if (continueToBilling) {
				if (typeof curShipSetSelectedAddressId != "undefined") {
					// curShipSetSelectedAddressId is defined in the DSIMultiShippingAddressesDisplay.jsp
					curShipSetSelectedAddressId = serviceResponse.requestProperties.newAddressId;	
				} else {
					if (document.getElementById("shippingAddressBookArea")) {
						// quick checkout page
						postAjaxAddressUpdate(continueToBilling);
					} else {
						// single shipping page or others
						redirectToBillingURL();
					}
				}
			}
		}
     /**
     * display an error message
     * @param (object) serviceResponse The service response object, which is the
     * JSON object returned by the service invocation
     */
		,failureHandler: function(serviceResponse) {
			// re-enable the button
			busy = false;
			cursor_clear();
			if (serviceResponse.errorMessageKey == '_ERR_ADDR_CMD_VERIFICATION_PARAM_2' ||
					serviceResponse.errorMessageKey == '_ERR_ADDR_CMD_VERIFICATION_PARAM_1') {
				openAddressQASModal(formSuffix, serviceResponse.exceptionData);
			} else if (serviceResponse.errorMessageKey == '_ERR_ADDR_CMD_BAD_WORD_PARAM') {
				if (document.getElementById("addrformErrMsgArea"+formSuffix)) {
					showErrorMessage(serviceResponse.dsiErrorMessage, "addrformErrMsgArea"+formSuffix);
					if (typeof addressEntryFormName != "undefined") {
						repopulateFieldsFromExceptionData(addressEntryFormName, formSuffix, serviceResponse.exceptionData);
					}
				}
			} else if (document.getElementById("addrformErrMsgArea"+formSuffix)) {
				showErrorMessage(serviceResponse.dsiErrorMessage, "addrformErrMsgArea"+formSuffix);
			}
		}
		
		,validateParameters: function(parameters) {
			oldAddressId = parameters["addressId"];
			if (typeof parameters["formSuffix"] != "undefined") {
				formSuffix = parameters["formSuffix"];
			}
			if (typeof parameters["continueToBilling"] != "undefined") {
				continueToBilling = parameters["continueToBilling"];
			}
			if (typeof parameters["formName"] != "undefined") {
				addressEntryFormName = parameters["formName"];
			}
			return true;
		}

	}),

	/**
	 * Add address using Ajax.
	 * @constructor
	 */
	wc.service.declare({
		id: "DSIAjaxAddressAdd",
		actionId: "DSIAjaxAddressAdd",
		url: getAbsoluteURL() + "DSIAjaxAddressAdd",
		formId: "",
		addressEntryFormName: "",
		formSuffix: ""

     /**
     * display a success message
     * @param (object) serviceResponse The service response object, which is the
     * JSON object returned by the service invocation
     */
		,successHandler: function(serviceResponse) {
			tb_remove();
			cursor_clear();
			
			// In the Single Shipping Address Page
			if (eval(document.getElementById("newShippingAddress"))) {
				if (typeof singleShipAddressId != "undefined") {
					if (typeof checkoutPageName != "undefined" && checkoutPageName == 'QuickCheckout') {
						if (addressEntryFormName == 'newShipAddrForm') {
							AjaxSetAddressToDefaultCountry(addressEntryFormName, serviceResponse.requestProperties.newAddressId);
			
							// displays the new address form area
							displayNewShipAddrForm(addressEntryFormName);
							
							// updates hidden fields in the shipping address form
							updateNewAddrForm(addressEntryFormName, "addressId", serviceResponse.requestProperties.newAddressId);
							
							// addressId of orderitems have not been updated during the ajax call of DSIAjaxAddressUpdate
							// calling it explicitly
							AjaxUpdateOrderItemsAddresses(singleShipAddressId, serviceResponse.requestProperties.newAddressId);
							
							singleShipAddressId = serviceResponse.requestProperties.newAddressId;
						}
					} else {
						// singleShipAddressId is defined in DSISingleShippingAddressDisplay.jsp
						// sets the new address to a deafult country
						AjaxSetAddressToDefaultCountry(serviceResponse.requestProperties.newAddressId);
		
						// displays the new address form area
						displayNewShipAddrForm();
						
						// updates hidden fields in the shipping address form
						updateNewShipAddrForm("addressId", serviceResponse.requestProperties.newAddressId);
						
						// addressId of orderitems have not been updated during the ajax call of DSIAjaxAddressUpdate
						// calling it explicitly
						AjaxUpdateOrderItemsAddresses(singleShipAddressId, serviceResponse.requestProperties.newAddressId);
						
						singleShipAddressId = serviceResponse.requestProperties.newAddressId;
					}
				} else if (typeof curShipSetSelectedAddressId != "undefined") {
					// curShipSetSelectedAddressId is defined in the DSIMultiShippingAddressesDisplay.jsp
					// updates hidden fields in the shipping address form
					AjaxSetAddressToDefaultCountry(serviceResponse.requestProperties.newAddressId);
					updateNewShipAddrForm("addressId", serviceResponse.requestProperties.newAddressId);
					curShipSetSelectedAddressId = serviceResponse.requestProperties.newAddressId;
				}
			}
			
			// In the Billing / Payment Page
			if (document.getElementById("newBillingAddress")) {
				if (typeof curBillingAddressId != "undefined") {
					curBillingAddressId = serviceResponse.requestProperties.newAddressId;
				}
				// call proceedToPayment(form) after existing address refresh area is refreshed
			}
			
			// From the Billing Address Form of the Quick Checkout Page
			if (typeof checkoutPageName != "undefined" && checkoutPageName == 'QuickCheckout') {
				if (addressEntryFormName == 'newBillAddrForm') {
					ShowAndRequire.selectedBillingAddress = serviceResponse.requestProperties.newAddressId;
				}
			}

			addBusy = false;
		}
		
     /**
     * display an error message
     * @param (object) serviceResponse The service response object, which is the
     * JSON object returned by the service invocation
     */
		,failureHandler: function(serviceResponse) {
			addBusy = false;
			cursor_clear();
			if (serviceResponse.errorMessageKey == '_ERR_ADDR_CMD_VERIFICATION_PARAM_2' ||
				serviceResponse.errorMessageKey == '_ERR_ADDR_CMD_VERIFICATION_PARAM_1') {
				openAddressQASModal(formSuffix, serviceResponse.exceptionData);
			} else if (serviceResponse.errorMessageKey == '_ERR_ADDR_CMD_BAD_WORD_PARAM') {
				if (document.getElementById("addrformErrMsgArea"+formSuffix)) {
					showErrorMessage(serviceResponse.dsiErrorMessage, "addrformErrMsgArea"+formSuffix);
					if (typeof addressEntryFormName != "undefined") {
						repopulateFieldsFromExceptionData(addressEntryFormName, formSuffix, serviceResponse.exceptionData);
					}
				}
			} else if (document.getElementById("addrformErrMsgArea"+formSuffix)) {
				showErrorMessage(serviceResponse.dsiErrorMessage, "addrformErrMsgArea"+formSuffix);
			}

		}

		,validateParameters: function(parameters) {
			if (typeof parameters["formSuffix"] != "undefined") {
				formSuffix = parameters["formSuffix"];
			}
			if (typeof parameters["formName"] != "undefined") {
				addressEntryFormName = parameters["formName"];
			}
			return true;
		}

	}),

	/**
	 * Delete address using Ajax.
	 * @constructor
	 */
	wc.service.declare({
		id: "AjaxAddressDelete",
		actionId: "AjaxAddressDelete",
		url: getAbsoluteURL() + "AjaxAddressDelete",
		formId: ""

     /**
     * display a success message
     * @param (object) serviceResponse The service response object, which is the
     * JSON object returned by the service invocation
     */
		,successHandler: function(serviceResponse) {
			if (typeof curShipSetSelectedAddressId != "undefined") {
				postAjaxAddressDeleteFromStep1();
			}
		}
     /**
     * display an error message
     * @param (object) serviceResponse The service response object, which is the
     * JSON object returned by the service invocation
     */
		,failureHandler: function(serviceResponse) {
		}

	}),
	
		/**
	 * Update orderitem address using Ajax.
	 * @constructor
	 */
	wc.service.declare({
		id: "DSIAjaxUpdateOrderItemsAddressesCtrl",
		actionId: "DSIAjaxUpdateOrderItemsAddressesCtrl",
		url: getAbsoluteURL() + "DSIAjaxUpdateOrderItemsAddressesCtrl",
		formId: ""

     /**
     * display a success message
     * @param (object) serviceResponse The service response object, which is the
     * JSON object returned by the service invocation
     */
		,successHandler: function(serviceResponse) {
			singleShipAddressId = serviceResponse.requestProperties.newAddressId;
			cursor_clear();
		}
     /**
     * display an error message
     * @param (object) serviceResponse The service response object, which is the
     * JSON object returned by the service invocation
     */
		,failureHandler: function(serviceResponse) {
			cursor_clear();
		}

	}),

		/**
	 * Update address fields of an address using Ajax.
	 * @constructor
	 */
	wc.service.declare({
		id: "DSIAjaxSetAddressFieldsForAddress",
		actionId: "DSIAjaxSetAddressFieldsForAddress",
		url: getAbsoluteURL() + "DSIAjaxSetAddressFieldsForAddress",
		formId: ""

     /**
     * display a success message
     * @param (object) serviceResponse The service response object, which is the
     * JSON object returned by the service invocation
     */
		,successHandler: function(serviceResponse) {
			cursor_clear();
			if (typeof curShipSetSelectedAddressId != "undefined") {
				if (typeof serviceResponse.requestProperties.fromAddressAdd != "undefined" && serviceResponse.requestProperties.fromAddressAdd == "true") {
				// displays the new address form area				
				displayNewShipAddrForm();
				}
			}
		}
     /**
     * display an error message
     * @param (object) serviceResponse The service response object, which is the
     * JSON object returned by the service invocation
     */
		,failureHandler: function(serviceResponse) {
			cursor_clear();
		}

	}),
	
	/**
	 * Postal code lookup using Ajax.
	 * @constructor
	 */
	wc.service.declare({
		id: "DSIAjaxPostalCodeLookup",
		actionId: "DSIAjaxPostalCodeLookup",
		url: getAbsoluteURL() + "DSIAjaxPostalCodeLookup",
		formId: ""

     /**
     * display a success message
     * @param (object) serviceResponse The service response object, which is the
     * JSON object returned by the service invocation
     */
		,successHandler: function(serviceResponse) {
			pcluLookupResults[serviceResponse.requestProperties.suffix] = serviceResponse.requestProperties.PCLUResults;
			if (typeof serviceResponse.requestProperties.moniker != "undefined") {
				populateFieldsFromPCLUResultsForMoniker(serviceResponse.requestProperties.formName, serviceResponse.requestProperties.suffix, serviceResponse.requestProperties.actualResultSize, serviceResponse.requestProperties.moniker);
			} else {
				postDSIAjaxPostalCodeLookup(serviceResponse.requestProperties.formName, serviceResponse.requestProperties.suffix, serviceResponse.requestProperties.actualResultSize);
			}
			cursor_clear();
		}
     /**
     * display an error message
     * @param (object) serviceResponse The service response object, which is the
     * JSON object returned by the service invocation
     */
		,failureHandler: function(serviceResponse) {
			cursor_clear();
		}

	}),
	/**
	 * Remove an item from shopping cart. A message is displayed after the service
	 * call.
	 * @constructor
	 */
	wc.service.declare({
		id: "DSIAjaxOrderItemDelete",
		actionId: "DSIAjaxOrderItemDelete",
		url: getAbsoluteURL() + "DSIAjaxOrderItemDelete",
		formId: ""
    /**
     * display a success message
     * @param (object) serviceResponse The service response object, which is the
     * JSON object returned by the service invocation
     */
		,successHandler: function(serviceResponse) {
			s_omni.temp_linkTrackVars=s_omni.linkTrackVars;
			s_omni.temp_linkTrackEvents=s_omni.linkTrackEvents;
			s_omni.linkTrackVars=s_omni.linkTrackVars+',events';
			s_omni.linkTrackEvents='scRemove';
			s_omni.events=s_omni.linkTrackEvents;
			s_omni.products=serviceResponse.oscTag_pr;
			s_omni.prop4="minicart";
			s_omni.tl(this, 'o', 'RemoveFromMiniCart');
			s_omni.linkTrackVars=s_omni.temp_linkTrackVars;
			s_omni.linkTrackEvents=s_omni.temp_linkTrackEvents;
// re-enable add to cart button
			removeCartLoad();
			var params = [];
			params["storeId"] = serviceResponse.requestProperties["storeId"];
			params["catalogId"] = serviceResponse.requestProperties["catalogId"];
			params["langId"] = serviceResponse.requestProperties["langId"];
			params["orderId"]		= serviceResponse.requestProperties["orderId"];
			params["calculationUsageId"] = "-1";
			//params["doPrice"] = "Y";
			if((document.location.href.indexOf("DSIShoppingCartDisplay") > -1) && (serviceResponse.requestProperties.orderEmpty == '1')){
				//alert("document.location.href: " + document.location.href);
				document.location.href = "DSIOrderItemDisplay?storeId=" + serviceResponse.requestProperties["storeId"] + "&catalogId=" + serviceResponse.requestProperties["catalogId"] + "&langId=" + serviceResponse.requestProperties["langId"] + "&orderId=.";
			}
			else if(document.location.href.indexOf("DSIPrepareSavedCart") > -1){
				document.location.href = document.location.href;
			}
			else{
				wc.service.invoke("DSIAjaxOrderCalculate", params);
			}		
// remove please wait modal			
			pw_hidePanel();		
		}
     /**
     * display an error message
     * @param (object) serviceResponse The service response object, which is the
     * JSON object returned by the service invocation
     */
		,failureHandler: function(serviceResponse) {
// re-enable the add to cart buttons on single and grouped product page and quickview pane
			if( eval(document.getElementById("add2CartButton")) ){
				document.getElementById("add2CartButton").disabled = false;
			}
			if( eval(document.getElementById("add2CartButton1")) ){
				document.getElementById("add2CartButton1").disabled = false;
			}
			if( eval(document.getElementById("add2CartButton2")) ){
				document.getElementById("add2CartButton2").disabled = false;
			}						
// re-enable add to cart function			
			busy = false;
// re-enable add to cart button 			
			removeCartLoad();
// remove please wait modal			
			pw_hidePanel();			
		}

	}),

	/**
	 * This service applies the promotion code to the order(s).
	 */
	wc.service.declare({
		id: "DSIAjaxPromotionCodeManage",
		actionId: "DSIAjaxPromotionCodeManage",
		url: getAbsoluteURL() + "DSIAjaxPromotionCodeManage",
		formId: ""

		,successHandler: function(serviceResponse) {
			//alert(serviceResponse.requestProperties["orderId"]);
			var params = [];
			params["storeId"] = serviceResponse.requestProperties["storeId"];
			params["catalogId"] = serviceResponse.requestProperties["catalogId"];
			params["langId"] = serviceResponse.requestProperties["langId"];
			params["orderId"]		= serviceResponse.requestProperties["orderId"]
			params["calculationUsageId"] = "-1";
			wc.service.invoke("DSIAjaxOrderCalculate", params);
		}

		,failureHandler: function(serviceResponse) {
			showErrorMessage(serviceResponse.dsiErrorMessage, "alertBox");
		}

	}),
	
	/**
	 * This service removes the coupon code from the order(s).
	 */
	wc.service.declare({
		id: "DSIAjaxDeselectCoupon",
		actionId: "DSIAjaxDeselectCoupon",
		url: getAbsoluteURL() + "DSIAjaxDeselectCoupon",
		formId: ""

    /**
     * hides all the messages and the progress bar
     * @param (object) serviceResponse The service response object, which is the
     * JSON object returned by the service invocation
     */
		,successHandler: function(serviceResponse) {
			var params = [];
			params["storeId"] = serviceResponse.requestProperties["storeId"];
			params["catalogId"] = serviceResponse.requestProperties["catalogId"];
			params["langId"] = serviceResponse.requestProperties["langId"];
			params["orderId"]		= serviceResponse.requestProperties["orderId"]
			params["calculationUsageId"] = "-1";
			wc.service.invoke("DSIAjaxOrderCalculate", params);
		}

		,failureHandler: function(serviceResponse) {

		}

	}),
	
	/**
	 * This service applies the coupon code to the order(s).
	 */
	wc.service.declare({
		id: "DSIAjaxSelectCoupon",
		actionId: "DSIAjaxSelectCoupon",
		url: getAbsoluteURL() + "DSIAjaxSelectCoupon",
		formId: ""

		,successHandler: function(serviceResponse) {
			var params = [];
			params["storeId"] = serviceResponse.requestProperties["storeId"];
			params["catalogId"] = serviceResponse.requestProperties["catalogId"];
			params["langId"] = serviceResponse.requestProperties["langId"];
			params["orderId"]		= serviceResponse.requestProperties["orderId"]
			params["calculationUsageId"] = "-1";
			wc.service.invoke("DSIAjaxOrderCalculate", params);
		}

		,failureHandler: function(serviceResponse) {

		}

	}),
	
	/**
	  * This services accepts a semi-colon separated list of orderitems and deletes each one
	  */
	wc.service.declare({
		id: "DSIAjaxMultiOrderItemDelete",
		actionId: "DSIAjaxMultiOrderItemDelete",
		url: getAbsoluteURL() + "DSIAjaxMultiOrderItemDelete",
		formId: ""
	
		,successHandler: function(serviceResponse) {
			var params = [];
			params["storeId"] = serviceResponse.requestProperties["storeId"];
			params["catalogId"] = serviceResponse.requestProperties["catalogId"];
			params["langId"] = serviceResponse.requestProperties["langId"];
			params["orderId"]		= serviceResponse.requestProperties["orderId"];
			params["calculationUsageId"] = "-1";
			//params["doPrice"] = "Y";
			wc.service.invoke("DSIAjaxOrderCalculate", params);
			pw_hidePanel();
		}
	
		,failureHandler: function(serviceResponse) {
			pw_hidePanel();			
		}
	})
	/**
	 * This service applies the coupon code to the order(s).
	 */
	wc.service.declare({
		id: "DSIAjaxOrderCalculate",
		actionId: "DSIAjaxOrderCalculate",
		url: getAbsoluteURL() + "DSIOrderCalculate",
		formId: ""

		,successHandler: function(serviceResponse) {
			if(typeof(window['orderCalculateRunning']) != "undefined"){
				orderCalculateRunning = false;
			}
			cursor_clear();
		}

		,failureHandler: function(serviceResponse) {
			if(typeof(window['orderCalculateRunning']) != "undefined"){
				orderCalculateRunning = false;
			}
			cursor_clear();
		}

	})

/************************************************************************************
 * Service Event Mappings
 * @fileOverview This class contains key-value paired variables that are
 * mapped to their respective services. The variables are used to determine
 * which refresh areas to update. For example, the order_updated variable is
 * used update order related refresh areas.
 */

/**
 * map order_updated to all the services that result in changes to an order
 * @static
 */
var order_updated = {	'AjaxAddOrderItem':'AjaxAddOrderItem',
											'AjaxAddOrderItemWithShipingInfo':'AjaxAddOrderItemWithShipingInfo',
											'AjaxDeleteOrderItem':'AjaxDeleteOrderItem',
											'AjaxUpdateOrderItem':'AjaxUpdateOrderItem',
											'AjaxUpdateOrderShippingInfo':'AjaxUpdateOrderShippingInfo',
											'AjaxPrepareOrder':'AjaxPrepareOrder',
											'AjaxOrderCalculate':'AjaxOrderCalculate',
											'AjaxLogoff':'AjaxLogoff',
											'AjaxPrepareOrder2':'AjaxPrepareOrder2',
											'AjaxSubmitOrder':'AjaxSubmitOrder',
											'DSIAjaxOrderItemAdd':'DSIAjaxOrderItemAdd',
											'DSIAjaxOrderItemUpdate':'DSIAjaxOrderItemUpdate',
											'DSIAjaxOrderItemDelete':'DSIAjaxOrderItemDelete',
											'DSIAjaxOrderCalculate':'DSIAjaxOrderCalculate',
											'DSIAjaxMultiOrderItemDelete':'DSIAjaxMultiOrderItemDelete'
										};

/**
 *  map address_updated to all the services that result in changes to a shopper's
 *  address book
 *  @static
 */
var address_updated = {	'AjaxDeleteAddressForPerson':'AjaxDeleteAddressForPerson',
			'AjaxAddAddressForPerson':'AjaxAddAddressForPerson',
			'AjaxUpdateAddressForPerson':'AjaxUpdateAddressForPerson'
		};

/**
 *  map user_changed to all the services that result in the user in session
 *  change
 *  @static
 */
var user_changed = {	'AjaxLogonService':'AjaxLogonService',
											'AjaxLogoff':'AjaxLogoff'
										};

/**
 *  map wishlist_changed to all the services that result in the changes to a wish list
 *  @static
 */
var wishlist_changed = {	'AjaxInterestItemAdd':'AjaxInterestItemAdd',
												'AjaxInterestItemDelete':'AjaxInterestItemDelete',
												'AjaxLogonService':'AjaxLogonService',
												'AjaxLogoff':'AjaxLogoff'
											};

/************************************************************************************
 * Common Dojo Utilities
 */

//Import the required Dojo libraries
dojo.registerModulePath("wc", "../wc");
	
dojo.require("wc.service.common");

//Reloads widgets when parts of the page has been re-loaded from server
dojo.require("dojo.parser");
dojo.require("dijit.Dialog");

dojo.require("wc.widget.RefreshArea");
dojo.require("wc.render.RefreshController");
dojo.require("wc.render.Context");

/**
 * Parses a Dojo widget.
 * Pass in the id of a dojo widget or a HTML container element containing a dojo widget, such as a div,
 * and this method will parse that widget, or all the widgets within that HTML container element.
 * 
 * @param {string} id The id of a dojo widget or a HTML container of a dojo widget to be parsed.
 */
function parseWidget(id)
{
	var node;
	var widget = dijit.byId(id);
	
	if (widget == null || widget == undefined)
	{
		if (id == null || id == undefined)
		{	
			node = dojo.body();
		}
		else
		{
			node = dojo.byId(id);
		}
		
		if (node != null && node != undefined)
		{
			if (node.getAttribute("dojoType") != null && node.getAttribute("dojoType") != undefined)
			{
				dojo.parser.instantiate([node]);
			}
			else
			{
				dojo.parser.parse(node);
			}
		}
	}
}

/** 
 * This variable indicates whether a request has been submitted or not.
 * The value is initialized to true and resets to false on full page load.
 */
var requestSubmitted = true;

/** 
 * This variable stores the id of the element (ex: button/link) which the user clicked.
 * This id is set when the user clicks an element which triggers an Ajax request.
 */
var currentId = "";

/**
 * Displays the progress bar dialog to indicate a request is currently running.
 */
function cursor_wait(bShowProgressBar) {
	setTimeout("showProgressBar("+bShowProgressBar+")",500);
}

/**
 * Helper method for cursor_wait() to display the progress bar pop-up.
 * Displays progress bar, next to the element if the element id was specified in currentId,
 * or defaults to the center of the page if currentId is empty.
 * Progress bar will only be displayed if the submitted request has not been completed.
 * This method is only called implicitly by the cursor_wait() method, which is triggered before a request is submitted.
 */
function showProgressBar(bShowProgressBar){
	//After the delay, if the request is still not finished
	//Then continue and show the progress bar
	//Otherwise, do not execute the following code
	if(!requestSubmitted){
		return;
	}
	
	var dialog = dijit.byId('progress_bar_dialog');
	
	if (bShowProgressBar) {
		//Make sure the dialog is created
		if(dialog != null){
				
			//Hide the header for the close button
			dialog.closeButtonNode.style.display='none';		
			
			var progressBar = document.getElementById('progress_bar');
			progressBar.style.display = 'block';	
					
			//Check whether or not an element ID is provided
			//If yes, point the progress bar to this element
			//Otherwise, show the progress bar in a dialog
			if(this.currentId != ""){
				var element = document.getElementById(this.currentId);	
				var pos = dijit.placeOnScreenAroundElement(progressBar,element,{'TR':'TL'});	
			} else {
				dialog.containerNode.innerHTML == "";
				progressBar.style.left = '';
				progressBar.style.top = '';
				dialog.containerNode.appendChild(progressBar);
				dialog.show();		
			}
			
		}
	}

	//Make sure the progress bar dialog goes away after 40 seconds 
	//and does not hang if server calls does not return
	//Assuming the longest server calls return before 40 seconds (considering large search results etc)
	setTimeout("cursor_clear()",40000);

}

function setCurrentId(id) {
	if(!requestSubmitted && this.currentId == "") {
		this.currentId = id;
	}
}

/**
 * Hides the progress bar dialog when the submitted request has completed.
 * Set the visibility of the progress bar dialog to hide from the page.
 */
function cursor_clear() {
		//Reset the flag 
		requestSubmitted = false;
		enableComponentsPostSubmitRequest();

		//Hide the progress bar dialog
		var dialog = dijit.byId('progress_bar_dialog');
		var progressBar = document.getElementById('progress_bar');
		if(dialog != null){
			if(progressBar != null){
				progressBar.style.display = 'none';
			}
			dialog.hide();
		}

		this.currentId="";
}	

/**
 * Checks whether a request can be submitted or not.
 * A new request may only be submitted when no request is currently running.
 * If a request is already running, then the new request will be rejected.
 *
 * @return {boolean} Indicates whether the new request was submitted (true) or rejected (false).
 */
function submitRequest() {
	if(!requestSubmitted) {
		requestSubmitted  = true;
		disableComponentsPreSubmitRequest();
		return true;
	}
	return false;
}

/**
 * Disable components after requestSubmit is set to true;  Each page needs to redefine this accordingly
 */
function disableComponentsPreSubmitRequest() {
}

/**
 * Enable components after requestSubmit is set to true;  Each page needs to redefine this accordingly
 */
function enableComponentsPostSubmitRequest() {
}

/**
 * if the ShipOMeter is enabled, invoke the updateShipOMeter function with the current order total
 */
function callShipOMeter() {
	if (typeof(isShipOMeterActive) != "undefined" && isShipOMeterActive){
		if( eval(document.getElementById('orderTotal')) ){
			total = document.getElementById('orderTotal').innerHTML;
		}else{
			total = "0";
		}
		updateShipOMeter(total);
	}   
}