(function(app){
	if (app) {
		// add Product object to app namespace
		app.Product = function(response) {
			// product private data

			// product json data
			var model 			= response.data;

			// div cotainer id
			var myContainerId	= "";

			// boolean flag to track the variants data request, reset in loadVariants() when the variants data is loaded
			var isLoadingVar	= false;

			// helper function to load variants data from the server
			// once the data is retrieved, it fires VariationsLoaded event so that UI can be refreshed appropriately
			var loadVariants	= function(thisProduct) {
				isLoadingVar = true;
				// build the url and load variants data
				var url = app.util.appendParamToURL(app.util.appendParamToURL(app.URLs.getVariants, "pid", thisProduct.pid), "format", "json")
				var result = app.ajax.getJson({
					url: url,
					data: {},
					callback: function(data){

						if (!data || !data.variations || !data.variations.variants) {
							return;
						}
						model.variations.variants = data.variations.variants;
						isLoadingVar = false; // we have loaded the variants
						jQuery(thisProduct).trigger("VariationsLoaded", ["loadVariants"]);
					}
				});
			}

			// creates product recommendation carousel using jQuery jcarousel plugin
			// uses app.tooltip to create tooltips for each product in the carousel
			var loadRecommendations = function(containerId) {
				if (jQuery(containerId+" .maywerecommend ul li").length > 0) {
					jQuery(containerId+" .maywerecommend ul").jcarousel({
						scroll: 1,
						itemVisibleInCallback: app.captureCarouselRecommendations
					});
					// create tooltips event handler
					app.tooltip({id: containerId+" .maywerecommend ul li", options: {
							bodyHandler: function() {
								return jQuery(this).children(".pdpTooltip").html();
							}
					}});
				}				
			}

			// helper function to bind product options drop downs event handlers
			// Intializes the product.selectedOptions object with the currently selected options
			// it also shows the computed/updated price
			var getOptionsDiv	= function(thisProduct) {
				if (model.isOption && !model.master) {

					var pdpOpt = jQuery(thisProduct.containerId+" .product_options:last select");

					pdpOpt.change(function(e){
						var vals = this.options[this.selectedIndex].value.split("%?%"); // 0 = value, 1 = price
						thisProduct.selectedOptions[this.id] = vals[0];
						thisProduct.selectedPrice[this.id] = vals[1];
						thisProduct.showUpdatedPrice(computePrice(thisProduct), model.pricing.standard);						
					});
					
					// let us get the currently selected value and intilize the ui
					pdpOpt.each(function(i) {
						var vals = this.options[this.selectedIndex].value.split("%?%"); // 0 = value, 1 = price					
						
						thisProduct.selectedOptions[this.id] = vals[0];
						thisProduct.selectedPrice[this.id] = vals[1];
						thisProduct.showUpdatedPrice(computePrice(thisProduct), model.pricing.standard);
					});
				}
			}

			// binds A2C button click handler
			var getAddToCartBtn = function(thisProduct) {
				var addToCartBtn = jQuery(thisProduct.containerId+" .addtocartbutton:last").click(function(e) {
					if (model.master || model.variant) {
						if (thisProduct.selectedVar == null) {
							return false;
						}
						thisProduct.selectedOptions.pid = thisProduct.selectedVar.id;
						thisProduct.selectedOptions.masterPid = thisProduct.pid;
					}
					else {
						// check if we are adding a bundle/productset to the cart
						if (model.bundle || model.productSet) {							
							var subProducts = thisProduct.subProducts;
							var comma 		= ",";
							var tempQty 	= "";
							var subproduct 	= null;
							
							thisProduct.selectedOptions.childPids = "";
														
							if (model.productSet) {
								thisProduct.selectedOptions.Quantity = "";
							}
							
							// process each individual products in the set/bundle
							// and prepare product.selectedOptions for final submission
							for (var i = 0; i < subProducts.length; i++) {
								subproduct = subProducts[i];
								
								// Only add products that are in stock or have qty > 0
								var avStatus = subproduct.getAvStatus(); // availability status
								if (avStatus != app.constants.AVAIL_STATUS_NOT_AVAILABLE && subproduct.selectedOptions.Quantity > 0)
								{
									if (i == subProducts.length - 1) {
										comma = ""; // at the end of the list
									}
									
									// see if any of the sub products are variations, if so then get the selected variation id
									// from selectedVar property and make it a comma separated list
									if (subproduct.variant || subproduct.master) {									
										if (subproduct.selectedVar == null) {
											return false;
										}
										thisProduct.selectedOptions.childPids += subproduct.selectedVar.id+comma;
									}
									else {
										thisProduct.selectedOptions.childPids += subproduct.selectedOptions.pid+comma;
									}
									
									var tempPid = subproduct.selectedOptions.pid;
									subproduct.selectedOptions.pid = null;
									// merge selected options of sub product with the main product
									thisProduct.selectedOptions = jQuery.extend({}, thisProduct.selectedOptions, subproduct.selectedOptions);
									subproduct.selectedOptions.pid = tempPid;
									
									// if it is a product set then sub products can have their separate qty
									if (model.productSet) {
										tempQty += subproduct.selectedOptions.Quantity+comma;
									}
								}
							}
						}
						
						// if it is a product set then sub products can have their separate qty
						// tempQty is a comma separated list of qty for each product in the set
						if (model.productSet) {
							thisProduct.selectedOptions.Quantity = tempQty;
						}
						
						// make sure the pid which gets submitted is for the main product
						thisProduct.selectedOptions.pid = thisProduct.pid;
					}
                    
					// Bundles can have a qty > 1 so removed this condition. DE. 
					//if (model.bundle) {
					//	thisProduct.selectedOptions.Quantity = 1; // hard coded qty=1 when we the product is a bundle
					//}
					//else 
					if (!model.productSet) {
						// grab the user entered qty
						thisProduct.selectedOptions.Quantity = jQuery(thisProduct.containerId+" .quantityinput:last").val();
					}
					
					// if it is not a productset then make sure qty is specified greater than 0
					if (model.productSet || thisProduct.selectedOptions.Quantity > 0) {
						// disable a2c button
						addToCartBtn.attr("disabled", "true");
						
						// close the quick view when user clicks A2C.
						app.quickView.close();
						
						// find if there is a handler bound to AddToCart event e.g. cart -> edit details or wishlist -> edit details etc.
						// then fire it otherewise call app.minicart.add to add the selected product to the cart and show minicart
						var event = jQuery.Event("AddToCart");
						event.selectedOptions = thisProduct.selectedOptions;
												
						(jQuery.event.global["AddToCart"] == undefined || jQuery.event.global["AddToCart"] == null) ? app.minicart.add( "", thisProduct.selectedOptions, function(){addToCartBtn.removeAttr("disabled")} ) : jQuery(document).trigger(event);
					}
					return false;
				} );

				return addToCartBtn;
			}

			// bind qty box keyup handler
			// the handler grabs the value and updates 
			// product.selectedOption.Quantity
			// show the updated availabilty message in case the available qty is different than available etc.
			// trigger AddtoCartEnabled event
			var getQtyBox 		= function(thisProduct) {				
				jQuery(thisProduct.containerId+" .quantityinput:last").keyup(function(e){
					var val = null;
					try {
						val = parseInt(jQuery(thisProduct.containerId+" .quantityinput:last").val());
					} catch(e){val = null};

					if (val != null) {
						thisProduct.selectedOptions.Quantity = val;
						
						if (thisProduct.subproduct && val <= 0)
						{
							thisProduct.disableA2CButton();
						}
						else if (thisProduct.subproduct)
						{
							thisProduct.enableA2CButton();
						}
					
						// Trying to prevent the availability flicker. Also dont want to update availability based on qty. DE.
						// setAvailabilityMsg(createAvMessage(thisProduct, val));
						
						jQuery(thisProduct).trigger("AddtoCartEnabled");
					}
				});

				// grab the currenlty displayed value basically the intial displayed value
				thisProduct.selectedOptions.Quantity = jQuery(thisProduct.containerId+" .quantityinput:last").val();
				
				// show proper availability message
				// Trying to prevent the availability flicker. Also dont want to update availability based on qty. DE.
				// setAvailabilityMsg(createAvMessage(thisProduct, thisProduct.selectedOptions.Quantity));
			}

			// create product tabs i.e. description, Attributes, Reviews etc.
			// it depends on jQuery to create tab display.
			var getTabs 		= function(containerId) {
				var tabsDiv = jQuery(containerId+" #pdpTabsDiv");
				tabsDiv.tabs();
			}
			
			// bind onclicks to desc links
			jQuery("a#infoLink").click(function() {
				jQuery('#pdpTabsDiv').tabs('select', 'pdpTab1');
				jQuery('html, body').animate({scrollTop: jQuery("div #pdpTab1").offset().top}, 500);
				return false;
			});
			jQuery("a.reviewLink").click(function() {
				jQuery('#pdpTabsDiv').tabs('select', 'pdpReviewsTab');
			});
			jQuery("a#delLink").click(function() {
				jQuery('#pdpTabsDiv').tabs('select', 'pdpTab3');
				jQuery('html, body').animate({scrollTop: jQuery("div #pdpTab3").offset().top}, 500); 
				return false;
			});
			jQuery("a.morerelateditems").click(function() {
				jQuery('#pdpTabsDiv').tabs('select', 'pdpCrossSellTab');
			});
			
			jQuery("a#backtotoplink").click(function() {
				jQuery('html, body').animate({scrollTop: jQuery("div #container").offset().top}, 500); 
				return false;
			});
			
			var getArpTabs = function(containerId){
				var tabsDiv = jQuery(containerId+" #arpTabsDiv");
				tabsDiv.tabs();
			}
			
			// bind addtowishlist, giftregistry, send to friend click handlers
			// bind handlers to AddtoCartDisabled, AddtoCartEnabled events for disabling/enabling wishlist/gift registry links
			var getMiscLinks 	= function(thisProduct) {
			
				var disablelinks = function() {
					if ((model.master || model.variant) && thisProduct.selectedVar == null) {
						// disable wishlist/gift registry links for master products
						jQuery(thisProduct.containerId+" .addtowishlist, "+thisProduct.containerId+" .addtoregistry").addClass("unselectable");
					}
				}
				
				disablelinks(); // call it for initial display and then register it with AddtoCartDisabled event
				
				jQuery(thisProduct).bind("AddtoCartDisabled", {}, disablelinks);
				
				jQuery(thisProduct).bind("AddtoCartEnabled", {}, function(e, source){
					// enable wishlist/gift registry links for variant products
					jQuery(thisProduct.containerId+" .addtowishlist, "+thisProduct.containerId+" .addtoregistry").removeClass("unselectable");
				});
				
				// Add to wishlist, Add to gift registry click handler
				jQuery(thisProduct.containerId+" .addtowishlist a, "+thisProduct.containerId+" .addtoregistry a").click(function(e) {
					// append the currently selectied options to the url
					
					// create a local copy of the selected options
					var selectedOptions = jQuery.extend({}, {}, thisProduct.selectedOptions);
					
					if (model.master || model.variant) {
						if (thisProduct.selectedVar != null) {
							selectedOptions.pid = thisProduct.selectedVar.id;
						}
						else {
							return false; // do not allow master product to be added to gift registry/wishlist
						}
					}
					else {
						selectedOptions.pid = thisProduct.pid;
					}
					
					var tempUrl = this.href;
					
					if (!(tempUrl.indexOf("?") > 0)) {
						tempUrl = tempUrl + "?";
					}
					else
					{
						tempUrl = tempUrl + "&";
					}
					// serialize the name/value into url query string and append it to the url, make request
					window.location = tempUrl + jQuery.param(selectedOptions);
					return false;
				} );			
				
				jQuery(thisProduct.containerId+" .sendtofriend").click(function(e) {
					handlerFunction = typeof dialogSendToFriendOpenHandler == 'function' ? dialogSendToFriendOpenHandler : null; 
					var sendToFriendUrl = app.URLs.sendToFriend;

					// Check if we are dealing with variant product and set its name if we are
					var thisProduct = app.ProductCache;
					if (app.URLs.sendToFriendRoot != null && thisProduct.variant &&  thisProduct.selectedVar != null) {
						sendToFriendUrl = app.util.appendParamToURL(app.URLs.sendToFriendRoot,'productName', thisProduct.selectedVar.displayName);
					}
					
					app.dialog.open(sendToFriendUrl, app.resources.SEND_TO_FRIEND, handlerFunction);
					return false;
				} );
				
				jQuery(thisProduct.containerId+" .sendtofriendqv").click(function(e) {
					sendToFriendUrl = app.URLs.sendToFriendQuickview;
					handlerFunction = typeof dialogSendToFriendOpenHandlerQuickview == 'function' ? dialogSendToFriendOpenHandlerQuickview : null;
					
					// Check if we are dealing with variant product and set its name if we are
					var thisProduct = app.ProductCacheQV;
					if (app.URLs.sendToFriendRoot != null && thisProduct.variant &&  thisProduct.selectedVar != null) {
						sendToFriendUrl = app.util.appendParamToURL(app.URLs.sendToFriendRoot,'productName', thisProduct.selectedVar.displayName);
					}
					app.dialog.open(sendToFriendUrl, app.resources.SEND_TO_FRIEND, handlerFunction);
					// Hide QuickView dialog when showing EmailToFriend to get around the problem with disabled QV input fields
					app.quickView.close();
					return false;
				} );
				
				// Print page event handler
				// Unbind all previous click events. Prevents print page appearing multiple times on product set / bundle pages.
				jQuery("a.printpage").unbind('click'); 
				jQuery("a.printpage").click(function() {
					window.print();
					return false;
				});
			}
			
			// binds product reviews click handlers
			// read review link opens reviews tab
			var getRatingSection = function(containerId) {

				jQuery(containerId+" #pdpReadReview").click(function(e) {
					jQuery(containerId+" #pdpTabsDiv").tabs("select", "pdpReviewsTab");
				} );

				jQuery(containerId+" #pdpWriteReview").click(function(e) {
				} );
			}

			// based on availability status, creates a message
			// param val - the stock value to compare i.e. qty entered by user
			var createAvMessage = function(thisProduct, val) {
				
				var avStatus 		= thisProduct.getAvStatus(); // availability status
				var avMessage 		= app.resources[avStatus];
				var ats 			= thisProduct.getATS(); // get available to sell qty
				var avInfoMessage 	= null;
				var atsMessage = thisProduct.getATSMessage();
			
				if (avStatus === app.constants.AVAIL_STATUS_NOT_AVAILABLE) 
				{
					avMessage = "<span class=\"outStock\">" + avMessage + "</span> ";
				}
				/*
				else if (val > ats) {
					// display quantity in stock message
					avMessage = jQuery.format(app.resources["QTY_"+avStatus], ats);
				}*/
				else if (avStatus === app.constants.AVAIL_STATUS_IN_STOCK) 
				{
					if (atsMessage != null && atsMessage != "")
					{
						avMessage = "<span class=\"inStock\">" + jQuery.format(app.resources["QTY_"+avStatus], atsMessage) + "</span> ";
					}
					else
					{
						avMessage = "<span class=\"inStock\">" + avMessage + "</span> ";
					}

				}
				else if (avStatus === app.constants.AVAIL_STATUS_BACKORDER)
				{
					if (atsMessage != null && atsMessage != "")
					{
						avMessage = "<span class=\"inStock\">" + jQuery.format(app.resources["QTY_"+avStatus], atsMessage) + "</span> ";
					}
					else
					{
						avMessage = "<span class=\"inStock\">" + avMessage + "</span> " ;
					}

					var stockDate = thisProduct.getInStockDate();
					
					if (stockDate == "null" || stockDate == "" )
					{
	                    avInfoMessage = app.resources["NO_IN_STOCK_DATE"];
					}
                    else
                    {
					    avInfoMessage = jQuery.format(app.resources["IN_STOCK_DATE"], stockDate );
                    }
				}
                else if (avStatus === app.constants.AVAIL_STATUS_PREORDER)
                {
					if (atsMessage != null && atsMessage != "")
					{
						avMessage = "<span class=\"inStock\">" + jQuery.format(app.resources["QTY_"+avStatus], atsMessage) + "</span> ";
					}
					else
					{
						avMessage = "<span class=\"inStock\">" + avMessage + "</span> " ;
					}                	

					var stockDate = thisProduct.getInStockDate();

					if (stockDate == "null" || stockDate == "" )
					{
	                    avInfoMessage = app.resources["NO_PRE_ORDER_DATE"];
					}
                    else
                    {
					    avInfoMessage = jQuery.format(app.resources["PRE_ORDER_DATE"], stockDate );
                    }
                }
				return {status:avMessage, msg:avInfoMessage}
			}

			// helper function to set availability message
			// Split status and message into two due to layout requirements
			var setAvailabilityMsg = function(av) {
				jQuery(myContainerId+" .availability:last .value").html(av.status);
				if(av.msg != null) {
					// Check if the container already exists, otherwise we'll get multiple messages
					if(jQuery(myContainerId).find(".availabilitymsg").size() > 0) {
						// Overwrite
						jQuery(myContainerId + " .availabilitymsg").html(av.msg);
					} else {
						// Append
						jQuery(myContainerId + " .availability").after("<p class=\"availabilitymsg\">" + av.msg + "</p>");
					}					
				} else {
					if(jQuery(myContainerId).find(".availabilitymsg").size() > 0) {
						// Overwrite
						jQuery(myContainerId + " .availabilitymsg").html('');
					}					
				};
			};

			// helper function to display/hide various elements based on the variant availability
			var switchOnVariantAvailability = function(avaialable, containerId) {
				if (avaialable)
				{
				    jQuery(containerId + " .quantitybox").css({"display": "block"});
				    jQuery(containerId + " #emailWhenAvailable").css({"display": "none"});
				    //jQuery(containerId + " .productactions .primarybuttonlarge").css({"display": "block"});
				    jQuery(containerId + " #primaryaddtocartbutton").css({"display": "block"});
				}
				else
				{
					jQuery(containerId + " .quantitybox").css({"display": "none"});
					jQuery(containerId + " #emailWhenAvailable").css({"display": "block"});
					//jQuery(containerId + " .productactions .primarybuttonlarge").css({"display": "none"});
					jQuery(containerId + " #primaryaddtocartbutton").css({"display": "none"});
				}
			}
			
			function updateProductBreadcrumb(thisProduct){
				
				if (thisProduct.subproduct != true)
				{
					jQuery("#breadcrumb .productname").html(thisProduct.selectedVar.displayName);
				}
			}

			/**
			 * Private. Computes price of a given product instance based on the selected options.
			 * 
			 * @param thisProduct - the product instance 
			 * @return price of the product to 2 decimal points.
			 */
			var computePrice = function(thisProduct) {

				var price = thisProduct.selectedVar != null ? thisProduct.selectedVar.pricing.sale : model.pricing.sale;
				// calculate price based on the selected options prices
				jQuery.each(thisProduct.selectedPrice, function(){
					price = (new Number(price) + new Number(this)).toFixed(2);
				});

				return price;
			}

			// bind click handlers for prev/next buttons on pdp from search
			var getNavLinks = function() {
				// bind events
				jQuery(".productnavigation a").click(function(e) {
					app.getProduct({url: this.href, source: "search"});
					return false;
				});
			}
			
			// Bind video and 360 links
			var getMediaLinks = function() {
				
				// Bind the video link
				jQuery("a.video, a.d3view").click(function(){
					
					// Create the element
					jQuery("<div id=\"isiteTVDialog\"/>").appendTo("body");
					
					// Create and append the iframe and update the src
					jQuery("<iframe src=\"\" id=\"isiteTV\" frameborder=\"0\" scrolling=\"no\" height=\"400\" width=\"500\"/>").attr("src", jQuery(this).attr("href")).appendTo("#isiteTVDialog");
					
					app.createDialog({id:'isiteTVDialog', options: {
				    	height: 450, //430
				    	width: 500,//480
				    	dialogClass: 'video',
				    	title: 'View product video',
				    	resizable: false,
				    	close: function(){
							// Remove the element when closed
							jQuery(this).remove();
						}
					}});
					
					// Open the dialog
					jQuery("#isiteTVDialog").dialog("open");
					return false;
				});
			};
			
			// size chart link click binding
			var getSizeChart = function() {
				jQuery(".attributecontentlink").click(function(e){
					// add size chart dialog container div if its not added yet
					// only added once
					if (jQuery("#sizeChartDialog").length == 0) {
						jQuery("<div/>").attr("id", "sizeChartDialog").css("overflow", "auto").appendTo(document.body);
					}
					
					app.createDialog({id: 'sizeChartDialog', options: {
				    	height: 600,
				    	width: 470,
				    	title: app.resources["SIZECHART_TITLE"]
					}});
					
					jQuery('#sizeChartDialog').dialog('open');
					
					// make the server call to load the size chart html
					jQuery("#sizeChartDialog").load(this.href);
					
					return false;
				});
			}
			
			// bind secondary product image switcher
			jQuery("a.secondaryProdImg").click(function() {
				document.getElementById("primaryProdImg").firstChild.src = this.href;
				return false;
			});
			
			// Product instance
			return {
				pid					: model.ID,
				variant				: model.variant,
				master				: model.master,
				bundled				: model.bundled,
				subproduct			: model.subproduct,
				productSet          : model.productSet,
				selectedVarAttribs	: {}, // object containing variation attributes values as name value e.g. {color: "blue", size: "3", width: ""}				
				selectedVar			: null, // currently selected variant
				selectedOptions		: {}, // holds currently selected options object {optionName, selected val}
				selectedPrice		: {}, // holds prices for selected options as {warranty: ""}
				containerId			: null, // holds the html container id of this product
				subProducts			: [], // array to keep sub products instances 
				
				/**
				 * Enable Add to Cart Button.
				 * Note - maybe should change the CSS class as well to show a different button?  DE
				 */
				enableA2CButton: function() {
					jQuery(this.containerId+" .addtocartbutton:last").removeAttr("disabled");
					jQuery(this.containerId+" .primarybutton:last").css({"display": "block"});
				},
				
				/**
				 * Enable Master Add to Cart Button.
				 * Note - maybe should change the CSS class as well to show a different button?  DE
				 */
				enableMasterA2CButton: function() {
					jQuery(this.containerId+" .primarybuttonlarge:last .addtocartbutton:last").removeAttr("disabled");
					jQuery(this.containerId+" .primarybuttonlarge:last").css({"display": "block"});
				},				
				
				/**
				 * Disable Add to Cart Button.
				 * Note - maybe should change the CSS class as well to show a different button?  DE
				 */
				disableA2CButton: function() {
					jQuery(this.containerId+" .addtocartbutton:last").attr("disabled", "true");
					jQuery(this.containerId+" .primarybutton:last").css({"display": "none"});
				},

				/**
				 * Disable Master Add to Cart Button.
				 * Note - maybe should change the CSS class as well to show a different button?  DE
				 */
				disableMasterA2CButton: function() {
					jQuery(this.containerId+" .primarybuttonlarge:last .addtocartbutton:last").attr("disabled", "true");
					jQuery(this.containerId+" .primarybuttonlarge:last").css({"display": "none"});
				},				
				
				// determine if this product is part of a bundle/product set VIEW
				isSubProduct		: function() {
					
					var productCache = app.ProductCache; 
					if (model.source == 'quickview')
					{
						productCache = app.ProductCacheQV;
					}
					return (model.bundled || model.productSetProduct) && productCache.subProducts.length > 0;
				},

				// show the selected variation attribute value next to the attribute label e.g. Color: Beige
				showSelectedVarAttrVal: function(varId, val) {
					jQuery(this.containerId+" .variationattributes p:not(.clear)").each(function(){
						var id = jQuery(this).data("data");
						
						if (varId === id) {
							jQuery(this).find('span.selectedvarval').html(val);
						}
					});
				},
				
				// selects review tab
				readReviews: function() {
					jQuery(this.containerId+" #pdpTabsDiv").tabs("select", "pdpReviewsTab");
				},
				
				// shows product images and thumbnails
				// @param selectedVal - currently selected variation attr val
				// @param vals - total available variation attr values
				showImages: function(selectedVal, vals)  {
					var that = this;
					vals = vals || {};

					// show swatch related images for the current variation value					
					jQuery.each(vals, function(){
						var imgCounter = -1;
						var thisVal = this;
						// Selected variant
						if (this.val === selectedVal && this.images) {
							// We have thumbnails and we're not a subproduct
							if (this.images.thumbnail.length > 0 && !(model.subproduct))
							{
							    jQuery(that.containerId+" .productthumbnails:first").html("");

								// Don't replace main images on page load as S7 won't have replaced div with flash yet.
							   	if (model.scene7enabled)
								{
									sjFlyout(model.scene7FlyoutId, thisVal.images.large[0], thisVal.images.largealt[0]);
								}
								else
								{
									jQuery(that.containerId+" .productimage").html("").append(jQuery("<img/>").attr("src",thisVal.images.large[0]).addClass('largeimage'));
								}
							}
							
							// Handle subproduct small images
							if (this.images.small.length > 0 && model.subproduct)
							{
								jQuery(that.containerId+" .productthumbnails:last").html("");

								// Don't replace main images on page load as S7 won't have replaced div with flash yet.
							   if (model.scene7enabled)
							   {
								   sjFlyout(model.scene7FlyoutId, thisVal.images.large[0], thisVal.images.largealt[0]);
							   }
							   else
							   {
								   jQuery(that.containerId+" .productimage").html("").append(jQuery("<img/>").attr("src",thisVal.images.large[0]));
							   }
							}
							
							// make sure to show number of images based on the smallest of large or small as these have to have 1-1 correspondence.
							var noOfImages = this.images.large.length >= this.images.thumbnail.length ? this.images.thumbnail.length : this.images.large.length;

							// show thumbnails only if more than 1 )
							if (this.images.thumbnail.length > 0 && (!that.isSubProduct()))
							{
								jQuery.each(this.images.thumbnail, function(){
									imgCounter++;
									var imageInd = imgCounter;
									if (imgCounter > noOfImages -1) {
										return;
									}								
								    if (!model.subproduct)
								    {

								    	jQuery(that.containerId+" .productthumbnails:first").append(jQuery("<img/>").attr('src',this).addClass('thumbimage').click(function(e){
								    		if (model.scene7enabled)
								    		{
												sjFlyout(model.scene7FlyoutId, thisVal.images.large[imageInd], thisVal.images.largealt[imageInd]);
								    		}
								    		else
								    		{
								    			jQuery(that.containerId+" .productimage").html("").append(jQuery("<img/>").attr("src", thisVal.images.large[imageInd]));
								    		}
									    }));								    	
								    }
								});
							}
							
							if (that.isSubProduct())
							{
								jQuery.each(this.images.small, function(){
									imgCounter++;
									var imageInd = imgCounter;
									if (model.subproduct && imgCounter > 0) {
										return;
									}
								    if (model.subproduct)
								    {								    	  
								    	jQuery(that.containerId+" .productthumbnails:last").append(jQuery("<img/>").attr('src',this).addClass('smallimage').click(function(e){
								    		if (model.scene7enabled)
								    		{
												sjFlyout(model.scene7FlyoutId, thisVal.images.large[imageInd], thisVal.images.largealt[imageInd]);
								    		}
								    		else
								    		{
								    			jQuery(that.containerId+" .productimage").html("").append(jQuery("<img/>").attr("src", thisVal.images.large[imageInd]));
								    		}
									    }));
								    }
								});
							}
						}
					});
				},

				/**
				* Event handler when a variation attribute is selected/deselected.
				*/
				varAttrSelected: function(e) {
					// update the selected value node
					this.showSelectedVarAttrVal(e.data.id, e.data.val || "");

					this.selectedVarAttribs[e.data.id] = e.data.val;
					
					// if this is a deselection and user landed on a variant page then reset its variant flag 
					// as now user has deselected an attribute thus making it essentially a master product view
					if (e.data.val == null) { 
						this.variant = false;
					}
					
					// store this ref
					var that = this;

					// trigger update event which will update every other variation attribute i.e. enable/disable etc.

					// first reset the contents of each attribute display
					// when we have got the varriations data
					if (!isLoadingVar) {
						// find variants which match the current selection
						var selectedVarAttrVariants = e.data.val != null ? this.findVariations({id: e.data.id, val: e.data.val}): null;
						var selectedVarAttrs = jQuery.extend({}, {}, this.selectedVarAttribs);
						var validVariants = null;
						var unselectedVarAttrs = new Array();
						
						// for each selected variation attribute find valid variants
						for (var selectedVar in selectedVarAttrs) {
							if (selectedVarAttrs[selectedVar]) {
								validVariants = this.findVariations({id: selectedVar, val: selectedVarAttrs[selectedVar]}, validVariants);
							}
							else {
								unselectedVarAttrs.push(selectedVar);
							}
						}
						// update each variation attribute display
						jQuery.each(model.variations.attributes, function () {
							if ((this.id != e.data.id || e.data.val == null) && selectedVarAttrs[this.id] == null) {
								that.varAttrDisplayHandler(this.id, validVariants);								
							}
							else if (this.id != e.data.id && selectedVarAttrs[this.id] != null) {
								that.varAttrDisplayHandler(this.id, selectedVarAttrVariants);
							}
							else {
								// show swatch related images for the current value								
								that.showImages(e.data.val, this.vals);
							}
						});

						// based on the currently selected variation attribute values, try to find a matching variant
						this.selectedVar = this.findVariation(this.selectedVarAttribs);

						// If we have a analytics tracking function defined - call it
						if ( this.selectedVar != null && typeof app.trackProductVariantSelection == 'function')
						{
							app.trackProductVariantSelection(this.selectedVar.id, this.selectedVar.displayName);						
						}						
						
					}

					// lets fire refresh view event to enable/disable variations attrs
					jQuery(this).trigger("VariationsLoaded");
				},

				/**
				* go thru all variations attr and disable which are not available
				*/
				resetVariations: function() {
					if (isLoadingVar) {
						return ; // we don't have the complete data yet
					}
					var that = this;

					jQuery(this.containerId + " .variationattributes .swatches").each(function(){
						var dataa = jQuery(this).data("data"); // data is id set via app.hiddenData api
						jQuery(this).find("a.swatchanchor").each(function(){
							// find A variation with this val
							if (that.isVariation({id:dataa, val:this.innerHTML})) {
								// found at least 1 so keep it enabled
								jQuery(this).parent().removeClass("unselectable");
							}
							else {
								jQuery(this).parent().addClass("unselectable");
								jQuery(this).parent().removeClass("selected");
							}
						});
					});
				},
				
				/**
				* given a variation attribute id and valid variants, it would adjust the ui i.e. enable/disable 
				* appropriate attribute values.
				* 
				* @param attrId - String, id of the variation attribute
				* @param validVariants - Array of json objects of valid variants for the given attribute id
				* */
				varAttrDisplayHandler: function (attrId, validVariants) {
					var that = this; // preserve this instance
					// loop thru all non-dropdown ui elements i.e. swatches e.g. color, width, length etc.
					jQuery(this.containerId + " .variationattributes .swatches").each(function(){
						var swatchId = jQuery(this).data("data");  // data is id set via app.hiddenData api
						if (swatchId === attrId) {
							
							jQuery(this).find("a.swatchanchor").each(function(){
							
								var parentLi= jQuery(this).parent();
								
								// find A variation with this val
								var filteredVariants = that.findVariations({id:attrId, val:this.innerHTML}, validVariants);
								if (filteredVariants.length > 0) {
									// found at least 1 so keep it enabled
									parentLi.removeClass("unselectable");
								}
								else {
									// no variant found with this value combination so disable it
									parentLi.addClass("unselectable");
									
									if (parentLi.hasClass("selected")) {
										// remove the currently selected value if the value is not selectable
										that.showSelectedVarAttrVal(attrId, "");
										that.selectedVarAttribs[attrId] = null;
									}
									// remove current selection
									parentLi.removeClass("selected");
								}
							});
						}
					});
					
					// loop thru all the non-swatches(drop down) attributes
					jQuery(this.containerId + " .variationattributes .variantdropdown select").each(function(){
						var vaId = jQuery(this).data("data").id;  // data is id set via app.hiddenData api
						if (vaId === attrId) {
							var len = this.options.length;
							
							jQuery.each(this.options, function(){
								
								if (len > 1 && this.index == 0) {
									//return; // very first option when the length is greater than 1 is 'Select ...' message so skip it
									// Not any more
								}
								
								// find A variation with this val
								var filteredVariants = that.findVariations({id:attrId, val:this.value}, validVariants);
								
								if (filteredVariants.length > 0) {
									// found at least 1 so keep it enabled
									this.disabled = false;
								}
								else {
									// no variant found with this value combination so disable it
									this.disabled = true;
									
									if (this.selected) {
										// remove the currently selected value if the value is not selectable
										that.showSelectedVarAttrVal(attrId, "");
										that.selectedVarAttribs[attrId] = null;
									}
									// remove current selection
									this.selected = false;
								}
							});
						}
					});
					
				},

				// refresh the UI i.e. availability, price, A2C button and variation attributes display
				refreshView: function() {
					var thisProduct = this;

					if (!isLoadingVar && this.selectedVar == null) {
						// if we have loaded the variations data then lets if the user has already selected some values
						// find a matching variation
						this.selectedVar = this.findVariation(this.selectedVarAttribs);
					}

					if (!isLoadingVar && this.selectedVar != null) {
						// update availability
						setAvailabilityMsg(createAvMessage(thisProduct, 1));
						// update price
						this.showUpdatedPrice(this.selectedVar.pricing.sale, this.selectedVar.pricing.standard);
			
			
						updateProductBreadcrumb(this);
						

						if (!(!this.selectedVar.inStock && this.selectedVar.avStatus === app.constants.AVAIL_STATUS_NOT_AVAILABLE) && this.getPrice() > 0) {
							// enable add to cart button
							//jQuery(this.containerId+" .addtocartbutton:last").removeAttr("disabled");
							
							thisProduct.enableA2CButton();
							jQuery(this).trigger("AddtoCartEnabled");
							switchOnVariantAvailability(true, this.containerId);
						}
						else {
							//jQuery(this.containerId+" .addtocartbutton:last").attr("disabled", "true");
							
							thisProduct.disableA2CButton();
							
							// Trigger this event for the given subproduct so that we recalculate the total
							// price in case of product set
							jQuery(this).trigger("AddtoCartEnabled");
							
							jQuery(this).trigger("AddtoCartDisabled");
							
							switchOnVariantAvailability(false, this.containerId);
						}
					}
					else {
						if (isLoadingVar) {
						// update availability
							setAvailabilityMsg(app.showProgress("productloader"));
						}
						else {
							setAvailabilityMsg(app.resources["NON_SELECTED"]);
						}
						// disable add to cart button
						//jQuery(this.containerId+" .addtocartbutton:last").attr("disabled", "true");
						thisProduct.disableA2CButton();
						jQuery(this).trigger("AddtoCartDisabled");
					}
					
					var nonSelectedVars = [];
					
					var validVariants = null;
					
					for (var selectedVar in this.selectedVarAttribs) {
						if (this.selectedVarAttribs[selectedVar]) {
							validVariants = this.findVariations({id: selectedVar, val: this.selectedVarAttribs[selectedVar]}, validVariants);
						}						
					}
						
					// update selected var attr vals and refresh their display
					jQuery.each(model.variations.attributes, function(){
						thisProduct.showSelectedVarAttrVal(this.id, thisProduct.selectedVarAttribs[this.id]);
						
						if (!thisProduct.selectedVarAttribs[this.id] || thisProduct.selectedVarAttribs[this.id] == "" ) {
							nonSelectedVars.push(this.name);
							
							thisProduct.varAttrDisplayHandler(this.id, validVariants);
						}
					});
					
					// process non-selected vals and show updated tooltip for A2C button as a reminder
					// and show it along availability 
					var tooltipStr = '';
					var nsLen = nonSelectedVars.length;
					if (nsLen == 1 || nsLen == 2) {					
						tooltipStr = nonSelectedVars.join(" & ");
					}
					else {
						for (var i=0; i < nsLen; i++) {
							if (i == nsLen - 2) {
								tooltipStr += nonSelectedVars[i] + " & " + nonSelectedVars[i+1];
								break;
							}
							else {
								tooltipStr += nonSelectedVars[i] + ", ";
							} 
						}
					}					
					
					if (nonSelectedVars.length > 0) {
						var availMsg = jQuery.format(app.resources["MISSING_VAL"], tooltipStr);
						setAvailabilityMsg(availMsg);
						jQuery(thisProduct.containerId+" .addtocartbutton:last").attr("title", availMsg);
					}					
				},

				// renders pricing div given a sale price and optional standard price
				showUpdatedPrice: function(sale, standard) {
					var standardPrice 	= Number(standard || 0);					
					var salePrice 		= Number(sale || 0);
					var priceHtml = "";
					
					if (standardPrice > 0 && standardPrice > salePrice && !model.subproduct) {
						// show both prices
						priceHtml = priceHtml + '<span class="standardprice"> was ' + app.currencyCodes[model.pricing.currencyCode] + standardPrice.toFixed(2) + '</span>';
					}
					
					if (salePrice > 0) {
						salesPriceHtml = '<span class="salesprice">' + app.currencyCodes[model.pricing.currencyCode] + salePrice.toFixed(2) + '</span>';
					} else {
						salesPriceHtml = '<span class="salesprice">N/A</span>';
					}
					
					priceHtml = salesPriceHtml + priceHtml;
					
					jQuery(this.containerId+" .productinfo .price:first").html(priceHtml);
					// containerId contains #, get rid of it before finding the right price div
					jQuery(this.containerId+" #pdpATCDiv"+this.containerId.substring(1)+" .price").html(priceHtml);
				},
				
				// Used to update the total selected and total price on the product set pages. 
				showTotalPriceAndQty: function(totalPrice, totalQty) {
					jQuery(this.containerId+" #pdpATCDiv"+this.containerId.substring(1)+" .totalsetpricing").html(app.currencyCodes[model.pricing.currencyCode] + totalPrice.toFixed(2));
					jQuery(this.containerId+" #pdpATCDiv"+this.containerId.substring(1)+" .totalsetitems").html(totalQty.toFixed(0));
				}, 
				
				/**
				 * returns a computed price for this product
				 */				
				getPrice: function() {
					return computePrice(this);
				},

				/*
				* receives 2 or 1 var attrib values and tries to figure out if there is a variant with these values.
				* returns true/false
				*/
				isVariation: function(val1, val2) {
					var variant = null;

					for (var i=0; i<model.variations.variants.length; i++) {
						variant = model.variations.variants[i];
						if (variant.attributes[val1.id] == val1.val && (val2 == undefined || variant.attributes[val2.id] == val2.val)) {
							return true;
						}
					}
					/*
					 * apparently there is no way to break out of jQuery.each half way :(
					jQuery.each(model.variations.variants, function(){
						if (!found && this.attributes[val1.id] == val1.val && this.attributes[val2.id] == val2.val) {
							found = true;
							return;
						}
					});*/
					return false;
				},
				
				/*
				* find 0 or more variants matching the given attribs object(s)
				* return null or found variants
				*/
				findVariations: function(attr, variants) {
					var foundVariants = new Array();
					variants = variants || model.variations.variants;
					
					var variant = null;
					for (var i=0; i<variants.length; i++) {
						variant = variants[i];
						if (variant.attributes[attr.id] === attr.val) {
							foundVariants.push(variant);
						}
					}
					
					return foundVariants;
				},
				
				/*
				* find a variant with the given attribs object
				* return null or found variation json
				*/
				findVariation: function(attrs) {
					if (!this.checkAttrs(attrs)) {
						return null;
					}

					var attrToStr = function(attrObj) {
						var result = "";
						jQuery.each(model.variations.attributes, function(){
							result += attrObj[this.id];
						});
						return result;
					}

					var attrsStr = attrToStr(attrs);

					for (var i=0; i<model.variations.variants.length; i++) {
						variant = model.variations.variants[i];
						if (attrToStr(variant.attributes) === attrsStr) {
							return variant;
						}
					}
					return null;
				},
				
				// find a variation with the give id otherwise empty object
				findVariationById: function(id) {

					for (var i=0; i<model.variations.variants.length; i++) {
					// IE7 does NOT support this!!!
					//for each(var variation in model.variations.variants) {
						var variation = model.variations.variants[i];
						if (variation && variation.id === id) {
							return variation;
						}
					}

					return {};
				},

				/*
				* see if the specified attrs object has all the variation attributes present in it
				* return true/false
				*/
				checkAttrs: function(attrs) {
					for (var i=0; i<model.variations.attributes.length; i++) {
						if (attrs[model.variations.attributes[i].id] == null) {
							return false;
						}
					}
					return true;
				},
				
				// given an id, return attr definition from model.variations.attributes
				getAttrByID: function(id) {
					for (var i=0; i<model.variations.attributes.length; i++) {
						if (model.variations.attributes[i].id === id) {
							return model.variations.attributes[i];
						}
					}
					return {};
				},
				
				// returns current availability status e.g. in_stock, preorder etc.
				getAvStatus: function() {
					if ((this.variant || this.master) && this.selectedVar != null) {
						return this.selectedVar.avStatus;
					}
					else {
						return model.avStatus;
					}
				},
				
				// return available to sell qty
				getATS: function() {
					if ((this.variant || this.master) && this.selectedVar != null) {
						return this.selectedVar.ATS;
					}
					else {
						return model.ATS;
					}
				},
				
				// return available to sell qty
				getATSMessage: function() {
					if ((this.variant || this.master) && this.selectedVar != null) {
						return this.selectedVar.ATSMessage;
					}
					else {
						return model.ATSMessage;
					}
				},
				
				// returns in stock date 
				getInStockDate: function() {
					if ((this.variant || this.master) && this.selectedVar != null) {
						return this.selectedVar.inStockDate;
					}
					else {
						return model.inStockDate;
					}
				},
				
				// determine if A2C button is enabled or disabled
				// true if enabled, false otherwise
				isA2CEnabled: function() {
					if (this.variant || this.master) {
						if (this.selectedVar != null) {
							return this.isStatusOrderable(this.selectedVar.avStatus);
						}
						else {
							return false;
						}
					}
					else {
						return this.isStatusOrderable(model.avStatus);
					}
				},
				
				// Checks if the given status is orderable
				isStatusOrderable: function(avStatus) {
					return avStatus === app.constants.AVAIL_STATUS_IN_STOCK 
					    || avStatus === app.constants.AVAIL_STATUS_PREORDER
					    || avStatus === app.constants.AVAIL_STATUS_BACKORDER;
				},
				

				// work horse of the product detail page getting everything tied together i.e. all the dynamic stuff 
				// and one time initialization. called only ONCE
				// bind all the product display events and handlers
				// load variants in case this is a variation product
				// bind subproducts a2c button enable event handler
				show: function(options) {
					// preserve this instance
					var thisProduct = this;

					// bind VariationsLoaded which gets fired when the variation data is received from the server
					jQuery(this).bind("VariationsLoaded", {}, function(e, source){
						// if this product instance is a variant then try to find its corresponding json based on the current attribute values 
						if (thisProduct.variant && thisProduct.selectedVar == null) {							
							thisProduct.selectedVar = thisProduct.findVariation(thisProduct.selectedVarAttribs);							
						}
						// enable/disable unavailable values
						if (source && source == "loadVariants") {
							thisProduct.resetVariations();
						}
						
						// Update the product title - for the selected variant
						if (thisProduct.variant &&  thisProduct.selectedVar != null)
						{
							jQuery(this.containerId + " h1.productname").text(thisProduct.selectedVar.displayName);
						}
						
						// Update subproduct links (and title for variant)
						if (thisProduct.subproduct && thisProduct.selectedVar != null && (thisProduct.variant || thisProduct.master))
						{
							var newURL = app.util.appendParamToURL(app.URLs.getProductUrl, "pid", thisProduct.selectedVar.id);
							jQuery(this.containerId + " h2.productname a").attr("href", newURL);

							if (thisProduct.variant)
							{
								jQuery(this.containerId + " h2.productname a").text(thisProduct.selectedVar.displayName);
							}
						}
						thisProduct.refreshView();
					});

					this.containerId 	= "#"+options.containerId;					
					var isQuickView 	= false;

					if (options.source && options.source == "quickview") {
						isQuickView = true;
					}
					
					myContainerId = this.containerId;
					
					// bind click handlers for prev/next links
					getNavLinks();
					
					// size chart click binding
					getSizeChart();
					
					//get video overlay
					getMediaLinks();
					
					// variation attributes handling in case it is a master or a variant product
					if (model.master || model.variant) {
						loadVariants(this); // make a server call to load the variants, this is due to the performance reasons
						// meanwhile display the available variation attributes
						
						// loop thru all the swatches and bind events etc.
						jQuery(thisProduct.containerId + " .variationattributes .swatches").each(function(){
							var thisSwatch 	= jQuery(this);
							var pdpVarId 	= thisSwatch.data("data"); // data is id which is set via app.hiddenData onload
							var attrDef 	= thisProduct.getAttrByID(pdpVarId);
							
							if (!attrDef) {
								return;
							}
							
							// grab the currently selected attr val																
							thisProduct.selectedVarAttribs[pdpVarId] =  thisSwatch.find(".selected a").html();
							
							// click handler for swatches links
							var varEventHandler = function(e){									
								var thisObj = jQuery(this);
								
								e.data = {id: pdpVarId, val: this.innerHTML};

								if (thisObj.parent().hasClass("unselectable")) {
									return false;
								}
								else if (thisObj.parent().hasClass("selected")) {
									// deselection
									e.data = {id: pdpVarId, val: null};
									thisObj.parent().removeClass("selected");
									// clear the current selection
									thisProduct.resetVariations();
									thisProduct.varAttrSelected(e);
								}
								else {
									// selection
									e.data = {id: pdpVarId, val: this.innerHTML};
									// remove the current selection										
									thisSwatch.find(".selected").removeClass("selected");										
									thisObj.parent().addClass("selected");
									thisProduct.varAttrSelected(e);
								}																
								
								return false;
							}
							
							// all swtach anchors
							var varJqryObjs = thisSwatch.find("a.swatchanchor");
							
							// if its a color attr then render its swatches and images
							if (pdpVarId === "color") {
								var colorAttrDef = thisProduct.getAttrByID('color');
								
								varJqryObjs.each(function(){
								
									// given a variation attr value, find its swatch image url
									var findSwatch = function(val) {
										for (var i=0; i<colorAttrDef.vals.length; i++){
											if (colorAttrDef.vals[i].val === val) {													
												return colorAttrDef.vals[i].images.swatch;
											}
										}
										return ""; // no swatch image found
									}
									
									var swatchUrl = findSwatch(this.innerHTML); // find swatch url
									
									if (swatchUrl && swatchUrl != "") {
										jQuery(this).css("color", "transparent").parent().css("background", "url(" + swatchUrl + ")");
									}
									else {
										jQuery(this).css("color", "transparent"); // no swatch image found
									}
								});
								
								// swatches click, hover and mouseleave event handlers
								varJqryObjs.data("data", {id: pdpVarId}).click(varEventHandler)
								.hover(function(e){
									thisProduct.showSelectedVarAttrVal("color", this.innerHTML);										
									thisProduct.showImages(this.innerHTML, colorAttrDef.vals)
								}).mouseleave(function(e) {
									if (thisProduct.selectedVarAttribs["color"]) {
										thisProduct.showImages(thisProduct.selectedVarAttribs["color"], colorAttrDef.vals)
									}
									else {
										thisProduct.showImages("", [{val: "", images: model.images}]);
									}
									
									thisProduct.showSelectedVarAttrVal("color", thisProduct.selectedVarAttribs["color"] || "");
								});
							}
							else {								
								// not a color swatch, we only have click handler for this type of variation attribute e.g. width, length etc.
								varJqryObjs.data("data", {id: pdpVarId}).click(varEventHandler);
							}
						});
						
						// loop thru all the non-swatches attributes and bind events etc.
						jQuery(thisProduct.containerId + " .variationattributes .variantdropdown select").each(function(){							
							var ele = jQuery(this);
							var data = ele.data("data"); // data is id
							if (ele[0].selectedIndex >= 0 && ele[0].options[ele[0].selectedIndex].value != "") {
								// grab the currently selected val
								thisProduct.selectedVarAttribs[data] = ele[0].options[ele[0].selectedIndex].value;
							}
							// default ui i.e. drop down
							ele.data("data", {id: data, val: ''}).change(function(e){
									// We no longer have a 'Select..' as the first option.
								    //if (this.selectedIndex == 0 && this.options.length == 1) { return; }

									e.data = jQuery(this).data("data");
									// this.selectedIndex == 0, it is deselection
									e.data.val = this.options[this.selectedIndex].value;
									
									/*if (this.selectedIndex == 0) {
										// deselection
										// clear the current selection
										thisProduct.resetVariations();
									}*/
									
									thisProduct.varAttrSelected(e);
								});
						});
						
						if (thisProduct.selectedVarAttribs["color"]) {
							// show swatch related images for the current value	
							thisProduct.showImages(thisProduct.selectedVarAttribs["color"], thisProduct.getAttrByID('color').vals);
						}
						else {
							// show images and bind hover event handlers for small/thumbnails to toggle large image								
							thisProduct.showImages("", [{val: "", images: model.images}]);
						}
					}
					else {
						// show images and bind hover event handlers for small/thumbnails to toggle large image								
						thisProduct.showImages("", [{val: "", images: model.images}]);
					}
					
					// bind product options event(s)
					getOptionsDiv(this);

					// DE. Replaced logic below with simpler version. Require update in qty box for everything 
					// except product set products which have no qty and no availability refresh for variants. 
					/*
					if(!model.productSet) {
						// quantity box
						if (!model.bundle) {
							getQtyBox(this);
						}// update availability for a bundle product, for everything else its done inside getQtyBox
						else if (model.bundle) {
						
						// Don't do for variants as the UI refresh calls this again
						if (!model.bundle && !model.master)
						{
							setAvailabilityMsg(createAvMessage(this, 1));
						}
					} */
					
					if(!model.productSet) {
						getQtyBox(this);
						if (!model.master)
						{
							setAvailabilityMsg(createAvMessage(this, 1));
						}
				    }

					// Add to cart button click binding
					var addToCartBtn = getAddToCartBtn(this);
					// intial display of A2C button
					// if the price is 0 or not available, its disabled
					// if not in stock, its disabled
					if (!(this.getPrice() > 0) || 
						model.master || model.variant || model.productSet || model.bundle || 
						(!model.inStock && model.avStatus === app.constants.AVAIL_STATUS_NOT_AVAILABLE && !model.productSet)) {
						if (model.subproduct)
						{
							switchOnVariantAvailability(false, this.containerId);
							this.disableA2CButton();
						}
						else
						{
							addToCartBtn.attr("disabled", "true");
						}
					}
						
					// if the bundled products are standard products then determine disability of the a2c button by checking each product's availability
					if (model.bundle) {
						
						var bundleA2CEnabled = false;
						for (var i = 0; i < thisProduct.subProducts.length; i++) {
							var subProduct = thisProduct.subProducts[i];
							bundleA2CEnabled = subProduct.isA2CEnabled();
							
							//console.debug("subproduct: " +bundleA2CEnabled);
							
							if (!bundleA2CEnabled) {
								break;
							}
						}
						// if any of the bundled product has its A2C button disabled then the bundle is not orderable
						//bundleA2CEnabled = true;
						//console.debug(bundleA2CEnabled);
						if (!bundleA2CEnabled) {
							addToCartBtn.attr("disabled", "true");
							//addToCartBtn.css("display", "none");
						} 
						else {
							addToCartBtn.removeAttr("disabled");
						}
					}						

					// customer rating section only displayed for the main product
					if (!model.productSetProduct && !model.bundled) {
						if (!model.productSet && !isQuickView && !model.bundle) {							
							getRatingSection(this.containerId);							
						}
					}
					
					// wish list, sent to friend, add to gift
					getMiscLinks(this);
							
					// recommendations carosel
					loadRecommendations(this.containerId);

					// product tabs
					getTabs(this.containerId);	
					
					getArpTabs(this.containerId);
					
					// see if have any subproducts and bind AddtoCartEnabled event
					jQuery.each(thisProduct.subProducts, function(){
						jQuery(this).bind("AddtoCartEnabled", {},
							/**
							* Event handler when a subproduct of a product set or a bundle is selected.
							* Basically enable the add to cart button or do other screen refresh if needed like price etc.
							*/
							function() {
								// enable Add to cart button if all the sub products have been selected
								// and show the updated price
								var enableAddToCart = true;
								var subProducts = thisProduct.subProducts;
								var price = new Number();
								var totalPrice = new Number(0);
								var totalQty   = new Number(0);
								
								// Iterate over the sub products. Need to determine 2 things:
								// 1. If this add to basket for bundle or set is enabled/disabled (this is the global add)
								// 2. If this is a product set we want to iterate over the sub products to determine the 
								//    total number of products selected and the total cost of those products. 
								for (var i = 0; i < subProducts.length; i++) {
									
									if (((subProducts[i].variant || subProducts[i].master) && subProducts[i].selectedVar == null) ||
										(!subProducts[i].bundled && (subProducts[i].selectedOptions["Quantity"] == undefined ||
										subProducts[i].selectedOptions["Quantity"] <= 0))) {
										enableAddToCart = true;
									}
									else
									{
										// If the sub product is valid but add to cart is disabled (i.e. may be out of stock)
										// then still disable the global add to cart button. 
										//if (thisProduct.productSet && !subProducts[i].isA2CEnabled())
										//{
										//	enableAddToCart = false;
										//}
																			
										if (subProducts[i].selectedVar != null)
										{
											subProducts[i].selectedOptions.pid = subProducts[i].selectedVar.pid;
										}
										else
										{
											subProducts[i].selectedOptions.pid = subProducts[i].pid;
										}
	
										price = price + new Number(subProducts[i].getPrice());
										
										if (thisProduct.productSet)
										{
											var subProdQty = new Number(subProducts[i].selectedOptions["Quantity"]);
						
											// Only add products that are in stock or have qty > 0
											var avStatus = subProducts[i].getAvStatus(); // availability status

											if (subProducts[i].getPrice() != null && subProducts[i].getPrice() > 0 && 
											    subProdQty != Number.NaN && subProdQty > 0 &&
											    avStatus != app.constants.AVAIL_STATUS_NOT_AVAILABLE)
											{
											    totalPrice = totalPrice + new Number(new Number(subProducts[i].getPrice()) * subProdQty);
										        totalQty = totalQty + subProdQty;
											}

										}
									}
								}
								
								// No products available for add all so disable the button
								if (thisProduct.productSet && totalQty <= 0 )
								{
									enableAddToCart = false;
								}
								
								if (enableAddToCart && (model.productSet || model.inStock) && price > 0) {
									//jQuery(thisProduct.containerId+" .addtocartbutton:last").removeAttr("disabled");
									thisProduct.enableMasterA2CButton();
									// show total price
									thisProduct.showUpdatedPrice(price);
								}
								else {
									// jQuery(thisProduct.containerId+" .addtocartbutton:last").attr("disabled", "true");
									thisProduct.disableMasterA2CButton();
									
									// show total price as it may be 0.
									thisProduct.showUpdatedPrice(price);									
								}
								
								if (thisProduct.productSet)
								{
								    thisProduct.showTotalPriceAndQty(totalPrice, totalQty);
								}
							}
						);
					});
					
					// trigger the AddToCartEnabled manually if there are no variant subproducts in the product set
					// Fix for YOD-1313
					if (thisProduct.productSet && !thisProduct.hasVariantSubProducts())
					{
						jQuery.each(thisProduct.subProducts, function(){
							jQuery(this).trigger("AddtoCartEnabled");	
						});
					}
				},

				toString: function() {
					return this.model;
				},
				
				// Returns true if the product is a set and has 
				// at least one variant product in its subproducts
				// YOD-1313
				hasVariantSubProducts : function() {
					
					if (!this.productSet || this.subProducts.length == 0)
					{
						return false;
					}
					for (var i = 0; i < this.subProducts.length; i++) {
						subproduct = this.subProducts[i];
						if (subproduct.master || subproduct.variant )
						{
							return true;
						}
					}
					return false;
				}
			}
		} // Product defintion end
	}
	else {
		// dw namespace has not been defined yet i.e. app object is unavailable
		alert("app is undefined!");
	}
})(app);

