"},"url":"/cart/ewc/compact?hostPageType=PromotionsDiscoveryHz&hostSubPageType=null&hostPageRID=GRFZWPS0TDKKZJ5JS4EA&prerender=0","cartCount":0,"freshCartCount":0,"almCartCount":0,"primeWardrobeCartCount":0,"isCompactViewEnabled":true,"isCompactEWCRendered":true,"isWiderCompactEWCRendered":true,"EWCBrowserCacheKey":"EWC_Cache_140-7668623-7957446__USD_en_US","isContentRepainted":false,"clearCache":false,"loadFromCacheWithDelay":0,"delayRenderingTillATF":false};
var hasAui = window.P && window.P.AUI_BUILD_DATE;
var isRTLEnabled = (document.dir === 'rtl');
config.pinnable = config.pinnable && hasAui;
config.isMigrationTreatment = true;
config.flyout = (function() {
var navbelt = document.getElementById('nav-belt');
var navCart = document.getElementById('nav-cart');
var ewcFlyout = document.getElementById('nav-flyout-ewc');
var persistentClassOnBody = 'nav-ewc-persistent-hover nav-ewc-full-height-persistent-hover';
var flyout = {};
var getDocumentScrollTop = function() {
return (document.documentElement && document.documentElement.scrollTop) || document.body.scrollTop;
};
var isWindow = function(obj) {
return obj != null && obj === obj.window;
};
var getWindow = function(elem) {
return isWindow(elem) ? elem : elem.nodeType === 9 && elem.defaultView;
};
var getOffset = function(elem) {
if (elem.getClientRects && !elem.getClientRects().length) {
return {top: 0};
}
var rect = elem.getBoundingClientRect
? elem.getBoundingClientRect()
: {top: 0};
if (rect.width || rect.height) {
var doc = elem.ownerDocument;
var win = getWindow(doc);
return {
top: rect.top + win.pageYOffset - doc.documentElement.clientTop
};
}
return rect;
};
flyout.align = function() {
var newTop = getOffset(navbelt).top - getDocumentScrollTop();
ewcFlyout.style.top = (newTop > 0 ? newTop + 'px' : 0);
};
flyout.hide = function() {
isRTLEnabled
? (ewcFlyout.style.left = '')
: (ewcFlyout.style.right = '');
};
if(typeof config.isCompactEWCRendered === 'undefined') {
if (
(config.isSmallScreenEnabled && viewportWidth() < 1400) ||
(config.isCompactViewEnabled && viewportWidth() >= 1400)
) {
config.isCompactEWCRendered = true;
config.isEWCStateExpanded = true;
config.url = config.url.replace("/gp/navcart/sidebar", "/cart/ewc/compact");
} else {
config.isCompactEWCRendered = false;
}
}
var viewportQualifyForPersistent = function () {
return (config.isCompactEWCRendered)
? true
: viewportWidth() >= 1400;
}
flyout.hasQualifiedViewportForPersistent = viewportQualifyForPersistent;
var getEWCRightOffset = function() {
if (!config.isCompactEWCRendered) {
return 0;
}
var $navbelt = document.getElementById('nav-belt');
if ($navbelt === undefined || $navbelt === null) {
return 0;
}
var EWCCompactViewWidth = (config.isWiderCompactEWCRendered && viewportWidth() >= 1280) ? 130 : 100;
var scrollLeft = (window.pageXOffset !== undefined)
? window.pageXOffset
: (document.documentElement || document.body.parentNode || document.body).scrollLeft;
var scrollXAxis = Math.abs(scrollLeft);
var windowWidth = document.documentElement.clientWidth;
var navbeltWidth = $navbelt.offsetWidth;
var isPartOfNavbarNotVisible = (navbeltWidth + EWCCompactViewWidth) > windowWidth;
if (isPartOfNavbarNotVisible) {
return 0 - (navbeltWidth - scrollXAxis - windowWidth + EWCCompactViewWidth);
} else {
return 0;
}
}
flyout.getEWCRightOffsetCssProperty = function () {
return getEWCRightOffset() + 'px';
}
if (config.isCompactEWCRendered) {
persistentClassOnBody = 'nav-ewc-persistent-hover nav-ewc-compact-view';
if (config.isWiderCompactEWCRendered) { persistentClassOnBody += ' nav-ewc-wider-compact-view'; }
}
flyout.show = function() {
isRTLEnabled
? (ewcFlyout.style.left = flyout.getEWCRightOffsetCssProperty())
: (ewcFlyout.style.right = flyout.getEWCRightOffsetCssProperty());
};
var isIOSDevice = function() {
return (/iPad|iPhone|iPod/.test(navigator.platform) ||
(navigator.platform === 'MacIntel' && navigator.maxTouchPoints > 1)) &&
!window.MSStream;
}
var checkForPersistent = function() {
if (!hasAui) {
return { result: false, reason: 'noAui' };
}
if (!config.enablePersistent) {
return { result: false, reason: 'config' };
}
if (!viewportQualifyForPersistent()) {
return { result: false, reason: 'viewport' };
}
if (isIOSDevice()) {
return { result: false, reason: 'iOS' };
}
if (!config.cartCount > 0) {
return { result: false, reason: 'emptycart' };
}
return { result: true };
};
flyout.ableToPersist = function() {
return checkForPersistent().result;
};
var persistentClassRegExp = '(?:^|\\s)' + persistentClassOnBody + '(?!\\S)';
flyout.applyPageLayoutForPersistent = function() {
if (!document.documentElement.className.match( new RegExp(persistentClassRegExp) )) {
document.documentElement.className += ' ' + persistentClassOnBody;
}
};
flyout.unapplyPageLayoutForPersistent = function() {
document.documentElement.className = document.documentElement.className.replace( new RegExp(persistentClassRegExp, 'g'), '');
};
flyout.persist = function() {
flyout.applyPageLayoutForPersistent();
flyout.show();
if (config.isCompactEWCRendered) {
flyout.align();
}
};
flyout.unpersist = function() {
flyout.unapplyPageLayoutForPersistent();
flyout.hide();
};
var persistentCheck = checkForPersistent();
var resizeCallback = function() {
if (flyout.ableToPersist()) {
flyout.persist();
}
else {
flyout.unpersist();
}
};
flyout.bindEvents = function() {
if (window.addEventListener) {
window.addEventListener('resize', resizeCallback, false);
if (config.isCompactEWCRendered) {
window.addEventListener('scroll', flyout.align, false);
}
}
};
flyout.unbindEvents = function() {
if (window.removeEventListener) {
window.removeEventListener('resize', resizeCallback, false);
if (config.isCompactEWCRendered) {
window.removeEventListener('scroll', flyout.align, false);
}
}
};
var ewcDefaultPersistence = function() {
if (persistentCheck.result) {
flyout.persist();
if (window.ue && ue.tag) {
ue.tag('ewc:persist');
}
} else {
if (window.ue && ue.tag) {
ue.tag('ewc:unpersist');
if (persistentCheck.reason === 'noAui') {
ue.tag('ewc:unpersist:noAui');
}
if (persistentCheck.reason === 'viewport') {
ue.tag('ewc:unpersist:viewport');
}
if (persistentCheck.reason === 'emptycart') {
ue.tag('ewc:unpersist:emptycart');
}
if (persistentCheck.reason === 'iOS') {
ue.tag('ewc:unpersist:iOS');
}
}
}
};
ewcDefaultPersistence();
if (window.ue && ue.tag) {
if (flyout.hasQualifiedViewportForPersistent()) {
ue.tag('ewc:bview');
}
else {
ue.tag('ewc:sview');
}
}
flyout.bindEvents();
flyout.cache = function () {
const cache = window.sessionStorage;
const CACHE_KEY = "EWCBrowserCacheKey";
const CACHE_EXPIRY = "EWCBrowserCacheExpiry";
const CACHE_VALUE = "EWCBrowserCacheValue";
const isSessionStorageValid = function () {
return window && cache && cache instanceof Storage;
};
const isCachePresent = function (key) {
return cache.length > 0 && cache.getItem(key);
}
const isValidType = function (value) {
// Prevents accessing empty key-value and internal methods(prototypes) of storage
// TODO: Log metrics for invalid access;
return value && value.constructor == String;
}
return {
getCache: function (key) {
const value = isCachePresent(key);
return (isValidType(value)) ? value : null;
},
setCache: function (key, value) {
const oldValue = isCachePresent(key);
const cacheExpiryTime = isCachePresent(CACHE_EXPIRY);
// Set the expiry when there's no existing cache - to prevent resetting expiry on page navigation
if (!cacheExpiryTime) {
var currentTime = new Date();
cache.setItem(CACHE_EXPIRY, new Date(currentTime.getTime() + 5 * 60000))
}
// TODO: Log length of old and new cache values when logMetrics is true
cache.setItem(key, value);
},
updateCacheAndEwcContainer: function (cacheKey, newEwcContent) {
const $ = $Nav.getNow("$");
const $currentEwc = $("#ewc-content");
if (!$currentEwc.length) {
var $content = $('#nav-flyout-ewc .nav-ewc-content');
$content.html(newEwcContent);
this.setCache(CACHE_KEY, cacheKey);
if (window.ue && window.ue.count) {
var current = window.ue.count("ewc-init-cache") || 0;
window.ue.count("ewc-init-cache", current + 1);
}
} else {
var $newEwcContent = $('');
var EWC_CONTENT_BODY_SCROLL_SELECTOR = ".ewc-scroller--selected";
if (newEwcContent) { // 1. Updates EWC container with new HTML
var domParser = new DOMParser();
var sandboxedEwcContent = domParser.parseFromString(newEwcContent, 'text/html');
var newEwcHtmlNoScript = sandboxedEwcContent.getElementById('ewc-content');
const $newEwcHtml = $newEwcContent.html(newEwcHtmlNoScript);
const offSet = $currentEwc.find(EWC_CONTENT_BODY_SCROLL_SELECTOR).position().top - $currentEwc.find(".ewc-active-cart--selected").position().top;
$currentEwc.html($newEwcHtml.html());
$currentEwc.find(EWC_CONTENT_BODY_SCROLL_SELECTOR).scrollTop(offSet);
if (typeof window.uex === 'function') {
window.uex('ld', 'ewc-reflect-new-state', {wb: 1});
}
} else {
// 2. Fetches cached response and updates it's html with new state on EWC Update
const cachedEwc = this.getCache(CACHE_VALUE);
$newEwcContent = $newEwcContent[0];
$(cachedEwc).map(function (elementIndex, element) {
$newEwcContent.appendChild((element.id === "ewc-content") ? $currentEwc.clone()[0] : element);
});
newEwcContent = $newEwcContent.innerHTML;
if (window.ue && window.ue.count) {
var current = window.ue.count("ewc-update-cache") || 0;
window.ue.count("ewc-update-cache", current + 1);
}
}
$newEwcContent.remove();
}
this.setCache(CACHE_VALUE, newEwcContent);
},
removeCache: function (key) {
return cache.removeItem(key);
}
}
}
;
return flyout;
}());
const CACHE_KEY = "EWCBrowserCacheKey";
const CACHE_VALUE = "EWCBrowserCacheValue";
const CACHE_EXPIRY = "EWCBrowserCacheExpiry";
var cache = config.flyout.cache();
const isCacheValid = function () {
// Check for page types and tenure of the cache
const clearCache = config.clearCache;
const cacheExpiryTime = cache.getCache(CACHE_EXPIRY);
const isCacheExpired = new Date() > new Date(cacheExpiryTime);
const cacheKey = config.EWCBrowserCacheKey;
const oldCacheKey = cache.getCache(CACHE_KEY);
const isCacheValid = !clearCache && !isCacheExpired && cacheKey == oldCacheKey;
if (!isCacheValid && window.ue && window.ue.count) {
var current = window.ue.count("ewc-cache-invalidated") || 0;
window.ue.count("ewc-cache-invalidated", current + 1);
}
return isCacheValid;
}
function loadFromCache() {
if (window.uet && typeof window.uet === 'function') {
window.uet('bb', 'ewc-loaded-from-cache', {wb: 1});
}
if (cache) {
if (isCacheValid()) {
var content = cache.getCache(CACHE_VALUE);
if (content) {
var $ewcContainer = document.getElementById("nav-flyout-ewc").getElementsByClassName("nav-ewc-content")[0];
var $ewcContent = document.getElementById("ewc-content");
if ($ewcContainer && !$ewcContent) {
$ewcContainer.innerHTML = content;
// Execute scripts from cache
const ewcJavascript = document.getElementById("ewc-content").parentNode.querySelectorAll(':scope > script');
ewcJavascript.forEach(function (script) {
var scriptTag = document.createElement("script");
scriptTag.innerHTML = script.innerHTML;
document.body.appendChild(scriptTag);
});
if (typeof window.uex === 'function') {
window.uex('ld', 'ewc-loaded-from-cache', {wb: 1});
}
} else if (window.ue && window.ue.count && typeof window.ue.count === 'function') {
var currentFailure = window.ue.count("ewc-slow-cache") || 0;
window.ue.count("ewc-slow-cache", currentFailure + 1);
}
}
} else {
cache.removeCache(CACHE_VALUE);
cache.removeCache(CACHE_KEY);
cache.removeCache(CACHE_EXPIRY);
}
}
}
function delayBy(delayTime) {
if (delayTime) {
window.setTimeout(function() {
loadFromCache();
}, delayTime)
} else {
loadFromCache();
}
}
if(config.delayRenderingTillATF) {
(window.AmazonUIPageJS ? AmazonUIPageJS : P).when('atf').execute("EverywhereCartLoadFromCacheOnAtf", function () {
delayBy(config.loadFromCacheWithDelay);
});
} else {
delayBy(config.loadFromCacheWithDelay);
}
return config;
}()));
if (typeof uet === 'function') {
uet('x2', 'ewc', {wb: 1});
}
if (window.ue && ue.tag) {
ue.tag('ewc');
ue.tag('ewc:unrec');
ue.tag('ewc:cartsize:0');
if ( window.P && window.P.AUI_BUILD_DATE ) {
ue.tag('ewc:aui');
} else {
ue.tag('ewc:noAui');
}
}
}());
'
} else {
colorMetadataInPopoverContent += '
' + colorName + '
'
}
}
colorMetadataInPopoverContent += ''
// displaying color dots popover
if ((hasMetadataColorList.length - dotMaximumNumber) > 0) {
productGrid.find("[name=seeMoreColors]").removeClass("hidden");
productGrid.find("[name=seeMoreColors] a").text("+" + (hasMetadataColorList.length - dotMaximumNumber) + " more");
productGrid.find("[name=seeMoreColors] a").css("outline", "none");
productGrid.find("[name=seeMoreColors] a").addClass("seeMoreColorsControl");
}
P.when("A", popoverType, "ready").execute(function (A, popover) {
let instance = popover.get(productGrid.find("[name=seeMoreColors]"));
instance.attrs("dataStrategy", "inline");
instance.attrs("activate", "onclick");
instance.update({"content" : colorMetadataInPopoverContent});
instance.attrs("closeButton", false);
instance.attrs("padding", "none");
if (popoverType === "a-popover") {
instance.attrs("position", "triggerVertical");
instance.attrs("max-height", "300px");
} else {
instance.attrs("header", "Color:");
instance.attrs("max-width", "30rem");
instance.attrs("max-height", "60rem");
instance.attrs("min-width", "20rem");
}
});
productGrid.find("[name=seeMoreColors]").click(function (event) {
event.preventDefault();
P.when("A", popoverType, "ready").execute(function (A, popover) {
// rendering highlight effect for selected color dot in color dots popover
let instance = popover.get(productGrid.find("[name=seeMoreColors]"));
let colorIndex = productGrid.find(".colorDotSelected").attr("data-color-index");
instance.getContent().find("li").removeClass("popoverDropdownActiveLi");
instance.getContent().find("[data-color-index=" + colorIndex + "]").addClass("popoverDropdownActiveLi");
// bind window scroll one time monitoring event
$(window).one("scroll", function (event) {
event.preventDefault();
if (instance.isActive()) {
instance.hide();
}
})
// bind click event for color dot items in color dots popover
instance.getContent().find("li").click(function () {
event.preventDefault();
instance.getContent().find("li").removeClass("popoverDropdownActiveLi");
$(this).addClass("popoverDropdownActiveLi");
productGrid.find("[name=seeMoreColors] a").text($(this).text());
productGrid.find("[name=seeMoreColors] a").append(popoverIcon);
instance.hide();
// replace last color dot in productGrid with selected color dot if selected color is only resides in color dots popover
if ($(this).attr("data-color-index") >= dotMaximumNumber - 1 && productGrid.find(".productVariationDataColorSelectorDotDiv").last().attr("data-color-index") != $(this).attr("data-color-index")) {
productGrid.find(".productVariationDataColorSelectorDotDiv").last().attr("data-color-index", $(this).attr("data-color-index"));
productGrid.find(".productVariationDataColorSelectorDotDiv").last().find(".ColorSelectorColorDotInnerFill").css("background-color", colorNameToMetadataMap.get(hasMetadataColorList.at($(this).attr("data-color-index"))));
// update tooltip of the last color dot for desktop
if (true) {
P.when("A", "a-tooltip", "ready").execute(function (A, popover) {
let instance = popover.get(productGrid.find(".productVariationDataColorSelectorDotDiv").last());
instance.update({"content": hasMetadataColorList.at(productGrid.find(".productVariationDataColorSelectorDotDiv").last().attr("data-color-index"))});
});
}
}
productGrid.find(".productVariationDataColorSelectorDotDiv").removeClass("colorDotSelected");
productGrid.find("#productVariationDataColorSelectorDotList").find("[data-color-index=" + $(this).attr("data-color-index") + "]").addClass("colorDotSelected");
// render size dropdown for selected color
let productInfos = hasMetadataColorMap.get(hasMetadataColorList.at($(this).attr("data-color-index")));
that.renderVariationalAsinFaceOutTemplate(productInfos[0], productGrid, that.getDpLinkForProductInfo(productInfos[0], productCategory), ldMerchantToAsins, productCategory);
that.renderSizeDropDown(productInfos[0], productGrid, productInfos, ldMerchantToAsins, productCategory);
})
// render hover effect for items in color dots popover
instance.getContent().find("li").hover(function (event) {
event.preventDefault();
$(this).addClass("popoverDropdownLiMouseover");
},
function (event) {
event.preventDefault();
$(this).removeClass("popoverDropdownLiMouseover");
}
)
});
})
}
return hasMetadataColorMap.get(hasMetadataColorList.at(0));
},
// private function
renderVariationalDropDown: function (productInfo, productGrid, productInfos, ldMerchantToAsins, productCategory) {
let that = this;
let productInfosInDropdown;
let ungroupedProductInfoList = [];
if (commonModule.isEmpty(productInfo["variationData"]["order"])) {
this.renderVariationalToPlainAsin(productInfo, productGrid, productCategory);
return;
}
let standardGroupIndex = this.processVariationalData(productInfo["variationData"]);
let passedProductInfoList = [];
for (let i = 0; i < productInfos.length; i += 1) {
let groupIndex = this.processVariationalData(productInfos[i]["variationData"]);
if (standardGroupIndex === groupIndex) {
passedProductInfoList.push(productInfos[i]);
} else {
ungroupedProductInfoList.push(productInfos[i]);
}
}
if (passedProductInfoList.length > 1) {
if (commonModule.isNotEmpty(productInfo["variationData"]["color_name"])) {
// only when there are multiple colors have the metadata, will productInfosInDropdown not being empty.
productInfosInDropdown = that.renderVariationColorDimension(productInfo, productGrid, productInfos, ldMerchantToAsins, productCategory);
} else {
passedProductInfoList.sort((a, b) => (parseInt(a["variationData"]["order"]) - parseInt(b["variationData"]["order"])))
productInfosInDropdown = passedProductInfoList;
}
if (commonModule.isNotEmpty(productInfosInDropdown) && productInfosInDropdown.length > 0) {
// those, rendering size dropdown for color dots occupied productGrid or rendering size dropdown for 'size' only variational family, which must have more than 1 children
this.renderSizeDropDown(productInfosInDropdown[0], productGrid, productInfosInDropdown, ldMerchantToAsins, productCategory);
}
} else {
this.renderVariationalToPlainAsin(productInfo, productGrid, productCategory);
}
// render leftover ungrouped asins
for (let i = 0; i < ungroupedProductInfoList.length; ++i) {
// 1. Create the product cell by cloning the grid template, clone the product grid template from productInfoList.jsp#productGridTemplate[name=productGrid]
let productGrid = $("#productGridTemplate [name=productGrid]").clone();
this.renderAsinFaceOut(ungroupedProductInfoList[i], productGrid, this.getDpLink(ungroupedProductInfoList, i, productCategory), ldMerchantToAsins, productCategory);
// 3. Append the product cell to the product list
$("#productInfoList").append(productGrid);
}
},
// private function
renderSizeDropDown: function (productInfo, productGrid, productInfos, ldMerchantToAsins, productCategory) {
let that = this;
// showing outdate indexed product in another productGrids
let ungroupedProductInfoList = [];
let standardGroupIndex = this.processVariationalData(productInfo["variationData"]);
let passedProductInfoList = [];
for (let i = 0; i < productInfos.length; i += 1) {
let groupIndex = this.processVariationalData(productInfos[i]["variationData"]);
if (standardGroupIndex === groupIndex) {
passedProductInfoList.push(productInfos[i]);
} else {
ungroupedProductInfoList.push(productInfos[i]);
}
}
// if no size dimension no handling at all
if (productInfo["variationData"]["size_name"]) {
// if there are more than 1 size, render size dropdown
if (passedProductInfoList.length > 1) {
productGrid.find("[name=chooseSizePromptBox]").removeClass("invisible");
// re-display hidden dropdown
if (true) {
productGrid.find(".desktopDropdown").removeClass("hidden");
} else if (false) {
productGrid.find(".mobileDropdown").removeClass("hidden");
} else {
productGrid.find(".tabletDropdown").removeClass("hidden");
}
// hide size label since we are showing dropdown now
productGrid.find(".marginForSizeLabel").addClass("hidden");
// rendering dropdown
const dropDownIdPrefix = 'VariationalDropDown';
// use the new number as dropdownId to unbind previously bound events
P.when("a-dropdown", "A", "ready").execute(function (dropdown, A) {
productGrid.find("[name=productVariationData]").removeClass("hidden");
productGrid.find("[name=productVariationDataSizeSelector]").removeClass("hidden");
// variable spacing
productGrid.find("[name=variableSpacing]").removeClass("displayNone");
// adding margin to LTD
productGrid.find("div[name=limitedTimeDeal]").addClass("limitedTimeDealSpacing");
productGrid.find("[name=productVariationDataDropDown]").attr("id", dropDownIdPrefix + passedProductInfoList[0]["sortId"].at(0));
let sizeDropdown = dropdown.getSelect(productGrid.find("[name=productVariationDataDropDown]"));
let dropdownSelectEvent = "a:dropdown:" + productGrid.find("[name=productVariationDataDropDown]").attr("id") + ":select";
// removes size options for previous selected color
sizeDropdown.removeOptions(Array.from(Array(sizeDropdown.getOptions().size()).keys()));
for (let i = 0; i < passedProductInfoList.length; i += 1) {
if (passedProductInfoList[i]["lightningDeal"]) {
that.startLdEndTimer(passedProductInfoList[i]["secondsLeftToClaim"], passedProductInfoList[i]["asin"]);
}
let variationDataMap = new Map(Object.entries(passedProductInfoList[i]["variationData"]));
sizeDropdown.addOption({
text: variationDataMap.get("size_name"),
value: i.toString()
}, i);
}
A.on(dropdownSelectEvent, function (data) {
that.renderVariationalDataForFaceOut(productGrid, passedProductInfoList[data.value], that.getDpLink(passedProductInfoList, data.value, productCategory), productCategory)
productGrid.find("[name=chooseSizePromptBox]").addClass("invisible");
});
})
} else {
that.renderTheOnlySizeAvailable(productInfo, productGrid, productCategory);
}
} else {
// when only color dimension available
productGrid.find("[name=chooseSizePromptBox]").addClass("invisible");
that.rerenderATCForNonSelectableProductGrid(passedProductInfoList[0], productGrid, productCategory);
}
// render leftover ungrouped asins
for (let i = 0; i < ungroupedProductInfoList.length; ++i) {
// 1. Create the product cell by cloning the grid template, clone the product grid template from productInfoList.jsp#productGridTemplate[name=productGrid]
let productGrid = $("#productGridTemplate [name=productGrid]").clone();
this.renderAsinFaceOut(ungroupedProductInfoList[i], productGrid, this.getDpLink(ungroupedProductInfoList, i, productCategory), ldMerchantToAsins, productCategory);
// 3. Append the product cell to the product list
$("#productInfoList").append(productGrid);
}
},
// private function
renderTheOnlySizeAvailable: function (productInfo, productGrid, productCategory) {
// productVariationData
productGrid.find("[name=chooseSizePromptBox]").addClass("invisible");
// hide size dropdown && showing size label
if (true) {
productGrid.find(".desktopDropdown").addClass("hidden");
} else if (false) {
productGrid.find(".mobileDropdown").addClass("hidden");
} else {
productGrid.find(".tabletDropdown").addClass("hidden");
}
productGrid.find("[name=productVariationDataSizeSelector]").removeClass("hidden");
productGrid.find(".marginForSizeLabel").removeClass("hidden");
productGrid.find(".marginForSizeLabel").text(productInfo["variationData"]["size_name"]);
this.rerenderATCForNonSelectableProductGrid(productInfo, productGrid, productCategory);
},
// private function
renderVariationalToPlainAsin: function (productInfo, productGrid, productCategory) {
// productVariationData
productGrid.find("[name=chooseSizePromptBox]").addClass("invisible");
productGrid.find("[name=productVariationData]").addClass("hidden");
if (commonModule.isEmpty(productInfo) || commonModule.isEmpty(productInfo["variationData"]) || Object.entries(productInfo["variationData"]).length === 0) {
// This is the case not usually expected, gracefully handling error.
this.getVariationalDataForAsin(productInfo["asin"], productGrid);
} else {
// This is the case either color meta data missing or only child in the promotion.
this.renderVariationalLabelForAsin(productInfo["variationData"], productGrid);
}
this.rerenderATCForNonSelectableProductGrid(productInfo, productGrid, productCategory);
},
// private function - rerender addToCart Button related sections
rerenderATCForNonSelectableProductGrid: function (productInfo, productGrid, productCategory) {
// price
let price;
if (productInfo["priceInfo"]["priceToPay"]) {
price = productInfo["priceInfo"]["priceToPay"]["displayString"];
}
// Add to cart / LD (View Item/View options)
let viewItemBtnBox = productGrid.find("[name=viewItemBtnBox]");
let addToCartBtnBox = productGrid.find("div[name=addToCartBtnBox]");
if (productInfo["blockATCAsin"]) {
// Render the select button for blockATCAsin offers
let selectBtnBox = productGrid.find("[name=selectBtnBox]");
selectBtnBox.removeClass("hidden");
selectBtnBox.find("[name=selectBtn]").attr("href", this.getDpLinkForProductInfo(productInfo, productCategory));
addToCartBtnBox.addClass("hidden");
}
else if (productInfo["lightningDeal"] || false) {
// View Item
viewItemBtnBox.removeClass("hidden");
viewItemBtnBox.find("[name=viewItemBtn]").attr("href", this.getDpLinkForProductInfo(productInfo, productCategory));
addToCartBtnBox.find("[name=addVariationalASINToCartBtn]").addClass("hidden");
addToCartBtnBox.addClass("hidden");
} else {
viewItemBtnBox.addClass("hidden");
if (productInfo["parentAsin"] || commonModule.isEmpty(productInfo["offerListingId"])) {
// See options
addToCartBtnBox.find("[name=seeOptionsBtn]").removeClass("hidden");
addToCartBtnBox.find("[name=seeOptionsBtn]").attr("href", productInfo["detailPageLink"]);
} else {
// Add to cart
let data_json = {
"asin": productInfo["asin"],
"offerListingId": productInfo["offerListingId"],
"price": price,
"quantity": productInfo["quantity"],
"merchantId": productInfo["merchantId"],
"canonicalAsin": productInfo["canonicalAsin"],
"minimumOrderQuantity": productInfo["minimumOrderQuantity"]
};
// set reftagSuffix only for carousel view
if (false && !isFilterOrSort) {
data_json["reftagSuffix"] = productCategoryToReftagSuffix.get(productCategory);
}
addToCartBtnBox.find("[name=addVariationalASINToCartBtn]").addClass("hidden");
addToCartBtnBox.find("[name=addToCartBtn]").removeClass("hidden");
addToCartBtnBox.find("[data-name=addToCartBtn]").attr("data-json", JSON.stringify(data_json));
addToCartBtnBox.find("[data-name=addToCartBtn]").removeClass("inputCursorDisabled");
}
}
// redeem coupon, logic to execute only once is in the redeemCoupon method
this.redeemCoupon(productInfo["asin"], productInfo["offerListingId"]);
},
// private function
renderAsVariationalAsin: function (productInfo, productGrid, dpLink, ldMerchantToAsins, productCategory) {
let startTime = new Date().getTime();
let that = this;
that.renderVariationalAsinFaceOutTemplate(productInfo, productGrid, dpLink, ldMerchantToAsins, productCategory);
let currentSortId = queryParameter["sortId"];
queryParameter["defaultGroupingIdForColorAndSize"] = productInfo["defaultGroupingIdForColorAndSize"];
that.cachedRecordedGroupingIds.push(productInfo["defaultGroupingIdForColorAndSize"]);
queryParameter["recordedGroupingIds"] = [];
$.ajax({
type: "GET",
url: "/promotion/psp/productInfoListForVariationalAsin",
data: $.param(queryParameter, true),
dataType: "json",
contentType: "application/x-www-form-urlencoded; charset=UTF-8",
success: function (productInfos) {
let variationalAsinDataPopulatedBack = false;
if (productInfos.length === 0) {
// Not expected to happen, gracefully handing.
that.renderVariationalToPlainAsin(productInfo, productGrid, productCategory);
}
if (productInfos.length === 1) {
if (commonModule.isNotEmpty(productInfos[0]["variationData"]) && Object.entries(productInfos[0]["variationData"]).length > 0) {
// Based on distinct indexed offer requirement from loadProductInfoListForVariationalAsin, if the variational asin
// is not the only child in the promotion, the returned productInfos length is >= 2.
// Note sortId would only progress when processing plain asin, there by expect when productInfos.length == 1,
// it can only be the only child in the promotion.
productInfo["variationData"] = productInfos[0]["variationData"];
that.renderVariationalToPlainAsin(productInfo, productGrid, productCategory);
} else {
// Not expected to happen, gracefully handing.
that.renderVariationalToPlainAsin(productInfo, productGrid, productCategory);
}
} else {
// Populating VariationalData from SubWorkflow back to MajorWorkflow
for (let productInfoEntry of productInfos) {
if (productInfo["asin"] === productInfoEntry["asin"]) {
productInfo["variationData"] = productInfoEntry["variationData"];
variationalAsinDataPopulatedBack = true;
break;
}
}
if (variationalAsinDataPopulatedBack) {
that.renderVariationalDropDown(productInfo, productGrid, productInfos, ldMerchantToAsins, productCategory);
} else {
that.renderVariationalToPlainAsin(productInfo, productGrid, productCategory);
let newProductGrid = $("#productGridTemplate [name=productGrid]").clone();
that.renderVariationalAsinFaceOutTemplate(productInfos[0], newProductGrid, that.getDpLink(productInfos, 0, productCategory), ldMerchantToAsins, productCategory);
that.renderVariationalDropDown(productInfos[0], newProductGrid, productInfos, ldMerchantToAsins, productCategory);
// 3. Append the product cell to the product list
$("#productInfoList").append(productGrid);
$("#productInfoList").append(newProductGrid);
}
}
},
error: function () {
that.renderVariationalToPlainAsin(productInfo, productGrid, productCategory);
}
})
queryParameter["sortId"] = currentSortId;
queryParameter["recordedGroupingIds"] = that.cachedRecordedGroupingIds;
queryParameter["defaultGroupingId"] = "";
queryParameter["defaultGroupingIdForColorAndSize"] = "";
totalRenderTime += (new Date().getTime() - startTime);
},
// private function
renderPriceForProductGrid: function (productInfo, productGrid) {
let price;
if (productInfo["priceInfo"]["priceToPay"]
|| productInfo["priceInfo"]["pricePerUnit"]
|| productInfo["priceInfo"]["basicPrice"]) {
let productPriceBox = productGrid.find("div[name=productPriceBox]");
price = productInfo["priceInfo"]["priceToPay"]["displayString"];
productPriceBox.find("[name=productPriceToPay]").attr("aria-label", productInfo["priceInfo"]["priceToPay"]["displayString"]);
productPriceBox.find(".a-price-symbol").text(productInfo["priceInfo"]["priceToPay"]["symbol"]);
productPriceBox.find(".a-price-whole").text(productInfo["priceInfo"]["priceToPay"]["whole"]);
productPriceBox.find(".a-price-decimal").text(productInfo["priceInfo"]["priceToPay"]["separator"]);
productPriceBox.find(".a-price-fraction").text(productInfo["priceInfo"]["priceToPay"]["fraction"]);
if (productInfo["priceInfo"]["symbolLast"]) {
productPriceBox.find("[name=symbolLast]").removeClass("hidden");
} else {
productPriceBox.find("[name=symbolFirst]").removeClass("hidden");
}
if (productInfo["priceInfo"]["pricePerUnit"]) {
productPriceBox.find("[name=pricePerUnit]").text("("+productInfo["priceInfo"]["pricePerUnit"]+")");
productPriceBox.find("[name=pricePerUnit]").attr("aria-label", productInfo["priceInfo"]["pricePerUnit"]);
}
if (productInfo["priceInfo"]["bottlingDepositFeeDE"]) {
productPriceBox.find("[name=bottlingDepositFee]").text(productInfo["priceInfo"]["bottlingDepositFeeDE"]);
productPriceBox.find("[name=bottlingDepositFee]").attr("aria-label", productInfo["priceInfo"]["bottlingDepositFeeDE"]);
}
if (productInfo["priceInfo"]["basicPrice"]) {
if(true) {
productPriceBox.find("[name=basicPrice]").text(productInfo["priceInfo"]["basicPrice"]["displayString"]);
productPriceBox.find("[name=basicPrice]").attr("aria-label", productInfo["priceInfo"]["basicPrice"]["displayString"]);
} else if (false) {
//Buy1 - Show Omnibus if applicable
if (productInfo["priceInfo"]["basisPriceType"] == "OMNIBUS_PRICE" ||
productInfo["priceInfo"]["basisPriceType"] == "OMNIBUS_PRICE_STRIKETHROUGH") {
//Handle Omnibus Price for EU
//Message
var omnibusPriceMessage = productInfo["priceInfo"]["basisPriceLabel"] + ": "
+ productInfo["priceInfo"]["basicPrice"]["displayString"];
productGrid.find("[name=omnibusContainer").removeClass("hidden")
productGrid.find("[name=omnibusPrice]").text(omnibusPriceMessage);
productGrid.find("[name=omnibusPrice]").attr("aria-label", omnibusPriceMessage);
//Popover
productGrid.find("[id=omnibusPopoverAction]").attr("data-a-popover", "{\"inlineContent\":\""
+ productInfo["priceInfo"]["basisPricePopover"] + "\"}");
productGrid.find("[id=omnibusPopover]").attr("class", "a-popover-trigger a-declarative a-size-small"); //remove hidden
//variable spacing
productGrid.find("[name=variableSpacing]").removeClass("displayNone");
//adding margin to LTD
productGrid.find("div[name=limitedTimeDeal]").addClass("limitedTimeDealSpacing");
//adding margin to dropdown
productGrid.find("[name=productVariationData]").addClass("selectorMargin");
//adding margin to attributes
productGrid.find("div[name=productVariationDataForPlainAsin").addClass("attributesMargin");
} else {
//Handle Strikethrough Price for non-EU
productPriceBox.find("[name=basicPrice]").text(productInfo["priceInfo"]["basicPrice"]["displayString"]);
productPriceBox.find("[name=basicPrice]").attr("aria-label", productInfo["priceInfo"]["basicPrice"]["displayString"]);
}
} else if (productInfo["priceInfo"]["basicPriceType"] != "OMNIBUS_PRICE") {
//buy X - Don't show Omnibus
productPriceBox.find("[name=basicPrice]").text(productInfo["priceInfo"]["basicPrice"]["displayString"]);
productPriceBox.find("[name=basicPrice]").attr("aria-label", productInfo["priceInfo"]["basicPrice"]["displayString"]);
}
}
productPriceBox.removeClass("invisible");
}
return price
},
// private function
renderImageForProductGrid: function (productInfo, productGrid, dpLink) {
let productImageBox = productGrid.find("div[name=productImageBox]");
productImageBox.find("img[name='productImage']").attr("src", productInfo["imgURL"]);
productImageBox.find("img[name='productImage']").attr("alt", productInfo["imgAlt"]);
productImageBox.find("img[name='productImage']").attr("title", productInfo["imgAlt"]);
productImageBox.find("[data-name='productImageUrl']").attr("href", dpLink);
},
getVariationalDataForAsin: function (asin, productGrid) {
let that = this;
let getItemVariationalDataRequest = {
"asin": asin
};
$.ajax({
type: "GET",
url: "/promotion/twister/variationalData",
data: getItemVariationalDataRequest,
contentType: 'application/x-www-form-urlencoded; charset=UTF-8;',
success: function (variationalData) {
that.renderVariationalLabelForAsin(variationalData, productGrid);
}
})
},
renderVariationalLabelForAsin: function (variationalData, productGrid) {
let variationalEntries = new Map(Object.entries(variationalData));
if (variationalEntries.size > 0) {
productGrid.find("div[name=productVariationDataForPlainAsin").removeClass("hidden");
let notFirst = false;
for (let [key, value] of variationalEntries) {
// Handles manual added variables under TwisterVariationParser.java
let delimiter = ":";
if (key === "order" || key === "color_metadata") {
continue;
}
if (key === "color_name") {
key = 'Color:';
delimiter = "";
}
if (key === "size_name") {
key = 'Size:';
delimiter = "";
}
if (notFirst) {
productGrid.find("[data-name=productVariationDataForPlainAsin]").append('
');
notFirst = true
}
}
if (notFirst) {
// variable spacing
productGrid.find("[name=variableSpacing]").removeClass("displayNone");
// adding margin to LTD
productGrid.find("div[name=limitedTimeDeal]").addClass("limitedTimeDealSpacing");
}
}
},
// private function
renderProductInfoList: function () {
let startTime = new Date().getTime();
let promotionShoppingPageResponse = this.cachedPromotionShoppingPageResponse;
let productInfoArray;
let pageId = "AD5Q0BRCP11K5";
const redundantProductInfoListContainer = document.getElementsByClassName("productInfoListContainer");
// since Amabot content is currently supported for "Carousel" view,
// this method cleans any leftover content when user switches between carousel and grid view
this.cleanupAmabotContent();
if (false && !isFilterOrSort) {
// setting productInfoArray to empty list if the response is null or undefined
productInfoArray = promotionShoppingPageResponse["viewModels"]["PRODUCT_INFO_LIST_SUS"] || [];
productInfoArray = productInfoArray.slice(0, 7);
// only hide productInfoListContainer if we have products to show in carousel
if (productInfoArray.length !== 0) {
redundantProductInfoListContainer[0].classList.add("hidden");
}
this.mapProductCategoryToCarousel("productInfoCarousel", productInfoArray);
this.hideUnusedCarousels("productInfoCarousel", productInfoArray);
$("#productInfoListCarouselContainer").removeClass("hidden");
$("#productGridTemplate [name=productGrid]").removeClass("productGrid");
$("#productGridTemplate [name=productGrid]").addClass("productGridForSUS");
// For SUS workflow, if the productInfoMap is empty then we need to call the addProductToPage method to render the error page.
if (productInfoArray.length === 0)
{
isServerResponseEmpty = true;
// This method is called to render the error page.
this.addProductToPage("", [], startTime, false)
}
for (let productInfoForSUS of productInfoArray) {
let carosuelRenderStartTime = new Date().getTime();
// Store reftagSuffix for a productCategory
productCategoryToReftagSuffix.set(productInfoForSUS.productCategory, productInfoForSUS.reftagSuffix);
$("#productInfoList").addClass("hidden");
let carouselName = refinementToCarouselMap.get(productInfoForSUS["productCategory"]);
// only rendering the visible products on the page first.
let visibleProductInfos = productInfoForSUS["productInfos"].slice(0, SUS_VISIBLE_PRODUCTS_COUNT);
this.addProductToPage(productInfoForSUS["productCategory"], visibleProductInfos, startTime, false);
this.hideEmptyResponseCarousel(carouselName, productInfoForSUS["productInfos"]);
carouselRenderTimes.push(new Date().getTime() - carosuelRenderStartTime);
}
this.initializeCarousels(productInfoArray);
this.hideEmptyCarouselCards(productInfoArray);
// This call is Carousel view specific.
if (false) {
pageId = SUSPageId;
}
this.renderAmabotContent(pageId);
const carouselElement = document.getElementsByClassName("a-carousel");
for (let i = 0; i < carouselElement.length; i++) {
carouselElement[i].classList.add("displayFlex");
}
const carouselCardElement = document.getElementsByClassName("a-carousel-card");
for (let i = 0; i < carouselCardElement.length; i++) {
carouselCardElement[i].classList.add("displayFlex");
}
} else {
// show productInfoListContainer
redundantProductInfoListContainer[0].classList.remove("hidden");
$("#productInfoListCarouselContainer").addClass("hidden");
$("#productInfoList").removeClass("hidden");
$("#productGridTemplate [name=productGrid]").addClass("productGrid");
let productInfoList = promotionShoppingPageResponse["viewModels"]["PRODUCT_INFO_LIST"];
if (!productInfoList || productInfoList.length === 0) {
isServerResponseEmpty = true;
}
this.addProductToPage("", productInfoList, startTime, false);
}
this.hideSpin();
pageRenderEndTime = new Date().getTime();
// rendering rest of the products which are not currently visible on the page.
if (false && !isFilterOrSort) {
for (let productInfo of productInfoArray) {
if (productInfo["productInfos"] && productInfo["productInfos"].length >= SUS_VISIBLE_PRODUCTS_COUNT) {
let restOfProductInfos = productInfo["productInfos"].slice(SUS_VISIBLE_PRODUCTS_COUNT);
this.addProductToPage(productInfo["productCategory"], restOfProductInfos, startTime, true);
}
}
}
},
// This method removes any previously loaded amabot content
cleanupAmabotContent: function () {
let slots = amabotSlots.split(",");
for (const slot of slots) {
$("#" + slot).empty();
}
},
// This method renders the content received from amabotContent controller to its specific slot.
renderAmabotContent: function (pageId) {
let amabotRequest = {
"pageId": pageId,
"slots": amabotSlots
};
$.ajax({
type: "GET",
url: "/promotion/psp/amabotContent",
data: amabotRequest,
dataType: "json",
contentType: "application/x-www-form-urlencoded; charset=UTF-8",
success: function (slotToContent) {
if (slotToContent) {
let slots = amabotSlots.split(",");
for (const slot of slots) {
let slotElement = $("#" + slot);
let content = slotToContent[slot];
if (slotElement && content) {
slotElement.append(content);
}
}
}
},
error: function (e) {
console.log(e.status);
console.log(e.responseText);
}
});
},
// capture stock up and save carousel and base page latency metrics
recordSUSLatencyMetrics: function (startTime, endTime, metricsPrefix) {
if ((false || false) && !isFilterOrSort && !isServerResponseEmpty) {
let metricsName = metricsPrefix;
metricsName += false ? "_carousel" : "_base";
metricsName += false ? "_mobile" : "_desktop";
metricsName += false ? "_cp" : "";
let data = {
"startTime" : startTime,
"endTime" : endTime,
"metricsName": metricsName
}
commonModule.clientSideMetrics(data);
}
},
// capture render times for products that are visible on the page
recordVisibleProductsRenderTime: function (startTime, endTime) {
if ((false || false) && !isFilterOrSort && !isServerResponseEmpty) {
let metricsName = false ? "SUS_Carousel_Page" : "SUS_Base_Page";
metricsName += false ? "_cp" : "";
let data = {
"startTime" : startTime,
"endTime" : endTime,
"metricsName": metricsName
}
commonModule.clientSideMetrics(data);
}
},
initializeCarousels: function (productInfoArray) {
P.when("a-carousel-framework", "ready").execute("get-the-carousel", function (framework) {
for (let i = 0; i < productInfoArray.length; i++) {
let carouselElement = document.getElementById(refinementToCarouselMap.get(productInfoArray[i]["productCategory"]));
let carousel = framework.getCarousel(carouselElement);
carousel.setAttr("set_size", productInfoArray[i]["productInfos"].length);
$("#productInfoCarousel_" + i).attr("data-a-carousel-options",
"{\"name\":\"productInfoCarousel_" + i + "\",\"set_size\":\""
+ productInfoArray[i]["productInfos"].length + "\",\"auto_adjust_height\":\"true\"}");
}
});
},
hideEmptyCarouselCards: function (productInfoArray) {
for (let i = 0; i < productInfoArray.length; i++) {
let productInfoLength = productInfoArray[i]["productInfos"].length;
let cards = $("#productInfoCarousel_" + i).children().children().children();
cards = cards.children(".a-carousel-viewport").children().children();
cards.slice(productInfoLength).empty();
}
},
hideEmptyResponseCarousel: function(carouselName, productInfo) {
if (productInfo.length == 0) {
$("#" + carouselName).addClass("hidden");
}
},
addProductToPage: function (productCategory, productInfoList, startTime, deferredRendering) {
// If pass-in promotionShoppingPageResponse doesn't exist, render from cached promotionShoppingPageResponse
let promotionShoppingPageResponse = this.cachedPromotionShoppingPageResponse;
if (!deferredRendering) {
this.showSpin();
}
// show error message or render product list
// Only looking at 100% valid productInfo to avoid showing empty page instead of the correct error page
let filteredProductInfoList = productInfoList.filter(productInfo => productInfo["failedGroupingId"] === false);
if (commonModule.isEmpty(promotionShoppingPageResponse) || commonModule.isEmpty(filteredProductInfoList)) {
$("#showMoreBtnContainer").addClass("hidden");
let endTime = new Date().getTime();
if (commonModule.isEmpty(queryParameter["sortId"]) || queryParameter["sortId"] == [] || queryParameter["sortId"].length == 0) {
// No selection
if (commonModule.isEmpty(queryParameter["productCategory"])
&& commonModule.isEmpty(queryParameter["searchKeyword"])
&& (commonModule.isEmpty(queryParameter["avgCustomerReview"]) || queryParameter["avgCustomerReview"] == "0")
&& ((commonModule.isEmpty(queryParameter["priceTierMin"]) || queryParameter["priceTierMin"] == "")
&& (commonModule.isEmpty(queryParameter["priceTierMax"]) || queryParameter["priceTierMax"] == ""))
&& (commonModule.isEmpty(queryParameter["bestSeller"]) || queryParameter["bestSeller"] == "0")
&& (commonModule.isEmpty(queryParameter["sortBy"]) || queryParameter["sortBy"] == "1")) {
$("#errorMessageWithSelection").addClass("hidden");
$("#errorMessageWithSuppressedProducts").addClass("hidden");
$("#errorMessageWithoutSelection").removeClass("hidden");
let data = {
"startTime": startTime,
"endTime": endTime,
"promotionId": "AD5Q0BRCP11K5",
"metricsName" : "productInfoListErrorPage"
}
commonModule.clientSideMetrics(data);
} else {
let data = {
"startTime": startTime,
"endTime": endTime,
"promotionId": "AD5Q0BRCP11K5",
"metricsName" : "productInfoListErrorPageRefinements"
}
commonModule.clientSideMetrics(data);
$("#errorMessageWithoutSelection").addClass("hidden");
$("#errorMessageWithSuppressedProducts").addClass("hidden");
$("#errorMessageWithSelection").removeClass("hidden");
}
}
}
//Check first ASIN to see if it suppressed do to legal requirements in JP and show error page
else if (this.isProductRestricted(productInfoList)) {
$("#showMoreBtnContainer").addClass("hidden");
$("#errorMessageWithoutSelection").addClass("hidden");
$("#errorMessageWithSelection").addClass("hidden");
$("#errorMessageWithSuppressedProducts").removeClass("hidden");
$("#couponClippingContainer").addClass("hidden");
}
// No errors found render product asin grid
else {
$("#errorMessageWithoutSelection").addClass("hidden");
$("#errorMessageWithSelection").addClass("hidden");
$("#errorMessageWithSuppressedProducts").addClass("hidden");
if (!false || isFilterOrSort) {
$("#showMoreBtnContainer").removeClass("hidden");
}
let ldMerchantToAsins = {};
let variationalAsinProductGridList = [];
let variationalAsinBaseProductInfos = [];
let currentRenderedProductGridNum = 0;
for (let i = 0; i < productInfoList.length; ++i) {
if (productInfoList[i] != undefined && !productInfoList[i]["failedGroupingId"]) {
// 1. Create the product cell by cloning the grid template, clone the product grid template from productInfoList.jsp#productGridTemplate[name=productGrid]
let cloneStartTime = new Date().getTime();
let productGrid = $("#productGridTemplate [name=productGrid]").clone();
totalCloneTime += (new Date().getTime() - cloneStartTime);
let productInfoPosInCarousel = deferredRendering ? i + SUS_VISIBLE_PRODUCTS_COUNT : i;
if (productInfoList[i]["defaultGroupingId"] != undefined) {
if (true === productInfoList[i]["variationalAsin"]) {
if (false) {
if (currentRenderedProductGridNum < prioritizedProductNumber) {
this.renderAsVariationalAsin(productInfoList[i], productGrid, this.getDpLink(productInfoList, i, productCategory), ldMerchantToAsins, productCategory)
++currentRenderedProductGridNum;
} else {
variationalAsinProductGridList.push(productGrid);
variationalAsinBaseProductInfos.push(productInfoList[i]);
this.renderVariationalAsinFaceOutTemplate(productInfoList[i], productGrid, this.getDpLink(productInfoList, i, productCategory), ldMerchantToAsins, productCategory)
}
} else {
this.renderAsVariationalAsin(productInfoList[i], productGrid, this.getDpLink(productInfoList, i, productCategory), ldMerchantToAsins, productCategory);
}
// 3. Append the product cell to the product list
// We still need productInfoList since search and sort still required us to revert back to the productInfoList UI.
$("#productInfoList").append(productGrid);
if (false && !isFilterOrSort) {
// Append the product cell to the product carousel
this.setCarouselElement(refinementToCarouselMap.get(productCategory), productGrid, productInfoPosInCarousel);
}
} else {
this.renderAsinFaceOut(productInfoList[i], productGrid, this.getDpLink(productInfoList, i, productCategory), ldMerchantToAsins, productCategory)
++currentRenderedProductGridNum;
// 3. Append the product cell to the product list
// We still need productInfoList since search and sort still required us to revert back to the productInfoList UI.
$("#productInfoList").append(productGrid);
if (false && !isFilterOrSort) {
// Append the product cell to the product carousel
this.setCarouselElement(refinementToCarouselMap.get(productCategory), productGrid, productInfoPosInCarousel);
}
}
} else {
this.renderAsinFaceOut(productInfoList[i], productGrid, this.getDpLink(productInfoList, i, productCategory), ldMerchantToAsins, productCategory);
++currentRenderedProductGridNum;
// 3. Append the product cell to the product list
// We still need productInfoList since search and sort still required us to revert back to the productInfoList UI.
$("#productInfoList").append(productGrid);
if (false && !isFilterOrSort) {
// Append the product cell to the product carousel
this.setCarouselElement(refinementToCarouselMap.get(productCategory), productGrid, productInfoPosInCarousel);
}
}
} else if (productInfoList[i] != undefined && productInfoList[i]["failedGroupingId"]) {
let that = this;
let productInfoPosInCarousel = deferredRendering ? i + SUS_VISIBLE_PRODUCTS_COUNT : i;
let currentSortId = queryParameter["sortId"];
queryParameter["defaultGroupingIdForColorAndSize"] = productInfoList[i]["defaultGroupingIdForColorAndSize"];
queryParameter["recordedGroupingIds"] = [];
// reset sortId to original failed one
queryParameter["sortId"] = productInfoList[i]["sortId"];
$.ajax({
type: "GET",
url: "/promotion/psp/productInfoListForVariationalAsin",
data: $.param(queryParameter, true),
dataType: "json",
contentType: "application/x-www-form-urlencoded; charset=UTF-8",
success: function (productInfos) {
let backupProductGrid = $("#productGridTemplate [name=productGrid]").clone();
if (productInfos.length === 1) {
that.renderVariationalAsinFaceOutTemplate(productInfos[0], backupProductGrid, that.getDpLinkForProductInfo(productInfos[0], productCategory), ldMerchantToAsins, productCategory);
that.renderVariationalToPlainAsin(productInfos[0], backupProductGrid, productCategory);
$("#productInfoList").append(backupProductGrid);
if (false && !isFilterOrSort) {
// Append the product cell to the product carousel
that.setCarouselElement(refinementToCarouselMap.get(productCategory), backupProductGrid, productInfoPosInCarousel);
}
} else if (productInfos.length > 1) {
that.renderVariationalAsinFaceOutTemplate(productInfos[0], backupProductGrid, that.getDpLinkForProductInfo(productInfos[0], productCategory), ldMerchantToAsins, productCategory);
that.renderVariationalDropDown(productInfos[0], backupProductGrid, productInfos, ldMerchantToAsins, productCategory);
$("#productInfoList").append(backupProductGrid);
if (false && !isFilterOrSort) {
// Append the product cell to the product carousel
that.setCarouselElement(refinementToCarouselMap.get(productCategory), backupProductGrid, productInfoPosInCarousel);
}
}
},
error: function (e) {
console.log(e.status);
console.log(e.responseText);
}
})
queryParameter["sortId"] = currentSortId;
queryParameter["recordedGroupingIds"] = that.cachedRecordedGroupingIds;
queryParameter["defaultGroupingIdForColorAndSize"] = "";
}
}
// Render Variational Selectors in Batch
this.renderVariationalSelectorsInBatch(queryParameter, variationalAsinBaseProductInfos, variationalAsinProductGridList, ldMerchantToAsins);
// Lightning Deal claim percentage update
this.continuousUpdateClaim(ldMerchantToAsins);
// Hide the Show More button if product list is null or the ES data set has been exhausted
if (commonModule.isEmpty(promotionShoppingPageResponse)
|| promotionShoppingPageResponse["reachBottom"]
|| queryParameter["sortId"] == null) {
$("#showMoreBtnContainer").addClass("hidden");
}
}
},
renderVariationalSelectorsInBatch: function (queryParameter, variationalAsinBaseProductInfos, variationalAsinProductGridList, ldMerchantToAsins) {
let that = this;
let defaultGroupingIdsForBatch = [];
for (let i = 0; i < variationalAsinBaseProductInfos.length; ++i) {
if (variationalAsinBaseProductInfos[i] !== undefined) {
if (!variationalAsinBaseProductInfos[i]["failedGroupingId"] && variationalAsinBaseProductInfos[i]["variationalAsin"]) {
this.cachedRecordedGroupingIds.push(variationalAsinBaseProductInfos[i]["defaultGroupingIdForColorAndSize"]);
defaultGroupingIdsForBatch.push(variationalAsinBaseProductInfos[i]["defaultGroupingIdForColorAndSize"])
}
}
}
if (variationalAsinBaseProductInfos.length === 0) {
return;
}
queryParameter["defaultGroupIdsForColorAndSizeAsList"] = defaultGroupingIdsForBatch;
queryParameter["recordedGroupingIds"] = [];
let productInfoListForVariationalAsinInBatchParam = {
"promotionId": queryParameter["promotionId"],
"avgCustomerReview": queryParameter["avgCustomerReview"],
"priceTierMin" : queryParameter["priceTierMin"],
"priceTierMax" : queryParameter["priceTierMax"],
"bestSeller": queryParameter["bestSeller"],
"sortBy": queryParameter["sortBy"],
"productCategory": queryParameter["productCategory"],
"searchKeyword": queryParameter["searchKeyword"],
"isSNSOnly": queryParameter["isSNSOnly"],
"defaultGroupIdsForColorAndSizeAsList": JSON.stringify(queryParameter["defaultGroupIdsForColorAndSizeAsList"]),
"subProductCategory": queryParameter["subProductCategory"],
"applicabilityIndex": queryParameter["applicabilityIndex"],
"isPreview": "false",
"anti-csrftoken-a2z": 'hJukOPLNYVNcSmmkg/VKd++3PudoNnJVpu3b7UN3BkpHAAAAAGhRQZwAAAAB'
};
$.ajax({
type: "GET",
url: "/promotion/psp/productInfoListForVariationalAsinInBatch",
data: productInfoListForVariationalAsinInBatchParam,
dataType: "json",
contentType: "application/x-www-form-urlencoded; charset=UTF-8",
success: function (productInfosBatch) {
let currentIndex = 0;
let endIndex = productInfosBatch.length;
for (let i = 0; i < defaultGroupingIdsForBatch.length; ++i) {
let defaultGroupingId = defaultGroupingIdsForBatch[i];
let baseProductInfo = variationalAsinBaseProductInfos[i];
let currentProductGrid = variationalAsinProductGridList[i];
let productInfos = [];
while (currentIndex < endIndex && productInfosBatch[currentIndex]["defaultGroupingIdForColorAndSize"] === defaultGroupingId) {
productInfos.push(productInfosBatch[currentIndex]);
++currentIndex;
}
let variationalAsinDataPopulatedBack = false;
if (productInfos.length === 0) {
// Not expected to happen, gracefully handing.
that.renderVariationalToPlainAsin(baseProductInfo, currentProductGrid, productCategory);
continue;
}
if (productInfos.length === 1) {
if (commonModule.isNotEmpty(productInfos[0]["variationData"]) && Object.entries(productInfos[0]["variationData"]).length > 0) {
// Based on distinct indexed offer requirement from loadProductInfoListForVariationalAsin, if the variational asin
// is not the only child in the promotion, the returned productInfos length is >= 2.
// Note sortId would only progress when processing plain asin, there by expect when productInfos.length == 1,
// it can only be the only child in the promotion.
baseProductInfo["variationData"] = productInfos[0]["variationData"];
that.renderVariationalToPlainAsin(baseProductInfo, currentProductGrid, productCategory);
} else {
// Not expected to happen, gracefully handing.
that.renderVariationalToPlainAsin(baseProductInfo, currentProductGrid, productCategory);
}
} else {
// Populating VariationalData from SubWorkflow back to MajorWorkflow
for (let productInfoEntry of productInfos) {
if (baseProductInfo["asin"] === productInfoEntry["asin"]) {
baseProductInfo["variationData"] = productInfoEntry["variationData"];
variationalAsinDataPopulatedBack = true;
break;
}
}
if (variationalAsinDataPopulatedBack) {
that.renderVariationalDropDown(baseProductInfo, currentProductGrid, productInfos, ldMerchantToAsins, productCategory);
} else {
that.renderVariationalToPlainAsin(baseProductInfo, currentProductGrid, productCategory);
let newProductGrid = $("#productGridTemplate [name=productGrid]").clone();
that.renderVariationalAsinFaceOutTemplate(productInfos[0], newProductGrid, that.getDpLink(productInfos, 0, productCategory), ldMerchantToAsins, productCategory);
that.renderVariationalDropDown(productInfos[0], newProductGrid, productInfos, ldMerchantToAsins, productCategory);
// 3. Append the product cell to the product list
$("#productInfoList").append(currentProductGrid);
$("#productInfoList").append(newProductGrid);
}
}
}
},
error: function () {
for (let i = 0; i < variationalAsinBaseProductInfos.length; ++i) {
that.renderVariationalToPlainAsin(variationalAsinBaseProductInfos[i], variationalAsinProductGridList[i], productCategory);
}
}
})
queryParameter["recordedGroupingIds"] = that.cachedRecordedGroupingIds;
queryParameter["defaultGroupIdsForColorAndSizeAsList"] = "";
},
setCarouselElement: function (name, productGrid, i) {
P.when("a-carousel-framework", "ready").execute("get-the-carousel", function (framework) {
// This carousel actually does have an id, so lets just use that since the lookup is faster
carousel = framework.getCarousel(document.getElementById(name));
// Since carousel doesn't allow adding or removing any items after the initialization
// we created 20 placeholers item, and use the getAttr("fetchedItems") API call to
// fetch all the items into a list, then splice the list to replace an item with one
// single ASIN faceout, then use setAttr to make the change onto the carousel.
let fetchedItems = carousel.getAttr("fetchedItems");
fetchedItems.splice(i, 1, productGrid[0]);
carousel.setAttr("fetchedItems", fetchedItems);
if (true) {
let addToCartBtnBox = productGrid.find("div[name=addToCartBtnBox]");
addToCartBtnBox.find("span[name= addToCartBtn]").find(".addToCartBtn").removeClass("addToCartBtn");
addToCartBtnBox.find("span[name= addVariationalASINToCartBtn]").find(".addToCartBtn").removeClass("addToCartBtn");
}
});
},
mapProductCategoryToCarousel(carouselName, productInfoArray) {
for (let i = 0; i < productInfoArray.length; i++) {
refinementToCarouselMap.set(productInfoArray[i]["productCategory"], carouselName + "_" + i);
//TODO: Need to implement internationalization for See all
// See All link must be present only for product categories. product categories starts after Recommendations and Buy it again.
if (!productInfoArray[i]["recommendationWidget"]) {
let productCategory = productInfoArray[i]["productCategory"];
let totalResults = productInfoArray[i]["totalResults"];
let seeAllText = this.getSeeAllText(totalResults);
let carouselHeading = $("#" + carouselName + "_" + i).children("#aCarouselHeading").children().eq(0);
carouselHeading.children().html(''+ productCategory + ''+seeAllText+'');
carouselHeading.addClass("a-span16");
carouselHeading.removeClass("a-span8");
} else {
$("#" + carouselName + "_" + i).children("#aCarouselHeading").children().eq(0).children()
.html(''+ productInfoArray[i]["productCategory"] + '');
}
}
},
// returns a string like "See all (N+ items)", where N is either 1000, 500, 200, 100, 30
getSeeAllText: function (count) {
let bucket = 0;
let seeAll = "See All";
let items = "items";
// bucketing logic is similar to https://code.amazon.com/packages/PromotionsDiscoveryHorizonteService/blobs/0b1c7522bb02a187e3ceec69746085a51ad26534/--/src/com/amazon/pdhs/psp/service/impl/GetRefinementServiceImpl.java#L230-L244
// 10% buffer due to late check.
if (count > 1100) {
bucket = 900;
} else if (count > 550) {
bucket = 400;
} else if (count > 220) {
bucket = 100;
} else if (count > 110) {
bucket = 50;
} else if (count > 33) {
bucket = 20;
} else {
return seeAll;
}
return seeAll + " (" + bucket + "+ " + items + ")";
},
// public function
ensureHowToClaimExpanderExpanded: function () {
// Sometimes the AUI expander may not fully always expand, manually ensure it to be fully expanded
$('#HowToClaimExpander').height("");
},
loadRenderRefinement: function () {
let that = this;
queryParameter["recordedGroupingIds"] = [];
let refinementParam = {
"promotionId": queryParameter["promotionId"],
"avgCustomerReview": queryParameter["avgCustomerReview"],
"priceTierMin" : queryParameter["priceTierMin"],
"priceTierMax" : queryParameter["priceTierMax"],
"bestSeller": queryParameter["bestSeller"],
"sortId": JSON.stringify(queryParameter["sortId"]),
"applicabilityIndex": queryParameter["applicabilityIndex"],
"productCategory": queryParameter["productCategory"],
"redirectAsin": queryParameter["redirectAsin"],
"redirectMerchantId": queryParameter["redirectMerchantId"],
"isSUSOnly": queryParameter["isSUSOnly"],
"isCarouselPilot": queryParameter["isCarouselPilot"],
"searchKeyword": queryParameter["searchKeyword"],
"subProductCategory": queryParameter["subProductCategory"],
"selectedBrands": JSON.stringify(queryParameter["selectedBrands"])
};
$.ajax({
type: "GET",
url: "/promotion/psp/refinement" + reftag,
data: refinementParam,
contentType: "application/x-www-form-urlencoded; charset=UTF-8",
success: function (promotionShoppingPageResponse) {
if (commonModule.isNotEmpty(promotionShoppingPageResponse)) {
if (false) {
appendDebugJSON("refinement", promotionShoppingPageResponse["debugJson"]);
}
that.renderRefinement(promotionShoppingPageResponse["viewModels"]["REFINEMENT"]);
}
},
error: function (e) {
console.log(e.status);
console.log(e.responseText);
}
});
},
// private function
renderRefinement: function (refinement) {
// Department
// Set product category of redirect asin if present
if (commonModule.isNotEmpty(refinement["preSelectedProductCategory"])) {
queryParameter[this.queryParameterKeys.productCategory] = refinement["preSelectedProductCategory"];
}
// Check PDA response to know if it is BXGY promotion, for non BXGY promotions, this field would be ""
if (queryParameter[this.queryParameterKeys.applicabilityIndex] === "0" || queryParameter[this.queryParameterKeys.applicabilityIndex] === "1") {
$("#view").removeClass("hidden");
if (!false) {
let viewPhoneDesktop = $("#viewList");
$("#department").addClass("paddingTop16");
viewPhoneDesktop.find("[type=radio]").prop("checked", false);
viewPhoneDesktop.find("[type=radio]").eq([queryParameter[this.queryParameterKeys.applicabilityIndex]]).prop("checked", true);
}
}
if (queryParameter[this.queryParameterKeys.applicabilityIndex] === "0")
{
$("#keywordSearchInputText").attr("placeholder", "Search qualifying items")
}
if (queryParameter[this.queryParameterKeys.applicabilityIndex] === "1")
{
$("#keywordSearchInputText").attr("placeholder", "Search benefit items")
}
let subCategoryDisplayDesktopNumber = 5;
let availableProductCategories = refinement["availableProductCategories"];
let availableSubCategories = new Map();
if (commonModule.isNotEmpty(refinement["subProductCategories"])) {
availableSubCategories = new Map(Object.entries(refinement["subProductCategories"]));
}
if (commonModule.isEmpty(availableProductCategories) || availableProductCategories.length == 0) {
queryParameter[this.queryParameterKeys.productCategory] = "";
queryParameter[this.queryParameterKeys.subProductCategory] = "";
}
$("#departmentList").empty();
$("#departmentListPhone").empty();
$("#anyDepartment").addClass("hidden");
for (let i in availableProductCategories) {
if ($("#departmentList")) {
let departmentListItemClone = $("#departmentListItemTemplate li").clone();
let currentCategoryItem = departmentListItemClone.find("[data-name=departmentListItemText]");
currentCategoryItem.text(availableProductCategories[i]);
currentCategoryItem.attr("data-value", availableProductCategories[i]);
if (this.getValue(this.queryParameterKeys.productCategory) == availableProductCategories[i] && commonModule.isNotEmpty(availableProductCategories[i])) {
commonModule.focus($("[data-name=departmentListItemText]"), $(currentCategoryItem));
$("#anyDepartment").removeClass("hidden");
}
$("#departmentList").append(departmentListItemClone);
if (commonModule.isNotEmpty(availableSubCategories) && availableSubCategories.size > 0 &&
commonModule.isNotEmpty(availableSubCategories.get(availableProductCategories[i])) && availableSubCategories.get(availableProductCategories[i]).length > 0) {
$("#departmentList li").last().append("");
$("#departmentList li").last().find("[name=subCategoryList]").append($("#departmentSubCategoryListTemplate").children().clone());
for (let subCategoryIndex in availableSubCategories.get(availableProductCategories[i])) {
{
let subCategoryItemClone = $("#departmentSubCategoryItemTemplate li").clone();
let currentSubCategoryItem = subCategoryItemClone.find("[data-name=departmentListSubCategoryItemText]");
currentSubCategoryItem.text(availableSubCategories.get(availableProductCategories[i])[subCategoryIndex]);
currentSubCategoryItem.attr("data-value", availableSubCategories.get(availableProductCategories[i])[subCategoryIndex]);
if (this.getValue(this.queryParameterKeys.productCategory) === availableProductCategories[i]
&& this.getValue(this.queryParameterKeys.subProductCategory) === availableSubCategories.get(availableProductCategories[i])[subCategoryIndex]) {
commonModule.focus($("[data-name=departmentListSubCategoryItemText]"), $(currentSubCategoryItem));
departmentListItemClone.find("[name=subCategoryList]").children().prepend(subCategoryItemClone);
if (subCategoryIndex == subCategoryDisplayDesktopNumber) {
departmentListItemClone.find("[name=subCategoryList] li").last().addClass("hidden");
}
} else {
if (subCategoryIndex >= subCategoryDisplayDesktopNumber) {
subCategoryItemClone.addClass("hidden");
}
departmentListItemClone.find("[name=subCategoryList]").children().append(subCategoryItemClone);
}
}
}
// rendering see more
if (availableSubCategories.get(availableProductCategories[i]).length > subCategoryDisplayDesktopNumber) {
// No need to render selectedSubCategory anymore, directly adding see more
let subCategoryItemClone = $("#departmentSubCategoryItemTemplate li").clone();
let currentSubCategoryItem = subCategoryItemClone.find("[data-name=departmentListSubCategoryItemText]");
let expander = $("#itemExpanderTemplate").children().clone();
let expanderName = availableProductCategories[i].replace(/\s/g, "_");
expander.attr("data-a-expander-name", expanderName);
currentSubCategoryItem.attr("data-name", "subCategoryExpander");
currentSubCategoryItem.append(expander);
P.when('A', 'ready').execute(function(A) {
A.on('a:expander:' + expanderName + ':toggle:expand', function(data) {
departmentListItemClone.find("[name=subCategoryList] li").removeClass("hidden");
});
A.on('a:expander:' + expanderName + ':toggle:collapse', function(data) {
let subCategories = departmentListItemClone.find("[name=subCategoryList] li");
if (subCategories.length > subCategoryDisplayDesktopNumber) {
subCategories.slice(subCategoryDisplayDesktopNumber, subCategories.length - 1).addClass("hidden");
}
});
});
departmentListItemClone.find("[name=subCategoryList]").children().append(subCategoryItemClone);
}
}
}
// Phone
if ($("#departmentListPhone")) {
let departmentBoxPhoneClone = $("#departmentBoxTemplate > div").clone();
departmentBoxPhoneClone.text(availableProductCategories[i]);
departmentBoxPhoneClone.attr("aria-label", availableProductCategories[i]);
departmentBoxPhoneClone.attr("data-key", "productCategory");
departmentBoxPhoneClone.attr("data-value", availableProductCategories[i]);
departmentBoxPhoneClone.attr("data-target", "departmentBox");
if (this.getValue(this.queryParameterKeys.productCategory) == availableProductCategories[i] && commonModule.isNotEmpty(availableProductCategories[i])) {
departmentBoxPhoneClone.addClass("menuButtonFocus");
// weblab check for subCategory
if (commonModule.isNotEmpty(availableSubCategories.get(availableProductCategories[i])) && availableSubCategories.get(availableProductCategories[i]).length > 0) {
$("#subCategoryListPhone").removeClass("hidden");
// render selected product category
// clear previous content
$("#categoryTraversalTree").removeClass("hidden").children().not("#AnyProductCategory").empty();
$("#categoryTraversalTree").find(".horizontalMargin5").remove();
// render new content
$("#categoryTraversalTree").append($("#categoryTraversalTreeNodeTemplate > span").clone());
let productCategoryTreeNode = $("#middleProductCategory").text(this.getValue(this.queryParameterKeys.productCategory));
productCategoryTreeNode.attr("data-value1", this.getValue(this.queryParameterKeys.productCategory));
productCategoryTreeNode.attr("data-value2", "");
productCategoryTreeNode.addClass("a-color-base");
$("#categoryTraversalTree").append(productCategoryTreeNode);
// if have selected subProductCategory
if (commonModule.isNotEmpty(this.getValue(this.queryParameterKeys.subProductCategory))) {
// doesn't bind leaf node with click to reset category related refinements
$("#categoryTraversalTree").append($("#categoryTraversalTreeNodeTemplate > span").clone());
let subProductCategoryTreeNode = $("#leafProductCategory").text(this.getValue(this.queryParameterKeys.subProductCategory));
subProductCategoryTreeNode.attr("data-value1", this.getValue(this.queryParameterKeys.productCategory));
subProductCategoryTreeNode.attr("data-value2", this.getValue(this.queryParameterKeys.subProductCategory));
$("#middleProductCategory").removeClass("a-color-base");
subProductCategoryTreeNode.addClass("a-color-base");
$("#categoryTraversalTree").append(subProductCategoryTreeNode);
// render selected subCategory only
let subCategoryBoxPhoneClone = $("#subCategoryBoxTemplate > div").clone();
subCategoryBoxPhoneClone.text(this.getValue(this.queryParameterKeys.subProductCategory));
subCategoryBoxPhoneClone.attr("aria-label", this.getValue(this.queryParameterKeys.subProductCategory));
subCategoryBoxPhoneClone.attr("data-key", "subProductCategory");
subCategoryBoxPhoneClone.attr("data-value", this.getValue(this.queryParameterKeys.subProductCategory));
subCategoryBoxPhoneClone.attr("data-id", this.getValue(this.queryParameterKeys.subProductCategory).replace("'", "'"));
subCategoryBoxPhoneClone.attr("data-target", "departmentBox");
subCategoryBoxPhoneClone.addClass("menuButtonFocus");
$("#subCategoryListPhone").find(".subCategoryBoxNode").remove();
$("#subCategoryListPhone").append(subCategoryBoxPhoneClone);
} else {
$("#subCategoryListPhone").find(".subCategoryBoxNode").remove();
// since no selected subCategory, displaying all the subCategories available
for (let subCategoryIndex in availableSubCategories.get(availableProductCategories[i])) {
let subCategoryBoxPhoneClone = $("#subCategoryBoxTemplate > div").clone();
subCategoryBoxPhoneClone.text(availableSubCategories.get(availableProductCategories[i])[subCategoryIndex]);
subCategoryBoxPhoneClone.attr("aria-label", availableSubCategories.get(availableProductCategories[i])[subCategoryIndex]);
subCategoryBoxPhoneClone.attr("data-id", availableSubCategories.get(availableProductCategories[i])[subCategoryIndex].replace("'", "'"));
subCategoryBoxPhoneClone.attr("data-key", "subProductCategory");
subCategoryBoxPhoneClone.attr("data-value", availableSubCategories.get(availableProductCategories[i])[subCategoryIndex]);
subCategoryBoxPhoneClone.attr("data-target", "departmentBox");
$("#subCategoryListPhone").append(subCategoryBoxPhoneClone);
}
}
$("#departmentListPhone").addClass("hidden");
}
} else {
$("#subCategoryListPhone").addClass("hidden");
$("#departmentListPhone").removeClass("hidden");
}
$("#departmentListPhone").append(departmentBoxPhoneClone);
// if on first page load with category and filterPanel does not contain a category menuButton yet, then add button
if (this.getValue(this.queryParameterKeys.productCategory) == availableProductCategories[i] && commonModule.isNotEmpty(availableProductCategories[i])) {
let filterPanelMenuButton = $("#departmentBox > .menuButton[data-key='productCategory'][data-value='" + queryParameter[this.queryParameterKeys.productCategory] + "']");
if(filterPanelMenuButton.length == 0) {
$("#departmentBox").append(departmentBoxPhoneClone.clone());
}
}
}
}
// Brands
$("#brandList").empty();
$("#brands").addClass("hidden");
$("#brandListPhone").find("[name=menuButton]").remove();
$("#brandListPhone").find("[name=subBrandList]").addClass("hidden");
let brandsDisplayDesktopNumber = 7;
let brandsMobileBrandsNoAlphabeticalSoltsNumber = 6;
let brandsMobileBrandsNoSoltsNumber = 10;
let availableBrands = refinement["availableBrands"];
let alphabeticalCounter = 0;
if (commonModule.isNotEmpty(availableBrands) && availableBrands.length > 0) {
$("#brands").removeClass("hidden");
if ($("#brandListPhone") && availableBrands.length > brandsMobileBrandsNoSoltsNumber) {
availableBrands.sort((a, b) => a.localeCompare(b));
}
if ($("#brandListPhone") && this.getValue(this.queryParameterKeys.selectedBrands).length == 0) {
$("#brandsBox").empty();
}
for (let i in availableBrands) {
// Desktop & Tablet
if ($("#brandList")) {
let brandListItemClone = $("#brandListItemTemplate li").clone();
let currentBrandCheckText = brandListItemClone.find("[data-name=brandListItemCheckText]");
let currentBrandCheckBox = brandListItemClone.find("[data-name=brandListItemCheckBox]");
currentBrandCheckText.text(availableBrands[i]);
currentBrandCheckText.attr("data-value", availableBrands[i]);
currentBrandCheckBox.attr("data-value", availableBrands[i]);
if (this.getValue(this.queryParameterKeys.selectedBrands).includes(availableBrands[i]) && commonModule.isNotEmpty(availableBrands[i])) {
$(currentBrandCheckText).addClass("a-text-bold");
brandListItemClone.find("[name=brandsCheckbox]").prop("checked", true);
$("#brandList").prepend(brandListItemClone);
if (i == brandsDisplayDesktopNumber) {
$("#brandList").last().addClass("hidden");
}
} else {
if (i >= brandsDisplayDesktopNumber) {
brandListItemClone.addClass("hidden");
}
$("#brandList").append(brandListItemClone);
}
}
// Mobile
if ($("#brandListPhone")) {
let brandBoxPhoneClone = $("#brandBoxTemplate > div").clone();
brandBoxPhoneClone.text(availableBrands[i]);
brandBoxPhoneClone.attr("aria-label", availableBrands[i]);
brandBoxPhoneClone.attr("data-key", "selectedBrands");
brandBoxPhoneClone.attr("data-value", availableBrands[i]);
brandBoxPhoneClone.attr("data-id", availableBrands[i].replace("'", "'"));
brandBoxPhoneClone.attr("data-target", "brandsBox");
if (this.getValue(this.queryParameterKeys.selectedBrands).includes(availableBrands[i]) && commonModule.isNotEmpty(availableBrands[i])) {
brandBoxPhoneClone.addClass("menuButtonFocus");
}
if (availableBrands.length <= brandsMobileBrandsNoSoltsNumber) {
$("#brandListPhone").append(brandBoxPhoneClone);
} else {
let code = availableBrands[i].charCodeAt(0);
if (code == 35 || ((code > 47 && code < 58))) { // # or 0 - 9
$("#subBrandList0-#").removeClass("hidden").append(brandBoxPhoneClone);
} else if ((code > 64 && code < 71) || (code > 96 && code < 103)) { // A-F or a-f
$("#subBrandListA-F").removeClass("hidden").append(brandBoxPhoneClone);
alphabeticalCounter += 1;
} else if ((code > 70 && code < 78) || (code > 102 && code < 110)) { // G-M or g-m
$("#subBrandListG-M").removeClass("hidden").append(brandBoxPhoneClone);
alphabeticalCounter += 1;
} else if ((code > 77 && code < 91) || (code > 109 && code < 123)) { // N-Z or n-z
$("#subBrandListN-Z").removeClass("hidden").append(brandBoxPhoneClone);
alphabeticalCounter += 1;
} else { // other character
$("#subBrandListOther").removeClass("hidden").append(brandBoxPhoneClone);
$("#subBrandListOther").find("#otherSubBrandTitle").removeClass("hidden");
}
}
}
}
if (alphabeticalCounter == 0) {
if ($("#subBrandList0-#").find(".menuButton").length == 0) {
$("#subBrandListOther").find("#otherSubBrandTitle").addClass("hidden");
}
} else if (alphabeticalCounter <= brandsMobileBrandsNoAlphabeticalSoltsNumber) {
$("#subBrandListG-M").find(".displayBlock").addClass("hidden");
$("#subBrandListN-Z").find(".displayBlock").addClass("hidden");
$("#subBrandListA-F").removeClass("hidden").find(".displayBlock").removeClass("hidden").find("span").text("A-Z");
} else {
$("#subBrandListG-M").find(".displayBlock").removeClass("hidden");
$("#subBrandListN-Z").find(".displayBlock").removeClass("hidden");
$("#subBrandListA-F").removeClass("hidden").find(".displayBlock").removeClass("hidden").find("span").text("A-F");
}
// rendering see more
if ($("#brandList")) {
if (availableBrands.length > brandsDisplayDesktopNumber) {
// No need to render selectedSubCategory anymore, directly adding see more
let brandListItemClone = $("#brandListItemTemplate li").clone();
let currentBrandCheckText = brandListItemClone.find("[data-name=brandListItemCheckText]");
let currentBrandCheckBox = brandListItemClone.find("[data-name=brandListItemCheckBox]");
let expander = $("#itemExpanderTemplate").children().clone();
let expanderName = "brandListExpander";
currentBrandCheckBox.addClass("hidden");
expander.attr("data-a-expander-name", expanderName);
currentBrandCheckText.attr("data-name", "brandsExpander");
currentBrandCheckText.append(expander);
P.when('A', 'ready').execute(function (A) {
A.on('a:expander:' + expanderName + ':toggle:expand', function (data) {
$("#brandList").children().removeClass("hidden");
});
A.on('a:expander:' + expanderName + ':toggle:collapse', function (data) {
let availableBrands = $("#brandList").children();
if (availableBrands.length > brandsDisplayDesktopNumber) {
availableBrands.slice(brandsDisplayDesktopNumber, availableBrands.length - 1).addClass("hidden");
}
});
});
$("#brandList").append(brandListItemClone);
}
}
}
// Price Tiers
let that = this;
if (true) {
$("#priceTier").removeClass("hidden");
let priceTierRanges = refinement["priceTierRangeResult"];
$("#priceTierList").empty();
$("#priceTierListPhone").empty();
if ($("#priceTierListPhone")) {
if (commonModule.isEmpty(this.getValue(this.queryParameterKeys.priceTierMin)) && commonModule.isEmpty(this.getValue(this.queryParameterKeys.priceTierMax))) {
$("#priceTierBox").empty();
}
}
for (let i in priceTierRanges) {
if ($("#priceTierList")) {
let priceTierListItemClone = $("#priceTierListItemTemplate li").clone();
let currentPriceTier = priceTierListItemClone.find("[data-name=priceTierOptions]");
let currentPriceTierText = priceTierListItemClone.find("[data-name=priceTierOptionsText]");
let priceMin = priceTierRanges[i]["priceMin"];
let priceMax = priceTierRanges[i]["priceMax"];
currentPriceTier.attr("data-value", i);
currentPriceTier.attr("min-price", priceMin);
currentPriceTier.attr("max-price", priceMax);
currentPriceTier.attr("id", "priceTier" + i);
if (priceMin == "" || priceMin == 0) {
currentPriceTierText.text("Under " + priceTierRanges[i]["priceMaxCurrency"]);
} else if (priceMax == "") {
currentPriceTierText.text(priceTierRanges[i]["priceMinCurrency"] + " & Above");
} else {
currentPriceTierText.text(priceTierRanges[i]["priceMinCurrency"] + " to " + priceTierRanges[i]["priceMaxCurrency"]);
}
if (commonModule.isEmpty(this.getValue(this.queryParameterKeys.priceTierMin)) && commonModule.isEmpty(this.getValue(this.queryParameterKeys.priceTierMax))) {
currentPriceTier.removeClass("hidden");
}
if (priceTierRanges[i]["hasEmptyDocCount"] && commonModule.isEmpty(this.getValue(this.queryParameterKeys.priceTierMin)) && commonModule.isEmpty(this.getValue(this.queryParameterKeys.priceTierMax))) {
currentPriceTier.contents().unwrap();
currentPriceTierText.removeClass("a-color-base");
currentPriceTierText.addClass("a-color-disabled");
currentPriceTierText.addClass("inputCursorDisabled");
}
if (this.getValue(this.queryParameterKeys.priceTierMin) == priceTierRanges[i]["priceMin"] && this.getValue(this.queryParameterKeys.priceTierMax) == priceTierRanges[i]["priceMax"]) {
currentPriceTier.removeClass("hidden");
commonModule.focus($("[data-name=priceTierOptions]"), $(currentPriceTier));
}
currentPriceTier.click(function () {
if ($(this).attr("data-value") != "") {
that.filterOrSort2(that.queryParameterKeys.priceTierMin, $(this).attr("min-price"), that.queryParameterKeys.priceTierMax, $(this).attr("max-price"));
$("#minPriceInput").val($(this).attr("min-price"));
$("#maxPriceInput").val($(this).attr("max-price"));
}
commonModule.gotoAnchor("#toolbarGridContainer");
{
$("#priceTierClear").removeClass("hidden");
$("#priceTierList [data-name=priceTierOptions]").addClass("hidden");
$("#priceTierList .inputCursorDisabled").addClass("hidden");
commonModule.focus($("#priceTierList"), $(this));
$(this).removeClass("hidden");
}
})
$("#priceTierList").append(priceTierListItemClone);
}
// Phone
$("#priceTierPhone").removeClass("hidden");
if ($("#priceTierListPhone")) {
let priceTierBoxPhoneClone = $("#priceTierBoxTemplate > div").clone();
if (priceTierRanges[i]["priceMin"] == "" || priceTierRanges[i]["priceMin"] == 0) {
priceTierBoxPhoneClone.text("Under " + priceTierRanges[i]["priceMaxCurrency"]);
} else if (priceTierRanges[i]["priceMax"] == "") {
priceTierBoxPhoneClone.text(priceTierRanges[i]["priceMinCurrency"] + " & Above");
} else {
priceTierBoxPhoneClone.text(priceTierRanges[i]["priceMinCurrency"] + " to " + priceTierRanges[i]["priceMaxCurrency"]);
}
priceTierBoxPhoneClone.attr("data-value", i);
priceTierBoxPhoneClone.attr("min-price", priceTierRanges[i]["priceMin"]);
priceTierBoxPhoneClone.attr("max-price", priceTierRanges[i]["priceMax"]);
priceTierBoxPhoneClone.attr("data-key1", this.queryParameterKeys.priceTierMin);
priceTierBoxPhoneClone.attr("data-key2", this.queryParameterKeys.priceTierMax);
if (this.getValue(this.queryParameterKeys.priceTierMin) == priceTierRanges[i]["priceMin"] && this.getValue(this.queryParameterKeys.priceTierMax) == priceTierRanges[i]["priceMax"]) {
priceTierBoxPhoneClone.addClass("menuButtonFocus");
}
if (priceTierRanges[i]["hasEmptyDocCount"]) {
priceTierBoxPhoneClone.removeClass("menuButtonFocus");
priceTierBoxPhoneClone.addClass("menuButtonDisable");
priceTierBoxPhoneClone.children().prop('disabled', true);
}
priceTierBoxPhoneClone.click(function () {
let target = "#" + $(this).attr("data-target");
if ($(this).hasClass("menuButtonFocus")) {
$(this).removeClass("menuButtonFocus");
that.filterOrSort2($(this).attr("data-key1"), "", $(this).attr("data-key2"), "");
$(target).empty();
} else {
$(this).parent().find("[name=menuButton]").removeClass("menuButtonFocus");
$(this).addClass("menuButtonFocus");
that.filterOrSort2($(this).attr("data-key1"), $(this).attr("min-price"), $(this).attr("data-key2"), $(this).attr("max-price"));
$(target).empty();
$(target).append($(this).clone());
$(target).find("[name=menuButton]").click(function () {
let InnerTarget = "#" + $(this).attr("data-target");
if ($(this).hasClass("menuButtonFocus")) {
$(this).removeClass("menuButtonFocus");
that.filterOrSort2($(this).attr("data-key1"), "", $(this).attr("data-key2"), "");
$(InnerTarget).empty();
}
});
}
that.showClearButton();
})
$("#priceTierListPhone").append(priceTierBoxPhoneClone);
}
}
}
// Customer Review: since the count is calculated pre late check, which is not precise. We don't render the count for now
let avgCustomerReviewResults = refinement["avgCustomerReviewResults"];
if (commonModule.isNotEmpty(avgCustomerReviewResults)) {
// TODO render count for each rank;
}
let bestSellerResults = refinement["bestSellerResults"];
// Bestseller: since the count is calculated pre late check, which is not precise. We don't render the count for now
if (commonModule.isNotEmpty(bestSellerResults)
&& commonModule.isNotEmpty(bestSellerResults["TOP_SELLER"])
&& bestSellerResults["TOP_SELLER"] > 0) {
$("#bestSeller").show();
// TODO render count for bestseller;
} else {
$("#bestSeller").hide();
}
// Result found desktop
if ($("#resultsFound")) {
if (refinement["resultFound"].toString().length > 0) {
$("#resultsFound").html(refinement["resultFound"] + " - " + 'Price may vary based on selection');
} else {
$("#resultsFound").html('Price may vary based on selection');
}
}
// Result found phone
if ($("#showResults")) {
$("#showResults").html(refinement["resultFoundPhone"]);
$("#showResultsBox").attr("aria-label", refinement["resultFoundPhone"])
}
this.showClearButton();
},
//private function
redeemCoupon: function (asin, offerListingId) {
// Set for coupon clipping
let isAutoRedeem = this.shouldAutoRedeem();
if (commonModule.isNotEmpty(isAutoRedeem) && isAutoRedeem && !hasBeenAutoRedeem) {
hasBeenAutoRedeem = true;
let redeemPromotionParam = {
"promotionId": "AD5Q0BRCP11K5",
"asin": asin,
"offerListingId": offerListingId,
'anti-csrftoken-a2z': 'hH4+ox0VWVRu6uLu0E29T/R+Jb7OjOGOQp0YZKob0f2GAAAAAGhRQZwAAAAB',
'source': "clp"
};
$.ajax({
type: "POST",
url: "/promotion/redeem/",
data: redeemPromotionParam,
contentType: 'application/x-www-form-urlencoded; charset=UTF-8;',
success: function () {
isClipped = true;
$("#couponClippingConfirmationBox").removeClass("hidden");
$("#couponClippingConfirmationBox").addClass("inlineBlock");
},
error: function (e) {
}
});
}
},
// private function
startLdEndTimer: function (countDownSeconds, asin) {
if (!asinToEndsInTimeMap.has(asin)) {
// Update the count down every 1 second
setInterval(function () {
countDownSeconds--;
asinToEndsInTimeMap.set(asin, countDownSeconds);
if (countDownSeconds < 0) {
clearInterval();
asinToEndsInTimeMap.set(asin, countDownSeconds);
}
}, 1000);
}
},
//private function
displayLdEndTime: function (ldBarPercentSection, asin) {
let that = this;
let tagElement = ldBarPercentSection.find("[name=dealTimeLeft]");
// Update the count down every 1 second
let intervalId = setInterval(function () {
let countDownSeconds = asinToEndsInTimeMap.get(asin);
let hours = "0" + Math.floor((countDownSeconds % (60 * 60 * 24)) / (60 * 60));
let minutes = "0" + Math.floor((countDownSeconds % (60 * 60)) / (60));
let seconds = "0" + Math.floor((countDownSeconds % (60)));
tagElement.text(hours.slice(-2) + ":" + minutes.slice(-2) + ":" + seconds.slice(-2));
if (countDownSeconds < 0) {
clearInterval();
if (asinToIntervalIdMap.has(asin)) {
asinToIntervalIdMap.delete(asin);
}
tagElement.text("00:00:00");
that.setDealHasEnded(ldBarPercentSection.find("[data-name=endsInTime]"));
}
}, 1000);
asinToIntervalIdMap.set(asin, intervalId);
},
updateClaim: function (ldMerchantToAsins) {
let that = this;
$.ajax({
type: "GET",
url: "/promotion/ld/claim",
data: $.param(ldMerchantToAsins, true),
traditional: true,
dataType: "json",
success: function (data) {
let viewModels = data["viewModels"];
let ldClaim = viewModels["LD_CLAIM"];
for (let i = 0; i < ldClaim.length; i++) {
let productGrid = $("#productInfoList").find("li[data-asin=" + ldClaim[i]["asin"] + "][data-merchant=" + ldClaim[i]["merchantId"] + "]");
if (productGrid !== undefined) {
let ldBarPercentSection = productGrid.find("div[name=ldBarPercentSection]");
if (ldClaim[i]["dealAvailable"]) {
ldBarPercentSection.find("[name=ldFilledBar]").width(ldClaim[i]["percentageClaimedBar"]);
ldBarPercentSection.find("[data-name=percentClaimed]").text(ldClaim[i]["percentageClaimed"]);
} else {
that.setDealHasEnded(ldBarPercentSection.find("[data-name=endsInTime]"));
}
}
}
},
error: function (e) {
}
});
},
// private function
getDpLink: function (productInfoList, i, productCategory) {
// set reftagSuffix only for carousel view
if (false && !isFilterOrSort) {
let reftagSuffix = productCategoryToReftagSuffix.get(productCategory);
return productInfoList[i]["detailPageLink"] + "&ref=" + "clp_pc_a_" + "AD5Q0BRCP11K5" + "_" + reftagSuffix;
}
return productInfoList[i]["detailPageLink"] + "&ref=" + "clp_pc_a_" + "AD5Q0BRCP11K5";
},
// private function
getDpLinkForProductInfo: function (productInfo, productCategory) {
// set reftagSuffix only for carousel view
if (false && !isFilterOrSort) {
let reftagSuffix = productCategoryToReftagSuffix.get(productCategory);
return productInfo["detailPageLink"] + "&ref=" + "clp_pc_a_" + "AD5Q0BRCP11K5" + "_" + reftagSuffix;
}
return productInfo["detailPageLink"] + "&ref=" + "clp_pc_a_" + "AD5Q0BRCP11K5";
},
setDealHasEnded: function (endsInTime) {
endsInTime.text("Deal has ended");
endsInTime.removeClass("a-color-success");
endsInTime.addClass("a-color-error");
},
continuousUpdateClaim: function (ldMerchantToAsins) {
if (Object.keys(ldMerchantToAsins).length > 0) {
let that = this;
// updates ever 10 seconds (10 * 1000 milliseconds) continuously
setInterval(function () {
that.updateClaim(ldMerchantToAsins);
}, 10000);
}
},
// private function
getRefTag: function (key, value) {
//Filter has been toggled off so no reftag is necessary
if (value === "") {
reftag = "";
return;
}
reftag = "?ref="
switch (key) {
case "applicabilityIndex":
reftag += "clp_pc_pd_";
break;
case "bestSeller":
reftag += "clp_pc_re_best";
break;
case "sortBy":
reftag += "clp_pc_so_" + value;
break;
case"productCategory":
reftag += "clp_pc_re_" + value;
break;
case "avgCustomerReview":
reftag += "clp_pc_re_cr_" + value;
break;
case "priceTierMin":
reftag += "clp_pc_re_pmin_";
case "priceTierMax":
reftag += "clp_pc_re_pmax_";
break;
case "searchKeyword":
reftag += "clp_pc_se_box";
break;
case "seeAll":
reftag += "clp_pc_see_all_" + value;
break;
case "sortId":
reftag += "_see_more";
}
},
// private function
getProductInfoControllerURL() {
if (false && !isFilterOrSort) {
return "/promotion/psp/productInfoListForSUS";
}
return "/promotion/psp/productInfoList";
},
// private function
// We generate 10 placeholder carousels by default to accommodate maximum 10 product category (cannot create
// extra after the initialization.
// However, we don't necessary get all 10 carousels every time, so we hide the rest of the placeholder
// carousel after runtime
hideUnusedCarousels: function (carouselName, availableProductCategories) {
for (let i = 6; i >= availableProductCategories.length; i--) {
$("#" + carouselName + "_" + i).addClass("hidden");
}
},
// private function
showSpin: function () {
// Show PSP page spinning
$("#a-page").attr("disabled", true);
$("#a-page").addClass("halfOpacity");
$("#pspSpinner").removeClass("hidden");
},
// private function
hideSpin: function () {
// Hide PSP page spinning
$("#pspSpinner").addClass("hidden");
$("#a-page").removeClass("halfOpacity");
$("#a-page").attr("disabled", false);
},
showClearButton: function() {
let menuButtons = $("#refinementMenu [name=menuButton].menuButtonFocus").not("#Featured-1");
if (menuButtons.length > 0) {
$("#clearFiltersBox").removeClass("hidden").addClass("inlineBlock");
} else {
$("#clearFiltersBox").addClass("hidden").removeClass("inlineBlock");
}
},
//private function
isProductRestricted: function(productInfoList) {
if (false) {
let firstAsin = productInfoList[0];
return firstAsin !== undefined && firstAsin["restrictedErrorPage"];
}
return false;
},
//private function
shouldAutoRedeem: function() {
let autoRedeem = "false" === "true" && !(this.isProductRestricted(this.cachedPromotionShoppingPageResponse["viewModels"]["PRODUCT_INFO_LIST"]));
if (false) {
autoRedeem = "false" === "true" && !(this.isProductRestricted(this.cachedPromotionShoppingPageResponse["viewModels"]["PRODUCT_INFO_LIST_SUS"]));
}
return autoRedeem;
}
}
});
window.P.when("queryParameterAjax_module", "ready").execute(function (queryParameterAjaxModule) {
// We only want this to happen when we want to show the productList and refinements.
if ("LONG_ENDED_PROMOTION" == "CUSTOMER_ELIGIBLE" || false) {
queryParameterAjaxModule.firstPageLoad(queryParameterAjaxModule.queryParameterKeys.promotionId, "AD5Q0BRCP11K5", true, true);
}
queryParameterAjaxModule.resetSelection();
});