{"version":3,"file":"ProductList.min.js","sources":["ProductList.js"],"sourcesContent":["(function ($, _, root, undefined) {\r\n 'use strict';\r\n\r\n var assetId = 'uc193-productlist';\r\n var productsHandlerUrl = root.R + 'Handlers/Public/ProductData.ashx';\r\n var pubSub = root.PubSub;\r\n\r\n var classes = {\r\n prodItem: 'js-uc193-item',\r\n mainImage: 'js-uc193-image',\r\n dimItem: 'js-uc193-dim-item',\r\n quickView: 'js-quick-view',\r\n buyBtn: 'BuyBtn',\r\n modifyQtyBtn: 'js-quantity-plus-minus-btn',\r\n editQtyBtn: 'js-edit-quantity-button',\r\n editQtyBtnReplacer: 'js-edit-quantity-button-replacer',\r\n quantityInput: 'QuantityTxb',\r\n fractionInput: 'js-uc193-fraction',\r\n overlayBtn: 'js-show-overlay',\r\n hideOverlayBtn: 'js-hide-overlay',\r\n };\r\n\r\n// ReSharper disable StringLiteralTypo\r\n var dataNames = {\r\n itemId: 'itemid',\r\n productId: 'productid',\r\n imageId: 'imageid',\r\n tempOrderLineId: 'temp-order-line-id',\r\n quantityEditMode: 'quantity-edit-mode',\r\n }\r\n// ReSharper restore StringLiteralTypo\r\n\r\n function controlsProvider($mainPanelControl) {\r\n return {\r\n $mainPanel: $mainPanelControl,\r\n $productListContainer: $mainPanelControl.find('.ProductListContainer'),\r\n $perPageItems: $mainPanelControl.find('.ItemsPerPage'),\r\n $pagingControls: $mainPanelControl.find('.ProductListPagerContainer'),\r\n $viewSettings: $mainPanelControl.find('.viewSettings'),\r\n $sortingControls: $mainPanelControl.find('.SortingSelector'),\r\n $cbxShowOnlyInStock: $mainPanelControl.find('.js-show-only-in-stock'),\r\n $searchInput: $mainPanelControl.find('.js-product-list-search').find('.js-product-list-search-input'),\r\n $campaignFragmentContainer: $mainPanelControl.find('.js-fragment-container.Campaign'),\r\n\r\n $productContainers: null,\r\n\r\n init: function () {\r\n this.$productContainers = this.$productListContainer.find('.' + classes.prodItem);\r\n }\r\n }\r\n }\r\n\r\n function productListController($mainPanel, productListModel) {\r\n var model = productListModel;\r\n\r\n var controls = new controlsProvider($mainPanel);\r\n\r\n var currentState = {\r\n controlId: model.controlId,\r\n pageControlId: model.pageControlId,\r\n page: model.currentPage,\r\n perPage: model.perPage,\r\n isProductPage: model.isProductPage,\r\n showOnlyInStock: model.showOnlyInStock,\r\n totalItems: model.totalItems,\r\n filteredItemIds: undefined,\r\n filtersUrl: undefined,\r\n appliedFilters: undefined,\r\n searchTerm: model.searchTerm,\r\n sort: undefined,\r\n showViewAll: model.showViewAll,\r\n loginUrl: root.R + model.loginUrl,\r\n isPreAppliedFilterProcessed: false,\r\n dataCache: {},\r\n timer: null,\r\n };\r\n\r\n var pubSubEventNames = {\r\n// ReSharper disable StringLiteralTypo\r\n filtersChannelPrefix: 'frontend.productlist.filters.' + currentState.controlId,\r\n staticFilterChannelPrefix: 'frontend.productlist.staticfilter.' + currentState.controlId,\r\n refreshChannelPrefix: 'frontend.productlist.refresh.' + currentState.controlId,\r\n initChannelPrefix: 'frontend.productlist.init.' + currentState.controlId,\r\n readyChannelPrefix: 'frontend.productlist.ready.' + currentState.controlId,\r\n\r\n uniqueFiltersChannelPrefix: 'frontend.productlist.filters.' + currentState.pageControlId,\r\n uniqueStaticFilterChannelPrefix: 'frontend.productlist.staticfilter.' + currentState.pageControlId,\r\n uniqueRefreshChannelPrefix: 'frontend.productlist.refresh.' + currentState.pageControlId,\r\n uniqueInitChannelPrefix: 'frontend.productlist.init.' + currentState.pageControlId,\r\n uniqueReadyChannelPrefix: 'frontend.productlist.ready.' + currentState.pageControlId,\r\n// ReSharper restore StringLiteralTypo\r\n }\r\n\r\n return {\r\n init: function () {\r\n initProductControls(model, controls, currentState, pubSubEventNames);\r\n\r\n reportImpressions(model, controls);\r\n\r\n var initialTerm = $.trim(controls.$searchInput.val());\r\n if (initialTerm && initialTerm.length >= 3) {\r\n search(model, controls, currentState, pubSubEventNames, initialTerm);\r\n }\r\n\r\n // Subscribe to removeFromCart event and hide shopCart icon\r\n// ReSharper disable StringLiteralTypo\r\n root.PublicEStore.subscribe('estore.callback.shopcart.removefromcart', removeFromCartCallback);\r\n root.PublicEStore.subscribe('estore.callback.shopcart.emptycart', emptyCartCallback);\r\n root.PublicEStore.subscribe('estore.callback.shopcart.addtocart', addToCartGlobalCallback);\r\n root.PublicEStore.subscribe('estore.callback.shopcart.updatecartquantity', updateCartGlobalCallback);\r\n// ReSharper restore StringLiteralTypo\r\n\r\n setupViewSettings();\r\n if (controls.$campaignFragmentContainer.length > 0) {\r\n // Hide paging and sorting for campaigns. Campaigns should be valid for the initial load only.\r\n controls.$viewSettings.hide();\r\n } else {\r\n controls.$viewSettings.show();\r\n setupPaging(model, controls, currentState, pubSubEventNames);\r\n }\r\n\r\n // Filters\r\n if (!model.skipFilterEvents) {\r\n pubSub.subscribe(pubSubEventNames.filtersChannelPrefix + '.apply', filterCallback);\r\n pubSub.subscribe(pubSubEventNames.uniqueFiltersChannelPrefix + '.apply', filterCallback);\r\n\r\n pubSub.subscribe(pubSubEventNames.staticFilterChannelPrefix + '.apply', onStaticFilterApplyChannel);\r\n pubSub.subscribe(pubSubEventNames.uniqueStaticFilterChannelPrefix + '.apply', onStaticFilterApplyChannel);\r\n\r\n pubSub.subscribe(pubSubEventNames.staticFilterChannelPrefix + '.reset', onStaticFilterResetChannel);\r\n pubSub.subscribe(pubSubEventNames.uniqueStaticFilterChannelPrefix + '.reset', onStaticFilterResetChannel);\r\n\r\n function onStaticFilterApplyChannel(topic, data) {\r\n currentState.page = 1;\r\n currentState.filteredCategoryIDs = data.selectedIds;\r\n refreshProductList(model, controls, currentState, pubSubEventNames, false, true, false, false, false);\r\n }\r\n\r\n function onStaticFilterResetChannel() {\r\n currentState.page = 1;\r\n currentState.filteredCategoryIDs = null;\r\n refreshProductList(model, controls, currentState, pubSubEventNames, false, true, false, false, false);\r\n }\r\n }\r\n\r\n if (model.enableHistoryState) {\r\n // Set initial state\r\n root.history.replaceState(currentState, '', null);\r\n // Subscribe to popstate event\r\n $(root).on('popstate', onHistoryPopState);\r\n }\r\n\r\n pubSub.publish(pubSubEventNames.readyChannelPrefix);\r\n pubSub.publish(pubSubEventNames.uniqueReadyChannelPrefix);\r\n\r\n function filterCallback(topic, filterState) {\r\n if (filterState.isPreApplied === true) {\r\n if (currentState.isPreAppliedFilterProcessed) {\r\n return;\r\n }\r\n currentState.isPreAppliedFilterProcessed = true;\r\n }\r\n\r\n var totalItemsAfterFiltersApplied = typeof (filterState.filteredItemIds) !== 'undefined' && filterState.filteredItemIds !== null\r\n ? filterState.filteredItemIds.length\r\n : currentState.totalItemsInDataSource;\r\n\r\n // reset paging\r\n if (!filterState.isRestoring) {\r\n currentState.page = 1;\r\n }\r\n currentState.totalItems = totalItemsAfterFiltersApplied;\r\n // apply filters\r\n currentState.filteredItemIds = filterState.filteredItemIds;\r\n currentState.filtersUrl = filterState.filtersUrl;\r\n currentState.appliedFilters = filterState.appliedFilters;\r\n\r\n refreshProductList(model, controls, currentState, pubSubEventNames, filterState.isHistoryPopEvent !== true, true, true, false, false);\r\n }\r\n\r\n function removeFromCartCallback(topic, dataContract) {\r\n _.each(dataContract.result.items, function (prod) {\r\n if (prod.status.toLowerCase() === 'ok') {\r\n var $prodContainer = controls.$productContainers.filter('[data-productid=\"' + prod.productID + '\"]');\r\n if ($prodContainer) {\r\n $prodContainer.find('.js-add-to-cart').hide();\r\n disableQuantityEditMode(controls, $prodContainer);\r\n }\r\n }\r\n });\r\n }\r\n\r\n function emptyCartCallback(topic, dataContract) {\r\n if (dataContract.status.toLowerCase() === 'ok') {\r\n controls.$productListContainer.find('.js-add-to-cart').hide();\r\n controls.$productContainers.each(function () {\r\n disableQuantityEditMode(controls, $(this));\r\n });\r\n }\r\n }\r\n\r\n function addToCartGlobalCallback(topic, contract) {\r\n _.each(contract.result.items, function (prod) {\r\n if (prod.status.toLowerCase() === 'ok') {\r\n var $prodContainer = controls.$productContainers.filter('[data-productId=\"' + prod.productID + '\"]');\r\n updateProdCardQuantity($prodContainer, prod.totalQuantityInTempOrderLine);\r\n\r\n enableQuantityEditMode($prodContainer, prod.tempOrderLineID);\r\n }\r\n });\r\n }\r\n\r\n function updateCartGlobalCallback(topic, contract) {\r\n _.each(contract.result.items, function (prod) {\r\n if (prod.status.toLowerCase() === 'ok') {\r\n var $prodContainer = controls.$productContainers.filter('[data-productId=\"' + prod.productID + '\"]');\r\n\r\n updateProdCardQuantity($prodContainer, prod.quantity);\r\n }\r\n });\r\n }\r\n\r\n function updateProdCardQuantity($prodContainer, prodQuntity){\r\n // Update or Add total product's count for the current temp order line\r\n var orderLineQuantityContainer = $prodContainer.find('.js-prod-count');\r\n orderLineQuantityContainer.show();\r\n orderLineQuantityContainer.text(prodQuntity);\r\n\r\n // Animate action\r\n var $addToCartIconContainer = $prodContainer.find('.js-add-to-cart');\r\n if ($addToCartIconContainer.length > 0 && prodQuntity > 0) {\r\n $addToCartIconContainer.show();\r\n $prodContainer.effect('transfer', { to: $addToCartIconContainer }, 500, function () {\r\n $addToCartIconContainer.effect('bounce', null, 500);\r\n });\r\n } else {\r\n $addToCartIconContainer.hide();\r\n }\r\n }\r\n\r\n function setupViewSettings() {\r\n // Setup sorting\r\n if (controls.$sortingControls.length > 0) {\r\n currentState.sort = controls.$sortingControls.val();\r\n controls.$sortingControls.change(function () {\r\n sortingChangedCallback(this.value);\r\n });\r\n }\r\n\r\n function sortingChangedCallback(sortBy) {\r\n currentState.sort = sortBy;\r\n refreshProductList(model, controls, currentState, pubSubEventNames, true, false, true, false, false);\r\n }\r\n\r\n // Setup items per page changes\r\n controls.$perPageItems.change(function (evt) {\r\n currentState.perPage = parseInt(evt.target.value);\r\n // Reset current page index\r\n currentState.page = 1;\r\n refreshProductList(model, controls, currentState, pubSubEventNames, true, true, true, false, false);\r\n });\r\n\r\n //Setup show only in stock change\r\n if (controls.$cbxShowOnlyInStock.length) {\r\n controls.$cbxShowOnlyInStock.prop('checked', currentState.showOnlyInStock === true);\r\n controls.$cbxShowOnlyInStock.change(function () {\r\n currentState.page = 1;\r\n currentState.showOnlyInStock = controls.$cbxShowOnlyInStock.prop('checked');\r\n refreshProductList(model, controls, currentState, pubSubEventNames, true, true, true, false, false);\r\n });\r\n }\r\n }\r\n\r\n function onHistoryPopState(evt) {\r\n var state = evt.originalEvent.state;\r\n if (state && state.controlId === currentState.controlId) {\r\n // Restore target state\r\n currentState = state;\r\n\r\n if (controls.$cbxShowOnlyInStock.length) {\r\n controls.$cbxShowOnlyInStock.prop('checked', currentState.showOnlyInStock === true);\r\n }\r\n\r\n refreshProductList(model, controls, currentState, pubSubEventNames, false, true, true, false, false);\r\n }\r\n }\r\n }\r\n }\r\n }\r\n\r\n function createProductListController(productListContext) {\r\n if (productListContext) {\r\n var mainPanelId = productListContext.mainPanelID;\r\n var $mainPanel = $('#' + mainPanelId);\r\n\r\n if ($mainPanel.length === 1) {\r\n return new productListController($mainPanel, productListContext);\r\n } else if ($mainPanel.length === 0) {\r\n console.warn(assetId + ': product list main panel element was not found by id#' + mainPanelId);\r\n } else {\r\n console.warn(assetId + ': found > 1 product list main panel elements with id#' + mainPanelId);\r\n }\r\n }\r\n return null;\r\n }\r\n\r\n root.createProductListController = createProductListController;\r\n\r\n $(function () {\r\n if (root.umwAssets && root.umwAssets[assetId]) {\r\n root.umwAssets[assetId].forEach(function (ctx) {\r\n var controller = createProductListController(ctx);\r\n if (controller) {\r\n controller.init();\r\n }\r\n });\r\n }\r\n });\r\n\r\n function initProductControls(model, controls, currentState, pubSubEventNames) {\r\n controls.init();\r\n\r\n controls.$productContainers.find('.' + classes.buyBtn).click(onBuyButtonClick);\r\n controls.$productContainers.find('.WishListBtn').click(onWishListButtonClick);\r\n controls.$productContainers.find('.QuantityDrp').change(onQuantityChanged);\r\n controls.$productContainers.find('.ShoppingListBtn').click(onShoppingListButtonClick);\r\n controls.$productContainers.find('.' + classes.quickView).click(onQuickViewButtonClick);\r\n controls.$productContainers.find('.' + classes.editQtyBtn).click(onEditQtyButtonClick);\r\n controls.$productContainers.find('.' + classes.modifyQtyBtn).click(onQuantityModifyButtonClick);\r\n controls.$productContainers.find('.' + classes.overlayBtn).click(onOverlayBtn);\r\n controls.$productContainers.find('.' + classes.hideOverlayBtn).click(onHideOverlayBtn);\r\n\r\n if (model.showCategoriesInfo) {\r\n setupCategoriesInfo();\r\n }\r\n\r\n if (model.showDimensionsInStockInfo) {\r\n // Build dimension stock info for single dimension products\r\n setupDimensionsInStockOverlay();\r\n }\r\n\r\n setupDimensionChoices();\r\n\r\n function setupCategoriesInfo() {\r\n const $productItems = controls.$productListContainer.find('.js-uc193-item');\r\n const productItemIds = $productItems.map(function () { return $(this).data(dataNames.itemId); }).get();\r\n\r\n $.post(productsHandlerUrl, {\r\n action: 'getProductsCategoriesInfo',\r\n itemIds: JSON.stringify(productItemIds),\r\n rootCategories: JSON.stringify(model.categoriesInfoRootCategories),\r\n iconImageWidth: model.categoryInfoIconImageWidth\r\n }).done((productsCategoriesMap) => {\r\n _.each(productsCategoriesMap, (categoriesInfo, currentItemId) => {\r\n if (categoriesInfo) {\r\n const currentProductCategoriesInfoComponent = document.querySelectorAll('cms-category-info[data-itemid=\"' + currentItemId + '\"]')[0];\r\n currentProductCategoriesInfoComponent.render(categoriesInfo);\r\n }\r\n })\r\n })\r\n .fail(() => {\r\n console.error('Failed to load products categories info');\r\n });\r\n }\r\n\r\n pubSub.publish(pubSubEventNames.initChannelPrefix, { controlId: currentState.controlId, mainPanelId: model.mainPanelID });\r\n pubSub.publish(pubSubEventNames.uniqueInitChannelPrefix, { controlId: currentState.controlId, mainPanelId: model.mainPanelID });\r\n\r\n function onBuyButtonClick(evt) {\r\n evt.preventDefault();\r\n var $prodContainer = $(this).closest('.' + classes.prodItem);\r\n\r\n var tempOrderLineId = $prodContainer.data(dataNames.tempOrderLineId);\r\n var quantity = $.mw_tryParseIntStrict(getSelectedProductQuantity($prodContainer));\r\n\r\n var deferred = [];\r\n\r\n if (isQuantityEditModeEnabled($prodContainer) && quantity === 0 && tempOrderLineId) {\r\n var removeFromCartContract = getRemoveFromCartContract($prodContainer, tempOrderLineId);\r\n deferred.push(root.PublicEStore.removeFromCart(removeFromCartContract));\r\n } else {\r\n var addToCartContract = getAddToCartContract($prodContainer);\r\n deferred.push(root.PublicEStore.addToCart(addToCartContract));\r\n }\r\n\r\n if (deferred.length) {\r\n $prodContainer.addClass('buying');\r\n $.when.apply($, deferred)\r\n .done(successCallback)\r\n .fail(errorCallback).always(function() {\r\n $prodContainer.removeClass('buying');\r\n });\r\n }\r\n\r\n function successCallback(dataContract) {\r\n _.each(dataContract.result.items, function (prod) {\r\n if (prod.status.toLowerCase() !== 'ok') {\r\n notify(prod.message, 'error');\r\n }\r\n });\r\n }\r\n\r\n function errorCallback(dataContract) {\r\n if (dataContract.status.toLowerCase() === 'unauthorized') {\r\n pubSub.publish('notification.warning', { text: model.labels.availableToRegisteredOnly + '
' + model.labels.loginToContinue + '', layout: 'center', killer: true, modal: true, timeout: false });\r\n } else if (dataContract.result) {\r\n _.each(dataContract.result.items, function (prod) {\r\n notify(prod.message, 'error');\r\n });\r\n }\r\n }\r\n }\r\n function onWishListButtonClick(evt) {\r\n var $wishListControl = $(this);\r\n var needsAdditionalInputToBuy = $wishListControl.hasClass('NeedsAdditionalInputToBuy');\r\n if (needsAdditionalInputToBuy) {\r\n return;\r\n }\r\n\r\n evt.preventDefault();\r\n\r\n var isAddToWishListAction = $wishListControl.hasClass('Add');\r\n var productId = $wishListControl.closest('.' + classes.prodItem).data(dataNames.productId);\r\n window.updateWishList(productId, isAddToWishListAction ? 'add' : 'remove', wishListCallback);\r\n\r\n function wishListCallback(dataContract) {\r\n if (dataContract.status.toLowerCase() === 'ok') {\r\n _.each(dataContract.result.items,\r\n function (prod) {\r\n if (prod.status.toLowerCase() === 'ok') {\r\n notify(model.labels.wishListUpdated, 'success');\r\n\r\n $wishListControl.toggleClass('Add', !isAddToWishListAction);\r\n $wishListControl.toggleClass('Remove', isAddToWishListAction);\r\n } else {\r\n notify(prod.message, 'error');\r\n }\r\n });\r\n } else {\r\n notify(dataContract.message, dataContract.status);\r\n }\r\n }\r\n }\r\n function onQuantityChanged() {\r\n if (model.multPriceByQuantity) {\r\n var $prodContainer = $(this).closest('.' + classes.prodItem);\r\n var productId = $prodContainer.data(dataNames.productId);\r\n var quantity = getSelectedProductQuantity($prodContainer);\r\n\r\n var cacheKey = 'quantityPrices_' + productId + '_' + quantity;\r\n if (cacheKey in currentState.dataCache) {\r\n var productListItem = currentState.dataCache[cacheKey];\r\n updateDisplayedPrices($prodContainer, productListItem);\r\n } else {\r\n\r\n blockUI();\r\n\r\n var query = {\r\n action: 'GetProductQuantityPrice',\r\n controlId: currentState.controlId,\r\n pageId: root.BasePageID,\r\n productId: productId,\r\n quantity: quantity\r\n };\r\n\r\n $.get(productsHandlerUrl, query)\r\n .done(function (productListItem) {\r\n currentState.dataCache[cacheKey] = productListItem;\r\n updateDisplayedPrices($prodContainer, productListItem);\r\n })\r\n .fail(function (errResp) {\r\n var message;\r\n if (typeof (errResp) === 'object') {\r\n // Extract error message\r\n var responseObj = JSON.parse(errResp.responseText);\r\n message = responseObj.Message ? responseObj.Message : errResp.statusText;\r\n } else {\r\n message = errResp;\r\n }\r\n notify(model.labels.failedToLoadProductList + '
' + message, 'error');\r\n })\r\n .always(unblockUI);\r\n }\r\n }\r\n\r\n function updateDisplayedPrices($prodContainer, productListItem) {\r\n if (productListItem.DiscountPrice) {\r\n $prodContainer.find('.DiscountPriceRow .DiscountPrice.Value').text(productListItem.DiscountPriceString);\r\n }\r\n if (productListItem.Price) {\r\n if (productListItem.OriginalPrice) {\r\n $prodContainer.find('.PriceRow .OriginalPrice.Value').text(productListItem.OriginalPriceString);\r\n }\r\n $prodContainer.find('.PriceRow .Price').not('.WithVAT,.WithoutVAT').text(productListItem.PriceString);\r\n }\r\n if (productListItem.PriceWithoutVAT) {\r\n if (productListItem.OriginalPrice) {\r\n $prodContainer.find('.PriceRow .OriginalPrice.Value').text(productListItem.OriginalPriceString);\r\n }\r\n $prodContainer.find('.PriceRow .Price.WithoutVAT').text(productListItem.PriceWithoutVATString);\r\n }\r\n if (productListItem.PriceWithVAT) {\r\n if (productListItem.OriginalPrice) {\r\n $prodContainer.find('.PriceRow .OriginalPrice.Value').text(productListItem.OriginalPriceString);\r\n }\r\n $prodContainer.find('.PriceRow .Price.WithVAT').text(productListItem.PriceWithVATString);\r\n }\r\n if (productListItem.Price2) {\r\n $prodContainer.find('.Price2Row .Price2.Value').text(productListItem.Price2String);\r\n }\r\n if (productListItem.Price3) {\r\n $prodContainer.find('.Price3Row .Price3.Value').text(productListItem.Price3String);\r\n }\r\n }\r\n }\r\n function onShoppingListButtonClick(evt) {\r\n evt.preventDefault();\r\n\r\n var $shoppingListButton = $(this);\r\n var $prodContainer = $shoppingListButton.closest('.' + classes.prodItem);\r\n var productToAdd = getAddToCartContract($prodContainer);\r\n root.showAddToCollectionPopup([productToAdd]);\r\n }\r\n function onQuickViewButtonClick(evt) {\r\n evt.preventDefault();\r\n\r\n var $prodContainer = $(this).closest('.' + classes.prodItem);\r\n var productId = $prodContainer.data(dataNames.productId);\r\n\r\n var query = {\r\n action: 'GetQuickView',\r\n controlId: currentState.controlId,\r\n pageId: root.BasePageID,\r\n productId: productId\r\n };\r\n\r\n blockUI();\r\n\r\n $.get(productsHandlerUrl, query)\r\n .always(unblockUI)\r\n .done(function (quickViewData) {\r\n var quickViewHtml = quickViewData.html;\r\n var quickViewModel = quickViewData.model;\r\n\r\n if (quickViewHtml) {\r\n showQuickViewPopup(quickViewHtml, quickViewModel);\r\n } else {\r\n reportQuickViewFail();\r\n }\r\n })\r\n .fail(reportQuickViewFail);\r\n\r\n function reportQuickViewFail() {\r\n notify(model.labels.failedToLoadQuickView, 'error');\r\n }\r\n\r\n function showQuickViewPopup(quickViewHtml, quickViewModel) {\r\n $.fancybox.open({\r\n src: quickViewHtml,\r\n type: 'html',\r\n opts: {\r\n parentEl: \"form:first\",\r\n afterLoad: function (instance, current) {\r\n if (typeof root.productViewController !== 'function')\r\n console.error('Product view main asset is not loaded');\r\n\r\n var quickViewController = root.productViewController(current.$content, quickViewModel);\r\n quickViewController.init();\r\n\r\n if (typeof root.customFieldsController === 'function') {\r\n var customFieldsController = root.customFieldsController();\r\n customFieldsController.init();\r\n }\r\n }\r\n }\r\n });\r\n }\r\n }\r\n function onEditQtyButtonClick(evt) {\r\n var $prodContainer = $(this).closest('.' + classes.prodItem);\r\n\r\n evt.preventDefault();\r\n\r\n var productId = $prodContainer.data(dataNames.productId);\r\n\r\n var query = {\r\n action: 'getProductCartInfo',\r\n productId: productId\r\n };\r\n\r\n blockUI();\r\n\r\n $.get(productsHandlerUrl, query)\r\n .always(unblockUI)\r\n .done(function (productCartInfo) {\r\n if (productCartInfo) {\r\n processProductCartInfo(productCartInfo);\r\n }\r\n })\r\n .fail(reportProductCartInfoFail);\r\n\r\n function reportProductCartInfoFail() {\r\n notify('Failed to load product cart info.', 'error');\r\n }\r\n\r\n function processProductCartInfo(productCartInfo) {\r\n $prodContainer.data(dataNames.tempOrderLineId, productCartInfo.tempOrderLineId);\r\n if (productCartInfo.factor) {\r\n $prodContainer.find('.' + classes.quantityInput).val(productCartInfo.factorQuantity);\r\n $prodContainer.find('.' + classes.fractionInput).val(productCartInfo.fractionQuantity);\r\n } else {\r\n $prodContainer.find('.' + classes.quantityInput).val(productCartInfo.inCartQuantity);\r\n }\r\n }\r\n }\r\n function onQuantityModifyButtonClick(evt) {\r\n evt.preventDefault();\r\n\r\n const $this = $(this);\r\n\r\n const dataAttributes = {\r\n actionType: $this.data('action'),\r\n quantityTxbId: $this.data('target')\r\n };\r\n\r\n const $quantityInput = $this.parent().find(dataAttributes.quantityTxbId);\r\n\r\n const quantityString = $quantityInput.val();\r\n let quantity = parseFloat(quantityString.replace(',', '.'));\r\n\r\n const quantityMinValString = $quantityInput.attr('min');\r\n const quantityDataMinValString = $quantityInput.data('min')?.toString();\r\n const quantityMinVal = quantityMinValString ?\r\n parseFloat(quantityMinValString.replace(',', '.'))\r\n : quantityDataMinValString ?\r\n parseFloat(quantityDataMinValString.replace(',', '.'))\r\n : 1;\r\n\r\n switch (dataAttributes.actionType) {\r\n case 'decrease':\r\n if (quantity > quantityMinVal)\r\n quantity = --quantity;\r\n break;\r\n case 'increase':\r\n quantity = ++quantity;\r\n break;\r\n }\r\n\r\n if (quantity < quantityMinVal) {\r\n $quantityInput.val(quantityMinVal.toLocaleString());\r\n } else {\r\n quantity = Math.round(quantity * 10) / 10;\r\n $quantityInput.val(quantity.toLocaleString());\r\n }\r\n\r\n $quantityInput.trigger('change');\r\n };\r\n function onOverlayBtn() {\r\n var $prodContainer = $(this).closest('.' + classes.prodItem);\r\n hideOverlaysExcept(controls, $prodContainer);\r\n $prodContainer.addClass('show-overlay');\r\n }\r\n function onHideOverlayBtn() {\r\n var $prodContainer = $(this).closest('.' + classes.prodItem);\r\n $prodContainer.removeClass('show-overlay');\r\n }\r\n\r\n function setupDimensionsInStockOverlay() {\r\n var $singleDimensionProducts = controls.$productListContainer.find('.SingleDimensionProduct');\r\n var singleDimensionItemIds = $singleDimensionProducts.map(function () { return $(this).data(dataNames.itemId); }).get();\r\n\r\n $.post(productsHandlerUrl, {\r\n action: 'GetAvailableDimensionProducts',\r\n itemIds: JSON.stringify(singleDimensionItemIds)\r\n })\r\n .done(function (availableDimProductsMap) {\r\n _.each(availableDimProductsMap, function (availableDimProducts, currentItemId) {\r\n var $currentProductContainer = $singleDimensionProducts.filter('[data-itemid=\"' + currentItemId + '\"]');\r\n var $currentDimensionsInStockContainer = $currentProductContainer.find('.js-dimensions-in-stock');\r\n\r\n var $dimensionsStockContent;\r\n if (availableDimProducts && availableDimProducts.length > 0) {\r\n $dimensionsStockContent = $('