/*
 * jScrollPane - v2.0.0beta11 - 2011-07-04
 * http://jscrollpane.kelvinluck.com/
 *
 * Copyright (c) 2010 Kelvin Luck
 * Dual licensed under the MIT and GPL licenses.
 */
(function(b,a,c){b.fn.jScrollPane=function(e){function d(D,O){var az,Q=this,Y,ak,v,am,T,Z,y,q,aA,aF,av,i,I,h,j,aa,U,aq,X,t,A,ar,af,an,G,l,au,ay,x,aw,aI,f,L,aj=true,P=true,aH=false,k=false,ap=D.clone(false,false).empty(),ac=b.fn.mwheelIntent?"mwheelIntent.jsp":"mousewheel.jsp";aI=D.css("paddingTop")+" "+D.css("paddingRight")+" "+D.css("paddingBottom")+" "+D.css("paddingLeft");f=(parseInt(D.css("paddingLeft"),10)||0)+(parseInt(D.css("paddingRight"),10)||0);function at(aR){var aM,aO,aN,aK,aJ,aQ,aP=false,aL=false;az=aR;if(Y===c){aJ=D.scrollTop();aQ=D.scrollLeft();D.css({overflow:"hidden",padding:0});ak=D.innerWidth()+f;v=D.innerHeight();D.width(ak);Y=b('<div class="jspPane" />').css("padding",aI).append(D.children());am=b('<div class="jspContainer" />').css({width:ak+"px",height:v+"px"}).append(Y).appendTo(D)}else{D.css("width","");aP=az.stickToBottom&&K();aL=az.stickToRight&&B();aK=D.innerWidth()+f!=ak||D.outerHeight()!=v;if(aK){ak=D.innerWidth()+f;v=D.innerHeight();am.css({width:ak+"px",height:v+"px"})}if(!aK&&L==T&&Y.outerHeight()==Z){D.width(ak);return}L=T;Y.css("width","");D.width(ak);am.find(">.jspVerticalBar,>.jspHorizontalBar").remove().end()}Y.css("overflow","auto");if(aR.contentWidth){T=aR.contentWidth}else{T=Y[0].scrollWidth}Z=Y[0].scrollHeight;Y.css("overflow","");y=T/ak;q=Z/v;aA=q>1;aF=y>1;if(!(aF||aA)){D.removeClass("jspScrollable");Y.css({top:0,width:am.width()-f});n();E();R();w();ai()}else{D.addClass("jspScrollable");aM=az.maintainPosition&&(I||aa);if(aM){aO=aD();aN=aB()}aG();z();F();if(aM){N(aL?(T-ak):aO,false);M(aP?(Z-v):aN,false)}J();ag();ao();if(az.enableKeyboardNavigation){S()}if(az.clickOnTrack){p()}C();if(az.hijackInternalLinks){m()}}if(az.autoReinitialise&&!aw){aw=setInterval(function(){at(az)},az.autoReinitialiseDelay)}else{if(!az.autoReinitialise&&aw){clearInterval(aw)}}aJ&&D.scrollTop(0)&&M(aJ,false);aQ&&D.scrollLeft(0)&&N(aQ,false);D.trigger("jsp-initialised",[aF||aA])}function aG(){if(aA){am.append(b('<div class="jspVerticalBar" />').append(b('<div class="jspCap jspCapTop" />'),b('<div class="jspTrack" />').append(b('<div class="jspDrag" />').append(b('<div class="jspDragTop" />'),b('<div class="jspDragBottom" />'))),b('<div class="jspCap jspCapBottom" />')));U=am.find(">.jspVerticalBar");aq=U.find(">.jspTrack");av=aq.find(">.jspDrag");if(az.showArrows){ar=b('<a class="jspArrow jspArrowUp" />').bind("mousedown.jsp",aE(0,-1)).bind("click.jsp",aC);af=b('<a class="jspArrow jspArrowDown" />').bind("mousedown.jsp",aE(0,1)).bind("click.jsp",aC);if(az.arrowScrollOnHover){ar.bind("mouseover.jsp",aE(0,-1,ar));af.bind("mouseover.jsp",aE(0,1,af))}al(aq,az.verticalArrowPositions,ar,af)}t=v;am.find(">.jspVerticalBar>.jspCap:visible,>.jspVerticalBar>.jspArrow").each(function(){t-=b(this).outerHeight()});av.hover(function(){av.addClass("jspHover")},function(){av.removeClass("jspHover")}).bind("mousedown.jsp",function(aJ){b("html").bind("dragstart.jsp selectstart.jsp",aC);av.addClass("jspActive");var s=aJ.pageY-av.position().top;b("html").bind("mousemove.jsp",function(aK){V(aK.pageY-s,false)}).bind("mouseup.jsp mouseleave.jsp",ax);return false});o()}}function o(){aq.height(t+"px");I=0;X=az.verticalGutter+aq.outerWidth();Y.width(ak-X-f);try{if(U.position().left===0){Y.css("margin-left",X+"px")}}catch(s){}}function z(){if(aF){am.append(b('<div class="jspHorizontalBar" />').append(b('<div class="jspCap jspCapLeft" />'),b('<div class="jspTrack" />').append(b('<div class="jspDrag" />').append(b('<div class="jspDragLeft" />'),b('<div class="jspDragRight" />'))),b('<div class="jspCap jspCapRight" />')));an=am.find(">.jspHorizontalBar");G=an.find(">.jspTrack");h=G.find(">.jspDrag");if(az.showArrows){ay=b('<a class="jspArrow jspArrowLeft" />').bind("mousedown.jsp",aE(-1,0)).bind("click.jsp",aC);x=b('<a class="jspArrow jspArrowRight" />').bind("mousedown.jsp",aE(1,0)).bind("click.jsp",aC);
if(az.arrowScrollOnHover){ay.bind("mouseover.jsp",aE(-1,0,ay));x.bind("mouseover.jsp",aE(1,0,x))}al(G,az.horizontalArrowPositions,ay,x)}h.hover(function(){h.addClass("jspHover")},function(){h.removeClass("jspHover")}).bind("mousedown.jsp",function(aJ){b("html").bind("dragstart.jsp selectstart.jsp",aC);h.addClass("jspActive");var s=aJ.pageX-h.position().left;b("html").bind("mousemove.jsp",function(aK){W(aK.pageX-s,false)}).bind("mouseup.jsp mouseleave.jsp",ax);return false});l=am.innerWidth();ah()}}function ah(){am.find(">.jspHorizontalBar>.jspCap:visible,>.jspHorizontalBar>.jspArrow").each(function(){l-=b(this).outerWidth()});G.width(l+"px");aa=0}function F(){if(aF&&aA){var aJ=G.outerHeight(),s=aq.outerWidth();t-=aJ;b(an).find(">.jspCap:visible,>.jspArrow").each(function(){l+=b(this).outerWidth()});l-=s;v-=s;ak-=aJ;G.parent().append(b('<div class="jspCorner" />').css("width",aJ+"px"));o();ah()}if(aF){Y.width((am.outerWidth()-f)+"px")}Z=Y.outerHeight();q=Z/v;if(aF){au=Math.ceil(1/y*l);if(au>az.horizontalDragMaxWidth){au=az.horizontalDragMaxWidth}else{if(au<az.horizontalDragMinWidth){au=az.horizontalDragMinWidth}}h.width(au+"px");j=l-au;ae(aa)}if(aA){A=Math.ceil(1/q*t);if(A>az.verticalDragMaxHeight){A=az.verticalDragMaxHeight}else{if(A<az.verticalDragMinHeight){A=az.verticalDragMinHeight}}av.height(A+"px");i=t-A;ad(I)}}function al(aK,aM,aJ,s){var aO="before",aL="after",aN;if(aM=="os"){aM=/Mac/.test(navigator.platform)?"after":"split"}if(aM==aO){aL=aM}else{if(aM==aL){aO=aM;aN=aJ;aJ=s;s=aN}}aK[aO](aJ)[aL](s)}function aE(aJ,s,aK){return function(){H(aJ,s,this,aK);this.blur();return false}}function H(aM,aL,aP,aO){aP=b(aP).addClass("jspActive");var aN,aK,aJ=true,s=function(){if(aM!==0){Q.scrollByX(aM*az.arrowButtonSpeed)}if(aL!==0){Q.scrollByY(aL*az.arrowButtonSpeed)}aK=setTimeout(s,aJ?az.initialDelay:az.arrowRepeatFreq);aJ=false};s();aN=aO?"mouseout.jsp":"mouseup.jsp";aO=aO||b("html");aO.bind(aN,function(){aP.removeClass("jspActive");aK&&clearTimeout(aK);aK=null;aO.unbind(aN)})}function p(){w();if(aA){aq.bind("mousedown.jsp",function(aO){if(aO.originalTarget===c||aO.originalTarget==aO.currentTarget){var aM=b(this),aP=aM.offset(),aN=aO.pageY-aP.top-I,aK,aJ=true,s=function(){var aS=aM.offset(),aT=aO.pageY-aS.top-A/2,aQ=v*az.scrollPagePercent,aR=i*aQ/(Z-v);if(aN<0){if(I-aR>aT){Q.scrollByY(-aQ)}else{V(aT)}}else{if(aN>0){if(I+aR<aT){Q.scrollByY(aQ)}else{V(aT)}}else{aL();return}}aK=setTimeout(s,aJ?az.initialDelay:az.trackClickRepeatFreq);aJ=false},aL=function(){aK&&clearTimeout(aK);aK=null;b(document).unbind("mouseup.jsp",aL)};s();b(document).bind("mouseup.jsp",aL);return false}})}if(aF){G.bind("mousedown.jsp",function(aO){if(aO.originalTarget===c||aO.originalTarget==aO.currentTarget){var aM=b(this),aP=aM.offset(),aN=aO.pageX-aP.left-aa,aK,aJ=true,s=function(){var aS=aM.offset(),aT=aO.pageX-aS.left-au/2,aQ=ak*az.scrollPagePercent,aR=j*aQ/(T-ak);if(aN<0){if(aa-aR>aT){Q.scrollByX(-aQ)}else{W(aT)}}else{if(aN>0){if(aa+aR<aT){Q.scrollByX(aQ)}else{W(aT)}}else{aL();return}}aK=setTimeout(s,aJ?az.initialDelay:az.trackClickRepeatFreq);aJ=false},aL=function(){aK&&clearTimeout(aK);aK=null;b(document).unbind("mouseup.jsp",aL)};s();b(document).bind("mouseup.jsp",aL);return false}})}}function w(){if(G){G.unbind("mousedown.jsp")}if(aq){aq.unbind("mousedown.jsp")}}function ax(){b("html").unbind("dragstart.jsp selectstart.jsp mousemove.jsp mouseup.jsp mouseleave.jsp");if(av){av.removeClass("jspActive")}if(h){h.removeClass("jspActive")}}function V(s,aJ){if(!aA){return}if(s<0){s=0}else{if(s>i){s=i}}if(aJ===c){aJ=az.animateScroll}if(aJ){Q.animate(av,"top",s,ad)}else{av.css("top",s);ad(s)}}function ad(aJ){if(aJ===c){aJ=av.position().top}am.scrollTop(0);I=aJ;var aM=I===0,aK=I==i,aL=aJ/i,s=-aL*(Z-v);if(aj!=aM||aH!=aK){aj=aM;aH=aK;D.trigger("jsp-arrow-change",[aj,aH,P,k])}u(aM,aK);Y.css("top",s);D.trigger("jsp-scroll-y",[-s,aM,aK]).trigger("scroll")}function W(aJ,s){if(!aF){return}if(aJ<0){aJ=0}else{if(aJ>j){aJ=j}}if(s===c){s=az.animateScroll}if(s){Q.animate(h,"left",aJ,ae)
}else{h.css("left",aJ);ae(aJ)}}function ae(aJ){if(aJ===c){aJ=h.position().left}am.scrollTop(0);aa=aJ;var aM=aa===0,aL=aa==j,aK=aJ/j,s=-aK*(T-ak);if(P!=aM||k!=aL){P=aM;k=aL;D.trigger("jsp-arrow-change",[aj,aH,P,k])}r(aM,aL);Y.css("left",s);D.trigger("jsp-scroll-x",[-s,aM,aL]).trigger("scroll")}function u(aJ,s){if(az.showArrows){ar[aJ?"addClass":"removeClass"]("jspDisabled");af[s?"addClass":"removeClass"]("jspDisabled")}}function r(aJ,s){if(az.showArrows){ay[aJ?"addClass":"removeClass"]("jspDisabled");x[s?"addClass":"removeClass"]("jspDisabled")}}function M(s,aJ){var aK=s/(Z-v);V(aK*i,aJ)}function N(aJ,s){var aK=aJ/(T-ak);W(aK*j,s)}function ab(aW,aR,aK){var aO,aL,aM,s=0,aV=0,aJ,aQ,aP,aT,aS,aU;try{aO=b(aW)}catch(aN){return}aL=aO.outerHeight();aM=aO.outerWidth();am.scrollTop(0);am.scrollLeft(0);while(!aO.is(".jspPane")){s+=aO.position().top;aV+=aO.position().left;aO=aO.offsetParent();if(/^body|html$/i.test(aO[0].nodeName)){return}}aJ=aB();aP=aJ+v;if(s<aJ||aR){aS=s-az.verticalGutter}else{if(s+aL>aP){aS=s-v+aL+az.verticalGutter}}if(aS){M(aS,aK)}aQ=aD();aT=aQ+ak;if(aV<aQ||aR){aU=aV-az.horizontalGutter}else{if(aV+aM>aT){aU=aV-ak+aM+az.horizontalGutter}}if(aU){N(aU,aK)}}function aD(){return -Y.position().left}function aB(){return -Y.position().top}function K(){var s=Z-v;return(s>20)&&(s-aB()<10)}function B(){var s=T-ak;return(s>20)&&(s-aD()<10)}function ag(){am.unbind(ac).bind(ac,function(aM,aN,aL,aJ){var aK=aa,s=I;Q.scrollBy(aL*az.mouseWheelSpeed,-aJ*az.mouseWheelSpeed,false);return aK==aa&&s==I})}function n(){am.unbind(ac)}function aC(){return false}function J(){Y.find(":input,a").unbind("focus.jsp").bind("focus.jsp",function(s){ab(s.target,false)})}function E(){Y.find(":input,a").unbind("focus.jsp")}function S(){var s,aJ,aL=[];aF&&aL.push(an[0]);aA&&aL.push(U[0]);Y.focus(function(){D.focus()});D.attr("tabindex",0).unbind("keydown.jsp keypress.jsp").bind("keydown.jsp",function(aO){if(aO.target!==this&&!(aL.length&&b(aO.target).closest(aL).length)){return}var aN=aa,aM=I;switch(aO.keyCode){case 40:case 38:case 34:case 32:case 33:case 39:case 37:s=aO.keyCode;aK();break;case 35:M(Z-v);s=null;break;case 36:M(0);s=null;break}aJ=aO.keyCode==s&&aN!=aa||aM!=I;return !aJ}).bind("keypress.jsp",function(aM){if(aM.keyCode==s){aK()}return !aJ});if(az.hideFocus){D.css("outline","none");if("hideFocus" in am[0]){D.attr("hideFocus",true)}}else{D.css("outline","");if("hideFocus" in am[0]){D.attr("hideFocus",false)}}function aK(){var aN=aa,aM=I;switch(s){case 40:Q.scrollByY(az.keyboardSpeed,false);break;case 38:Q.scrollByY(-az.keyboardSpeed,false);break;case 34:case 32:Q.scrollByY(v*az.scrollPagePercent,false);break;case 33:Q.scrollByY(-v*az.scrollPagePercent,false);break;case 39:Q.scrollByX(az.keyboardSpeed,false);break;case 37:Q.scrollByX(-az.keyboardSpeed,false);break}aJ=aN!=aa||aM!=I;return aJ}}function R(){D.attr("tabindex","-1").removeAttr("tabindex").unbind("keydown.jsp keypress.jsp")}function C(){if(location.hash&&location.hash.length>1){var aL,aJ,aK=escape(location.hash);try{aL=b(aK)}catch(s){return}if(aL.length&&Y.find(aK)){if(am.scrollTop()===0){aJ=setInterval(function(){if(am.scrollTop()>0){ab(aK,true);b(document).scrollTop(am.position().top);clearInterval(aJ)}},50)}else{ab(aK,true);b(document).scrollTop(am.position().top)}}}}function ai(){b("a.jspHijack").unbind("click.jsp-hijack").removeClass("jspHijack")}function m(){ai();b("a[href^=#]").addClass("jspHijack").bind("click.jsp-hijack",function(){var s=this.href.split("#"),aJ;if(s.length>1){aJ=s[1];if(aJ.length>0&&Y.find("#"+aJ).length>0){ab("#"+aJ,true);return false}}})}function ao(){var aK,aJ,aM,aL,aN,s=false;am.unbind("touchstart.jsp touchmove.jsp touchend.jsp click.jsp-touchclick").bind("touchstart.jsp",function(aO){var aP=aO.originalEvent.touches[0];aK=aD();aJ=aB();aM=aP.pageX;aL=aP.pageY;aN=false;s=true}).bind("touchmove.jsp",function(aR){if(!s){return}var aQ=aR.originalEvent.touches[0],aP=aa,aO=I;Q.scrollTo(aK+aM-aQ.pageX,aJ+aL-aQ.pageY);aN=aN||Math.abs(aM-aQ.pageX)>5||Math.abs(aL-aQ.pageY)>5;
return aP==aa&&aO==I}).bind("touchend.jsp",function(aO){s=false}).bind("click.jsp-touchclick",function(aO){if(aN){aN=false;return false}})}function g(){var s=aB(),aJ=aD();D.removeClass("jspScrollable").unbind(".jsp");D.replaceWith(ap.append(Y.children()));ap.scrollTop(s);ap.scrollLeft(aJ)}b.extend(Q,{reinitialise:function(aJ){aJ=b.extend({},az,aJ);at(aJ)},scrollToElement:function(aK,aJ,s){ab(aK,aJ,s)},scrollTo:function(aK,s,aJ){N(aK,aJ);M(s,aJ)},scrollToX:function(aJ,s){N(aJ,s)},scrollToY:function(s,aJ){M(s,aJ)},scrollToPercentX:function(aJ,s){N(aJ*(T-ak),s)},scrollToPercentY:function(aJ,s){M(aJ*(Z-v),s)},scrollBy:function(aJ,s,aK){Q.scrollByX(aJ,aK);Q.scrollByY(s,aK)},scrollByX:function(s,aK){var aJ=aD()+Math[s<0?"floor":"ceil"](s),aL=aJ/(T-ak);W(aL*j,aK)},scrollByY:function(s,aK){var aJ=aB()+Math[s<0?"floor":"ceil"](s),aL=aJ/(Z-v);V(aL*i,aK)},positionDragX:function(s,aJ){W(s,aJ)},positionDragY:function(aJ,s){V(aJ,s)},animate:function(aJ,aM,s,aL){var aK={};aK[aM]=s;aJ.animate(aK,{duration:az.animateDuration,easing:az.animateEase,queue:false,step:aL})},getContentPositionX:function(){return aD()},getContentPositionY:function(){return aB()},getContentWidth:function(){return T},getContentHeight:function(){return Z},getPercentScrolledX:function(){return aD()/(T-ak)},getPercentScrolledY:function(){return aB()/(Z-v)},getIsScrollableH:function(){return aF},getIsScrollableV:function(){return aA},getContentPane:function(){return Y},scrollToBottom:function(s){V(i,s)},hijackInternalLinks:function(){m()},destroy:function(){g()}});at(O)}e=b.extend({},b.fn.jScrollPane.defaults,e);b.each(["mouseWheelSpeed","arrowButtonSpeed","trackClickSpeed","keyboardSpeed"],function(){e[this]=e[this]||e.speed});return this.each(function(){var f=b(this),g=f.data("jsp");if(g){g.reinitialise(e)}else{g=new d(f,e);f.data("jsp",g)}})};b.fn.jScrollPane.defaults={showArrows:false,maintainPosition:true,stickToBottom:false,stickToRight:false,clickOnTrack:true,autoReinitialise:false,autoReinitialiseDelay:500,verticalDragMinHeight:0,verticalDragMaxHeight:99999,horizontalDragMinWidth:0,horizontalDragMaxWidth:99999,contentWidth:c,animateScroll:false,animateDuration:300,animateEase:"linear",hijackInternalLinks:false,verticalGutter:4,horizontalGutter:4,mouseWheelSpeed:0,arrowButtonSpeed:0,arrowRepeatFreq:50,arrowScrollOnHover:false,trackClickSpeed:0,trackClickRepeatFreq:70,verticalArrowPositions:"split",horizontalArrowPositions:"split",enableKeyboardNavigation:true,hideFocus:false,keyboardSpeed:0,initialDelay:300,speed:30,scrollPagePercent:0.8}})(jQuery,this);

/* minified mousewheel actions for scrolling tab contents */
(function(a){function c(b){var c=b||window.event,d=[].slice.call(arguments,1),e=0,f=true,g=0,h=0;b=a.event.fix(c);b.type="mousewheel";if(b.wheelDelta){e=b.wheelDelta/120}if(b.detail){e=-b.detail/3}h=e;if(c.axis!==undefined&&c.axis===c.HORIZONTAL_AXIS){h=0;g=-1*e}if(c.wheelDeltaY!==undefined){h=c.wheelDeltaY/120}if(c.wheelDeltaX!==undefined){g=-1*c.wheelDeltaX/120}d.unshift(b,e,g,h);return a.event.handle.apply(this,d)}var b=["DOMMouseScroll","mousewheel"];a.event.special.mousewheel={setup:function(){if(this.addEventListener){for(var a=b.length;a;){this.addEventListener(b[--a],c,false)}}else{this.onmousewheel=c}},teardown:function(){if(this.removeEventListener){for(var a=b.length;a;){this.removeEventListener(b[--a],c,false)}}else{this.onmousewheel=null}}};a.fn.extend({mousewheel:function(a){return a?this.bind("mousewheel",a):this.trigger("mousewheel")},unmousewheel:function(a){return this.unbind("mousewheel",a)}})})(jQuery)

/* calling scrolling for tabs contents on pdp */
$(function()
{
	var pane = $('.scroll-pane');
	pane.jScrollPane(
	    {
	        showArrows: true,
	        autoReinitialise: true
	    }
	);
	
	/*
	var nextLink = jQuery('a[name="BV_TrackingTag_Review_Display_NextPage"]');
	var prevLink = jQuery('a[name="BV_TrackingTag_Review_Display_PrevPage"]');

	nextLink.click(function() {
		nextLink.attr('href', nextLink.attr('href').replace('scrollToTop=true', 'scrollToTop=false'));
		prevLink.attr('href', prevLink.attr('href').replace('scrollToTop=true', 'scrollToTop=false'));
		return true;
	});
	
	prevLink.click(function() {
		nextLink.attr('href', nextLink.attr('href').replace('scrollToTop=true', 'scrollToTop=false'));
		prevLink.attr('href', prevLink.attr('href').replace('scrollToTop=true', 'scrollToTop=false'));
		return true;
	});
	*/
	
	var nextLink = jQuery('a[name="BV_TrackingTag_Review_Display_NextPage"]');
	var prevLink = jQuery('a[name="BV_TrackingTag_Review_Display_PrevPage"]');
	
	nextLink.live("click", function() {
		jQuery('.jspPane').css('top', '0px');
		return true;
	});
	
	prevLink.live("click", function() {
		jQuery('.jspPane').css('top', '0px');
		return true;
	});
	
});


