{"version":3,"file":"jwsdw-basket.js","sources":["../../../../../../../webfrontend/assets/vendor/angularjs/angular-touch.js","../../../../../../../temp/ngAnnotate/assets/modules/basket/app.module.js","../../../../../../../temp/ngAnnotate/assets/modules/basket/app.constants.js","../../../../../../../temp/ngAnnotate/assets/modules/basket/app.controller.js","../../../../../../../temp/ngAnnotate/assets/modules/basket/data.service.js","../../../../../../../temp/ngAnnotate/assets/jwsdw-selectVoucherPicker.js","../../../../../../../temp/ngAnnotate/assets/jwsdw-basket.js"],"sourcesContent":["/**\r\n * @license AngularJS v1.8.0\r\n * (c) 2010-2020 Google, Inc. http://angularjs.org\r\n * License: MIT\r\n */\r\n(function(window, angular) {'use strict';\r\n\r\n/**\r\n * @ngdoc module\r\n * @name ngTouch\r\n * @description\r\n *\r\n * The `ngTouch` module provides helpers for touch-enabled devices.\r\n * The implementation is based on jQuery Mobile touch event handling\r\n * ([jquerymobile.com](http://jquerymobile.com/)). *\r\n *\r\n * See {@link ngTouch.$swipe `$swipe`} for usage.\r\n *\r\n * @deprecated\r\n * sinceVersion=\"1.7.0\"\r\n * The ngTouch module with the {@link ngTouch.$swipe `$swipe`} service and\r\n * the {@link ngTouch.ngSwipeLeft} and {@link ngTouch.ngSwipeRight} directives are\r\n * deprecated. Instead, stand-alone libraries for touch handling and gesture interaction\r\n * should be used, for example [HammerJS](https://hammerjs.github.io/) (which is also used by\r\n * Angular).\r\n */\r\n\r\n// define ngTouch module\r\n/* global ngTouch */\r\nvar ngTouch = angular.module('ngTouch', []);\r\n\r\nngTouch.info({ angularVersion: '1.8.0' });\r\n\r\nfunction nodeName_(element) {\r\n return angular.$$lowercase(element.nodeName || (element[0] && element[0].nodeName));\r\n}\r\n\r\n/* global ngTouch: false */\r\n\r\n /**\r\n * @ngdoc service\r\n * @name $swipe\r\n *\r\n * @deprecated\r\n * sinceVersion=\"1.7.0\"\r\n *\r\n * See the {@link ngTouch module} documentation for more information.\r\n *\r\n * @description\r\n * The `$swipe` service is a service that abstracts the messier details of hold-and-drag swipe\r\n * behavior, to make implementing swipe-related directives more convenient.\r\n *\r\n * Requires the {@link ngTouch `ngTouch`} module to be installed.\r\n *\r\n * `$swipe` is used by the `ngSwipeLeft` and `ngSwipeRight` directives in `ngTouch`.\r\n *\r\n * # Usage\r\n * The `$swipe` service is an object with a single method: `bind`. `bind` takes an element\r\n * which is to be watched for swipes, and an object with four handler functions. See the\r\n * documentation for `bind` below.\r\n */\r\n\r\nngTouch.factory('$swipe', [function() {\r\n // The total distance in any direction before we make the call on swipe vs. scroll.\r\n var MOVE_BUFFER_RADIUS = 10;\r\n\r\n var POINTER_EVENTS = {\r\n 'mouse': {\r\n start: 'mousedown',\r\n move: 'mousemove',\r\n end: 'mouseup'\r\n },\r\n 'touch': {\r\n start: 'touchstart',\r\n move: 'touchmove',\r\n end: 'touchend',\r\n cancel: 'touchcancel'\r\n },\r\n 'pointer': {\r\n start: 'pointerdown',\r\n move: 'pointermove',\r\n end: 'pointerup',\r\n cancel: 'pointercancel'\r\n }\r\n };\r\n\r\n function getCoordinates(event) {\r\n var originalEvent = event.originalEvent || event;\r\n var touches = originalEvent.touches && originalEvent.touches.length ? originalEvent.touches : [originalEvent];\r\n var e = (originalEvent.changedTouches && originalEvent.changedTouches[0]) || touches[0];\r\n\r\n return {\r\n x: e.clientX,\r\n y: e.clientY\r\n };\r\n }\r\n\r\n function getEvents(pointerTypes, eventType) {\r\n var res = [];\r\n angular.forEach(pointerTypes, function(pointerType) {\r\n var eventName = POINTER_EVENTS[pointerType][eventType];\r\n if (eventName) {\r\n res.push(eventName);\r\n }\r\n });\r\n return res.join(' ');\r\n }\r\n\r\n return {\r\n /**\r\n * @ngdoc method\r\n * @name $swipe#bind\r\n *\r\n * @description\r\n * The main method of `$swipe`. It takes an element to be watched for swipe motions, and an\r\n * object containing event handlers.\r\n * The pointer types that should be used can be specified via the optional\r\n * third argument, which is an array of strings `'mouse'`, `'touch'` and `'pointer'`. By default,\r\n * `$swipe` will listen for `mouse`, `touch` and `pointer` events.\r\n *\r\n * The four events are `start`, `move`, `end`, and `cancel`. `start`, `move`, and `end`\r\n * receive as a parameter a coordinates object of the form `{ x: 150, y: 310 }` and the raw\r\n * `event`. `cancel` receives the raw `event` as its single parameter.\r\n *\r\n * `start` is called on either `mousedown`, `touchstart` or `pointerdown`. After this event, `$swipe` is\r\n * watching for `touchmove`, `mousemove` or `pointermove` events. These events are ignored until the total\r\n * distance moved in either dimension exceeds a small threshold.\r\n *\r\n * Once this threshold is exceeded, either the horizontal or vertical delta is greater.\r\n * - If the horizontal distance is greater, this is a swipe and `move` and `end` events follow.\r\n * - If the vertical distance is greater, this is a scroll, and we let the browser take over.\r\n * A `cancel` event is sent.\r\n *\r\n * `move` is called on `mousemove`, `touchmove` and `pointermove` after the above logic has determined that\r\n * a swipe is in progress.\r\n *\r\n * `end` is called when a swipe is successfully completed with a `touchend`, `mouseup` or `pointerup`.\r\n *\r\n * `cancel` is called either on a `touchcancel` or `pointercancel` from the browser, or when we begin scrolling\r\n * as described above.\r\n *\r\n */\r\n bind: function(element, eventHandlers, pointerTypes) {\r\n // Absolute total movement, used to control swipe vs. scroll.\r\n var totalX, totalY;\r\n // Coordinates of the start position.\r\n var startCoords;\r\n // Last event's position.\r\n var lastPos;\r\n // Whether a swipe is active.\r\n var active = false;\r\n\r\n pointerTypes = pointerTypes || ['mouse', 'touch', 'pointer'];\r\n element.on(getEvents(pointerTypes, 'start'), function(event) {\r\n startCoords = getCoordinates(event);\r\n active = true;\r\n totalX = 0;\r\n totalY = 0;\r\n lastPos = startCoords;\r\n if (eventHandlers['start']) {\r\n eventHandlers['start'](startCoords, event);\r\n }\r\n });\r\n var events = getEvents(pointerTypes, 'cancel');\r\n if (events) {\r\n element.on(events, function(event) {\r\n active = false;\r\n if (eventHandlers['cancel']) {\r\n eventHandlers['cancel'](event);\r\n }\r\n });\r\n }\r\n\r\n element.on(getEvents(pointerTypes, 'move'), function(event) {\r\n if (!active) return;\r\n\r\n // Android will send a touchcancel if it thinks we're starting to scroll.\r\n // So when the total distance (+ or - or both) exceeds 10px in either direction,\r\n // we either:\r\n // - On totalX > totalY, we send preventDefault() and treat this as a swipe.\r\n // - On totalY > totalX, we let the browser handle it as a scroll.\r\n\r\n if (!startCoords) return;\r\n var coords = getCoordinates(event);\r\n\r\n totalX += Math.abs(coords.x - lastPos.x);\r\n totalY += Math.abs(coords.y - lastPos.y);\r\n\r\n lastPos = coords;\r\n\r\n if (totalX < MOVE_BUFFER_RADIUS && totalY < MOVE_BUFFER_RADIUS) {\r\n return;\r\n }\r\n\r\n // One of totalX or totalY has exceeded the buffer, so decide on swipe vs. scroll.\r\n if (totalY > totalX) {\r\n // Allow native scrolling to take over.\r\n active = false;\r\n if (eventHandlers['cancel']) {\r\n eventHandlers['cancel'](event);\r\n }\r\n return;\r\n } else {\r\n // Prevent the browser from scrolling.\r\n event.preventDefault();\r\n if (eventHandlers['move']) {\r\n eventHandlers['move'](coords, event);\r\n }\r\n }\r\n });\r\n\r\n element.on(getEvents(pointerTypes, 'end'), function(event) {\r\n if (!active) return;\r\n active = false;\r\n if (eventHandlers['end']) {\r\n eventHandlers['end'](getCoordinates(event), event);\r\n }\r\n });\r\n }\r\n };\r\n}]);\r\n\r\n/* global ngTouch: false */\r\n\r\n/**\r\n * @ngdoc directive\r\n * @name ngSwipeLeft\r\n *\r\n * @deprecated\r\n * sinceVersion=\"1.7.0\"\r\n *\r\n * See the {@link ngTouch module} documentation for more information.\r\n *\r\n * @description\r\n * Specify custom behavior when an element is swiped to the left on a touchscreen device.\r\n * A leftward swipe is a quick, right-to-left slide of the finger.\r\n * Though ngSwipeLeft is designed for touch-based devices, it will work with a mouse click and drag\r\n * too.\r\n *\r\n * To disable the mouse click and drag functionality, add `ng-swipe-disable-mouse` to\r\n * the `ng-swipe-left` or `ng-swipe-right` DOM Element.\r\n *\r\n * Requires the {@link ngTouch `ngTouch`} module to be installed.\r\n *\r\n * @element ANY\r\n * @param {expression} ngSwipeLeft {@link guide/expression Expression} to evaluate\r\n * upon left swipe. (Event object is available as `$event`)\r\n *\r\n * @example\r\n \r\n \r\n
\r\n Some list content, like an email in the inbox\r\n
\r\n
\r\n \r\n \r\n
\r\n \r\n \r\n angular.module('ngSwipeLeftExample', ['ngTouch']);\r\n \r\n \r\n */\r\n\r\n/**\r\n * @ngdoc directive\r\n * @name ngSwipeRight\r\n *\r\n * @deprecated\r\n * sinceVersion=\"1.7.0\"\r\n *\r\n * See the {@link ngTouch module} documentation for more information.\r\n *\r\n * @description\r\n * Specify custom behavior when an element is swiped to the right on a touchscreen device.\r\n * A rightward swipe is a quick, left-to-right slide of the finger.\r\n * Though ngSwipeRight is designed for touch-based devices, it will work with a mouse click and drag\r\n * too.\r\n *\r\n * Requires the {@link ngTouch `ngTouch`} module to be installed.\r\n *\r\n * @element ANY\r\n * @param {expression} ngSwipeRight {@link guide/expression Expression} to evaluate\r\n * upon right swipe. (Event object is available as `$event`)\r\n *\r\n * @example\r\n \r\n \r\n
\r\n Some list content, like an email in the inbox\r\n
\r\n
\r\n \r\n \r\n
\r\n \r\n \r\n angular.module('ngSwipeRightExample', ['ngTouch']);\r\n \r\n \r\n */\r\n\r\nfunction makeSwipeDirective(directiveName, direction, eventName) {\r\n ngTouch.directive(directiveName, ['$parse', '$swipe', function($parse, $swipe) {\r\n // The maximum vertical delta for a swipe should be less than 75px.\r\n var MAX_VERTICAL_DISTANCE = 75;\r\n // Vertical distance should not be more than a fraction of the horizontal distance.\r\n var MAX_VERTICAL_RATIO = 0.3;\r\n // At least a 30px lateral motion is necessary for a swipe.\r\n var MIN_HORIZONTAL_DISTANCE = 30;\r\n\r\n return function(scope, element, attr) {\r\n var swipeHandler = $parse(attr[directiveName]);\r\n\r\n var startCoords, valid;\r\n\r\n function validSwipe(coords) {\r\n // Check that it's within the coordinates.\r\n // Absolute vertical distance must be within tolerances.\r\n // Horizontal distance, we take the current X - the starting X.\r\n // This is negative for leftward swipes and positive for rightward swipes.\r\n // After multiplying by the direction (-1 for left, +1 for right), legal swipes\r\n // (ie. same direction as the directive wants) will have a positive delta and\r\n // illegal ones a negative delta.\r\n // Therefore this delta must be positive, and larger than the minimum.\r\n if (!startCoords) return false;\r\n var deltaY = Math.abs(coords.y - startCoords.y);\r\n var deltaX = (coords.x - startCoords.x) * direction;\r\n return valid && // Short circuit for already-invalidated swipes.\r\n deltaY < MAX_VERTICAL_DISTANCE &&\r\n deltaX > 0 &&\r\n deltaX > MIN_HORIZONTAL_DISTANCE &&\r\n deltaY / deltaX < MAX_VERTICAL_RATIO;\r\n }\r\n\r\n var pointerTypes = ['touch'];\r\n if (!angular.isDefined(attr['ngSwipeDisableMouse'])) {\r\n pointerTypes.push('mouse');\r\n }\r\n $swipe.bind(element, {\r\n 'start': function(coords, event) {\r\n startCoords = coords;\r\n valid = true;\r\n },\r\n 'cancel': function(event) {\r\n valid = false;\r\n },\r\n 'end': function(coords, event) {\r\n if (validSwipe(coords)) {\r\n scope.$apply(function() {\r\n element.triggerHandler(eventName);\r\n swipeHandler(scope, {$event: event});\r\n });\r\n }\r\n }\r\n }, pointerTypes);\r\n };\r\n }]);\r\n}\r\n\r\n// Left is negative X-coordinate, right is positive.\r\nmakeSwipeDirective('ngSwipeLeft', -1, 'swipeleft');\r\nmakeSwipeDirective('ngSwipeRight', 1, 'swiperight');\r\n\r\n\r\n\r\n})(window, window.angular);","/**\r\n * @namespace jwsdwBasket\r\n */\r\n'use strict';\r\n(function (angular) {\r\n\r\n config.$inject = ['$compileProvider'];\r\n angular.module('jwsdw.basket', [\r\n 'jwsdw.services',\r\n 'jwsdw.ocapi',\r\n 'jwsdw.tracking',\r\n 'jwsdw.util',\r\n 'jwsdw.picker',\r\n 'jwsp.picker',\r\n 'jwsp.picture',\r\n 'ngSanitize',\r\n 'ngTouch'\r\n ]).config(config);\r\n\r\n /**\r\n * Config function that specifies configuration for the jwsdw basket module.\r\n * @param {Object} $compileProvider compile provider disables adding of internal debug info.\r\n * @returns {void}\r\n */\r\n function config($compileProvider) {\r\n $compileProvider.debugInfoEnabled(false);\r\n }\r\n}(angular));","'use strict';\r\n\r\n(function (angular, window) {\r\n\r\n angular\r\n .module('jwsdw.basket')\r\n .constant('BASKET_ID', window.jwsdwSettings.basket.id)\r\n .constant('LIST_PRICE_BOOK', window.jwsdwSettings.listPriceBook)\r\n .constant('SALE_PRICE_BOOK', window.jwsdwSettings.salePriceBook)\r\n .constant('IMAGE_BASE_URL', window.jwsdwSettings.productGetImageBaseUrl)\r\n .constant('SETTINGS', window.jwsdwSettings);\r\n}(angular, window));","'use strict';\r\n\r\n(function (angular) {\r\n BasketController.$inject = ['$scope', '$log', '$anchorScroll', '$window', '$location', '$timeout', 'dataService', 'productService', 'basketService', 'contentService', 'BASKET_ID', 'SETTINGS', 'trackAddToBasketService'];\r\n angular\r\n .module('jwsdw.basket')\r\n .config(['$locationProvider', function($locationProvider) {\r\n $locationProvider.html5Mode(true);\r\n // $locationProvider.hashPrefix('?');\r\n }])\r\n .controller('BasketController', BasketController);\r\n\r\n /**\r\n * @class jwsdwBasket.BasketController\r\n * @description Method to initialize the basket page functionality\r\n * @param {Object} $scope current scope\r\n * @param {Object} $log log service that provides logging in angluar\r\n * @param {Object} $anchorScroll service to allow scrolling on the page\r\n * @param {Object} $window browser window object\r\n * @param {Object} $location browser location object\r\n * @param {Object} $timeout angular timeout service\r\n * @param {Object} dataService service to provide access data layer of the basket\r\n * @param {Object} productService service to provide product information (used for creation of variants item)\r\n * @param {Object} basketService service to provide basket information\r\n * @param {Object} contentService service to provide content information via OCAPI\r\n * @param {String} BASKET_ID basket id of the current basket provided through demandware backend (window.jwsdwSettings) and loaded into the module as constant\r\n * @param {String} SETTINGS window jwsdwSettings\r\n * @param {Object} trackAddToBasketService trackAddToBasketService\r\n * @constructor\r\n */\r\n function BasketController($scope, $log, $anchorScroll, $window, $location, $timeout, dataService, productService, basketService, contentService, BASKET_ID, SETTINGS, trackAddToBasketService) { // eslint-disable-line max-len, max-params, max-statements\r\n var vm = this;\r\n\r\n vm.dataService = dataService;\r\n vm.productService = productService;\r\n\r\n vm.proceedingToCheckout = false;\r\n vm.proceedingToDirectCheckout = false;\r\n\r\n vm.updating = false;\r\n vm.sessionError = false;\r\n vm.invalidProductError = false;\r\n vm.quantityError = false;\r\n vm.bonusProductActive = true;\r\n vm.couponCode = '';\r\n vm.gPayLoaded = false;\r\n vm.maxCartQuantityPerItem = SETTINGS.maxCartQuantityPerItem;\r\n vm.quantityOptions = [];\r\n vm.couponInputRevealed = false;\r\n vm.recommendedProductDismissed = false;\r\n vm.recommendedProductObserver = null;\r\n vm.refusalReason = $location.search().reason || undefined;\r\n vm.currentVoucher = undefined;\r\n vm.voucherSectionUpdating = false;\r\n\r\n /* Wishlist handling */\r\n vm.wishlistCount = SETTINGS.wishlistCount || 0;\r\n vm.maxWishlistItemsForGuest = SETTINGS.maxWishlistItemsForGuest || 0;\r\n vm.wishlist = SETTINGS.wishlist;\r\n\r\n //public methods\r\n vm.removeItem = removeItem;\r\n vm.onRemoveButtonClick = onRemoveButtonClick;\r\n vm.onRemoveCancelButtonClick = onRemoveCancelButtonClick;\r\n vm.updateQuantity = updateQuantity;\r\n vm.updateProduct = updateProduct;\r\n vm.addCoupon = addCoupon;\r\n vm.removeCoupon = removeCoupon;\r\n vm.removeBonusCoupon = removeBonusCoupon;\r\n vm.toggleBonusProduct = toggleBonusProduct;\r\n vm.checkout = checkout;\r\n vm.directCheckout = directCheckout;\r\n vm.onEditButtonClick = onEditButtonClick;\r\n vm.openPriceOverridePicker = openPriceOverridePicker;\r\n vm.openVoucherPicker = openVoucherPicker;\r\n vm.onMoveToWishlistButtonClick = onMoveToWishlistButtonClick;\r\n vm.onMoveToWishlistCancelButtonClick = onMoveToWishlistCancelButtonClick;\r\n vm.moveItemToWishlist = moveItemToWishlist;\r\n vm.toggleCouponInput = toggleCouponInput;\r\n vm.addRecommendedProduct = addRecommendedProduct;\r\n vm.addBonusItem = addBonusItem;\r\n vm.onRemoveRecommButtonClick = onRemoveRecommButtonClick;\r\n vm.selectVoucher = selectVoucher;\r\n vm.addVoucherToBasket = addVoucherToBasket;\r\n\r\n /**\r\n * @description Method to run the initialization of the basket module\r\n * @returns {void}\r\n */\r\n this.$onInit = function () {\r\n dataService.init(function() {\r\n vm.errorMessage = dataService.errorMessages();\r\n\r\n // check for invalid products\r\n dataService.productItems().forEach(function(product) {\r\n if (!product.hasOwnProperty('price') || typeof product.price !== 'number') {\r\n removeItem(product);\r\n vm.invalidProductError = true;\r\n\r\n if (product.isBonusProduct) {\r\n // prevent bonusproduct selection picker from reappearing\r\n $window.sessionStorage.setItem('jwsdw-choiceOfBonusProductPicker', 'hide');\r\n }\r\n }\r\n });\r\n\r\n if (dataService.recommendedProductItem() && !vm.recommendedProductObserver) {\r\n _initObserver(dataService.recommendedProductItem());\r\n }\r\n\r\n if (!vm.gPayLoaded && window.googlePay && dataService.applicablePaymentMethods().indexOf('GOOGLE_PAY') > -1) {\r\n $.getScript(\"https://pay.google.com/gp/p/js/pay.js\", function() {\r\n vm.gPayLoaded = true;\r\n window.googlePay.onLoaded();\r\n });\r\n }\r\n\r\n /*\r\n Logic to first show the order limit reached message as a general banner on the basket page when first landing on it,\r\n whether it's due to the reason URL param or from pdict information.\r\n */\r\n if (vm.refusalReason === undefined) {\r\n vm.refusalReason = dataService.refusalReason();\r\n }\r\n\r\n /*\r\n The general banner disappears once the order limit is not an issue anymore.\r\n If the limit is an issue again (eg. if the customer updates a product's quantity), then the order limit message is shown above the 'Checkout' button\r\n */\r\n if (vm.refusalReason === 'orderLimit' && !dataService.orderLimitReached()) {\r\n vm.refusalReason = null;\r\n\r\n if ($location.search().reason) {\r\n $location.search('reason', null).replace();\r\n }\r\n }\r\n\r\n vm.orderLimitMsg = dataService.orderLimitMsg();\r\n vm.showShippingNotification = dataService.showShippingNotification();\r\n\r\n updateProgressBar();\r\n });\r\n\r\n populateCartQuantityOptions();\r\n\r\n // listen to the 'sessionExpired' event broadcasted by the mediator\r\n $window.jwsdwMediator.subscribe('sessionExpired', function() {\r\n $anchorScroll();\r\n vm.sessionError = true;\r\n });\r\n\r\n // listen to the 'updateBasket' event broadcasted by the mediator\r\n $window.jwsdwMediator.subscribe('updateBasket', function() {\r\n dataService.init();\r\n });\r\n\r\n // listen to the 'updateBasket' event broadcasted by the mediator\r\n $window.jwsdwMediator.subscribe('updateBasketProduct', function(data) {\r\n updateProduct(data.itemId, data.initialProductId, data.variantId, data.quantity, data.product);\r\n });\r\n\r\n\r\n // listen to the 'updateBonusProduct' event broadcasted by the mediator\r\n $window.jwsdwMediator.subscribe('updateBonusProduct', function(data) {\r\n updateBonusProduct(data.itemId, data.initialProductId, data.variantId, data.product);\r\n });\r\n\r\n /* Update basket quantity dynamically */\r\n $window.jwsdwMediator.subscribe('setCartCount', function(cartQuantity) {\r\n vm.productCount = cartQuantity;\r\n });\r\n\r\n //if data service publishes a qunatity error the view model parameter is set to true as well\r\n $scope.$watch(function () {\r\n return dataService.quantityError;\r\n }, function () {\r\n vm.quantityError = dataService.quantityError;\r\n });\r\n };\r\n\r\n /**\r\n * Method that is triggered if user clicks edit button for a product.\r\n * It broadcasts the 'openPicker' event for 'variationPicker' with the product as payload.\r\n * The Listener is registered in the variationPicker.controller.js\r\n * @param {Object} product the product which should be edited\r\n * @param {Boolean} isBonus optional parameter, true if current product is of type bonus\r\n * @returns {void}\r\n */\r\n function onEditButtonClick(product, isBonus) {\r\n $window.jwsdwMediator.publish('openPicker', 'variationPicker', {\r\n 'product': product,\r\n 'dataService': dataService,\r\n 'isBonus': isBonus\r\n });\r\n }\r\n\r\n /**\r\n * @description Method to open the product remove overlay.\r\n * @param {Object} product - The product which should be removed.\r\n * @returns {undefined}\r\n */\r\n function onRemoveButtonClick(product) {\r\n product.markedForRemoval = true;\r\n }\r\n\r\n /**\r\n * @description Method to add multiple items to the basket.\r\n * @param {Object} recommendedProduct recommended product object\r\n * @returns {undefined}\r\n */\r\n function _initObserver(recommendedProduct) {\r\n $timeout(() => {\r\n let recommendationBlock;\r\n let observer = new IntersectionObserver(entries => {\r\n entries.forEach(entry => {\r\n if (entry.isIntersecting) {\r\n let sendEvent = trackAddToBasketService.sendRecommendedProductImpressions.bind(this, recommendedProduct, 1);\r\n $window.jwsdwApi.tracking.ensureConsent(sendEvent);\r\n observer.disconnect();\r\n }\r\n });\r\n }, {\r\n 'root': null,\r\n 'rootMargin': '0px',\r\n 'threshold': 1.0\r\n });\r\n\r\n recommendationBlock = document.getElementById('recommendationBlock');\r\n observer.observe(recommendationBlock);\r\n vm.recommendedProductObserver = true;\r\n });\r\n }\r\n\r\n /**\r\n * @description Method to open the product move to wishlist overlay.\r\n * @param {Object} product - The product which should be moved to the wishlist.\r\n * @returns {undefined}\r\n */\r\n function onMoveToWishlistButtonClick(product) {\r\n product.markedForWishlist = true;\r\n }\r\n\r\n /**\r\n * @description Method to close the product remove overlay.\r\n * @param {Object} product - The product whose removal overlay should be closed.\r\n * @returns {undefined}\r\n */\r\n function onRemoveCancelButtonClick(product) {\r\n product.markedForRemoval = false;\r\n }\r\n\r\n /**\r\n * @description Method to close the product move to wishlist overlay.\r\n * @param {Object} product - The product whose move to wishlist overlay should be closed.\r\n * @returns {undefined}\r\n */\r\n function onMoveToWishlistCancelButtonClick(product) {\r\n product.markedForWishlist = false;\r\n }\r\n\r\n /**\r\n * @description Method to trigger removal of a product from the basket. This method triggers the basket service.\r\n * @param {Object} product - The product which should be removed from the basket.\r\n * @param {boolean} markForRemoval - Boolean parameter to determine whether to also mark the product for removal.\r\n * @returns {void}\r\n */\r\n function removeItem(product, markForRemoval) {\r\n if (markForRemoval) {\r\n product.markedForRemoval = true;\r\n }\r\n\r\n product.removing = true;\r\n\r\n basketService.removeItem(product.basketItemId).then((basketData) => {\r\n product.removed = true;\r\n product.removing = false;\r\n $timeout(() => {\r\n product.tileHeight = angular.element(`[data-item-id=${product.basketItemId}]`).outerHeight() + 'px';\r\n product.fadeOut = true;\r\n $timeout(() => {\r\n dataService.basketSuccess(basketData);\r\n }, 1000);\r\n }, 2000);\r\n });\r\n }\r\n\r\n /**\r\n * @description Method to trigger removal of a product from the basket and its addition to the wishlist. This method triggers the basket service.\r\n * @param {Object} product - The product which should be moved to the wishlist.\r\n * @returns {undefined}\r\n */\r\n function moveItemToWishlist(product) {\r\n product.movingToWishlist = true;\r\n\r\n if (!window.jwsdwSettings.customerAuthenticated && vm.wishlistCount === vm.maxWishlistItemsForGuest) {\r\n product.movingToWishlist = false;\r\n window.jwsdwMediator.publish('openPicker', 'loginPicker', {\r\n 'showMaxGuestWishlistMessage': true,\r\n 'callback': function() {\r\n moveItemToWishlist(product);\r\n }\r\n });\r\n return;\r\n }\r\n\r\n productService.addToWishlist(product.id).then(addToWishlistSuccess, addToWishlistError);\r\n\r\n /**\r\n * @description Method on success\r\n * @param {Object} data response data\r\n * @returns {undefined}\r\n */\r\n function addToWishlistSuccess(data) {\r\n vm.wishlist.products.push({\r\n 'id': data.itemId,\r\n 'pid': data.productId,\r\n 'color': data.color\r\n });\r\n\r\n window.jwsdwMediator.publish('setWishlistCount', data.items);\r\n\r\n basketService.removeItem(product.basketItemId).then((basketData) => {\r\n product.movedToWishlist = true;\r\n product.movingToWishlist = false;\r\n $timeout(() => {\r\n product.tileHeight = angular.element(`[data-item-id=${product.basketItemId}]`).outerHeight() + 'px';\r\n product.fadeOut = true;\r\n $timeout(() => {\r\n dataService.basketSuccess(basketData);\r\n }, 1000);\r\n }, 2000);\r\n });\r\n }\r\n\r\n /**\r\n * @description Method on error\r\n * @returns {undefined}\r\n */\r\n function addToWishlistError() {\r\n product.movingToWishlist = false;\r\n }\r\n }\r\n\r\n /**\r\n * @description Method to trigger update of a product quantity in the basket.\r\n * This method checks if the new quantity is valid and then triggers the basket service.\r\n * @param {Object} product - The basket product for which the quantity should be updated.\r\n * @returns {undefined}\r\n */\r\n function updateQuantity(product) {\r\n if (dataService.checkValidQuantity(product.basketItemId, product.quantity, product.stock)) {\r\n _refreshProductView(\r\n product,\r\n basketService\r\n .updateQuantity(product.basketItemId, product.quantity)\r\n .then(dataService.basketSuccess)\r\n );\r\n }\r\n }\r\n\r\n /**\r\n * @description Method to update a product via the variation picker using the basketService. The method checks if the product changed\r\n * and then adds the new product to the basket and then removes the old one.\r\n * @param {String} itemId itemId\r\n * @param {String} initialProductId initialProductId\r\n * @param {String} variantId Id of the variant that should replace the old product\r\n * @param {Number} quantity quantity for the product. This is the same if enough stock is available for the\r\n * new variant otherwise the maximum stock will be used.\r\n * @param {Object} product the product object of the new variant\r\n * @returns {void}\r\n */\r\n function updateProduct(itemId, initialProductId, variantId, quantity, product) {\r\n if (initialProductId !== variantId) {\r\n basketService.addItem(variantId, quantity, product).then(function() {\r\n _refreshBasketView(\r\n basketService\r\n .removeItem(itemId)\r\n .then(dataService.basketSuccess)\r\n );\r\n });\r\n }\r\n }\r\n\r\n /**\r\n * @description Method to update a bonus product via the variation picker using the basketService. The method checks if the product changed\r\n * and then adds the new product to the basket and then removes the old one.\r\n * @param {String} itemId itemId\r\n * @param {String} initialProductId initialProductId\r\n * @param {String} variantId Id of the variant that should replace the old product\r\n * @param {Object} product the product object of the new variant\r\n * @returns {void}\r\n */\r\n function updateBonusProduct(itemId, initialProductId, variantId, product) {\r\n if (initialProductId !== variantId) {\r\n basketService.removeItem(itemId).then(function() {\r\n _refreshBasketView(\r\n basketService\r\n .addBonusItem(variantId, product)\r\n .then(dataService.basketSuccess)\r\n );\r\n });\r\n }\r\n }\r\n\r\n /**\r\n * @description Method to add a recommended product to basket\r\n * @param {String} productID productID\r\n * @param {String} quantity quantity\r\n * @param {Object} product product\r\n * @returns {void}\r\n */\r\n function addRecommendedProduct(productID, quantity, product) {\r\n _refreshBasketView(\r\n basketService\r\n .addItem(productID, quantity, product, true)\r\n .then(dataService.basketSuccess)\r\n );\r\n vm.recommendedProductDismissed = true;\r\n }\r\n\r\n /**\r\n * @description Method to add a bonus product to basket\r\n * @param {String} productID productID\r\n * @param {Object} product product\r\n * @returns {void}\r\n */\r\n function addBonusItem(productID, product) {\r\n _refreshBasketView(\r\n basketService\r\n .addBonusItem(productID, product)\r\n .then(dataService.basketSuccess)\r\n );\r\n vm.isRemovedBonusProduct = false;\r\n }\r\n\r\n /**\r\n * @description Method to remove a recommended product block\r\n * @returns {void}\r\n */\r\n function onRemoveRecommButtonClick() {\r\n vm.recommendedProductDismissed = true;\r\n }\r\n\r\n /**\r\n * @description Method to add a coupon to the basket using the basketService.\r\n * The logic first tries to add the coupon as entered by the user.\r\n * If the request fails it retries with uppercase and lowercase variants of the coupon.\r\n * @returns {void}\r\n */\r\n function addCoupon() {\r\n // logic tries the coupon code as it was entered by the user\r\n // if no matching code can be found tries uppercase and lowercase versions of the code\r\n // if still no code is found an error message is displayed\r\n\r\n // frontend validation\r\n if (!$('.jwsdw-basket-couponArea-form').valid()) {\r\n return;\r\n }\r\n\r\n _refreshBasketView(\r\n basketService\r\n .addCoupon(vm.couponCode)\r\n .then(couponSuccess, couponError)\r\n );\r\n }\r\n\r\n /**\r\n * @description Method to handle successful responses from the add coupon code function.\r\n * It handles if and how coupons are displayed in the basket and shows errors otherwise.\r\n * Cases:\r\n * valid and applied - coupon is displayed as applied\r\n * valid and not applied - coupon is displayed as not applied\r\n * not valid - error no coupon is displayed, error message coupon not found\r\n * @param {Object} basketData current basket data\r\n * @returns {void}\r\n */\r\n function couponSuccess(basketData) {\r\n var couponItem;\r\n\r\n dataService.basketSuccess(basketData);\r\n couponItem = dataService.couponItems()\r\n .concat(dataService.couponGiftCertificateItems())\r\n .find(function(coupon) {\r\n return coupon.code.toUpperCase() === vm.couponCode.toUpperCase();\r\n });\r\n\r\n //check the status of the received coupon\r\n if (couponItem && couponItem.valid) {\r\n vm.couponCode = '';\r\n }\r\n }\r\n\r\n /**\r\n * @description Method to handle unsuccessful responses for coupon code calls.\r\n * @param {Object} errorData current error data\r\n * @returns {void}\r\n */\r\n function couponError(errorData) {\r\n $('.jwsdw-basket-couponArea-form').validate().showErrors({\r\n \"basketCouponCode\": errorData.details.message\r\n });\r\n }\r\n\r\n /**\r\n * @description Method to remove a coupon from the basket using the basketService.\r\n * @param {String} couponId id of the coupon that should be removed\r\n * @returns {void}\r\n */\r\n function removeCoupon(couponId) {\r\n _refreshBasketView(\r\n basketService\r\n .removeCoupon(couponId)\r\n .then(dataService.basketSuccess)\r\n );\r\n }\r\n\r\n /**\r\n * @description Method to remove a coupon from the basket using the basketService.\r\n * @param {String} couponCode coupon code that should be removed\r\n * @returns {void}\r\n */\r\n function removeBonusCoupon(couponCode) {\r\n _refreshBasketView(\r\n basketService\r\n .removeBonusCoupon(couponCode)\r\n .then(dataService.basketSuccess)\r\n );\r\n }\r\n\r\n /**\r\n * @description Method to open the price override picker. It calculates the adjusted product pice without previous manual adjustments.\r\n * @param {Object} product the product which should be edited\r\n * @returns {void}\r\n */\r\n function openPriceOverridePicker(product) {\r\n var regex = new RegExp('\\\\d{5,7}-\\\\d-' + product.id),\r\n adjustmentTotal = 0,\r\n manualAdjustments = product.priceAdjustments.filter(function (priceAdjustment) {\r\n $log.info('regexp: ' + regex.toString());\r\n $log.info('adjustment: ' + priceAdjustment.promotionId);\r\n $log.info('adjustment matches: ' + regex.test(priceAdjustment.promotionId));\r\n return regex.test(priceAdjustment.promotionId);\r\n });\r\n\r\n manualAdjustments.forEach(function (manualAdjustment) {\r\n adjustmentTotal = adjustmentTotal + (manualAdjustment.price * -1);\r\n });\r\n\r\n window.jwsdwMediator.publish('openPicker', 'priceOverridePicker', {\r\n 'productId': product.id,\r\n 'oldPrice': adjustmentTotal > 0 ? product.priceAfterItemDiscount + adjustmentTotal : product.priceAfterItemDiscount\r\n });\r\n }\r\n\r\n\r\n /**\r\n * Method open info picker with Checkout-redeem-coupons content\r\n * @returns {void}\r\n */\r\n function openVoucherPicker() {\r\n contentService.getContent('Checkout-redeem-coupons').then(success, error);\r\n\r\n /**\r\n * Method called on success\r\n * @param {Object} response response object\r\n * @returns {void}\r\n */\r\n function success(response) {\r\n $window.jwsdwMediator.publish('openPicker', 'infoPicker', {\r\n 'width': 1,\r\n 'content': response.content,\r\n 'isVisible': true,\r\n 'level': 2\r\n });\r\n }\r\n\r\n /**\r\n * Method called on error\r\n * @param {Object} err error object\r\n * @returns {void}\r\n */\r\n function error(err) {\r\n $log.error('Could not fetch content asset \"Checkout-redeem-coupons\"', err);\r\n }\r\n }\r\n\r\n /**\r\n * @description Method to toggle the bonus product.\r\n * This method is currently not in use since demandware has no internal logic to remove bonus products from basket.\r\n * @returns {void}\r\n */\r\n function toggleBonusProduct() {\r\n vm.bonusProductActive = !vm.bonusProductActive;\r\n }\r\n\r\n /**\r\n * @description Method to validate the basket and if validation is successful direct the customer to the checkout.\r\n * @returns {void}\r\n */\r\n function checkout() {\r\n vm.proceedingToCheckout = true;\r\n basketService.prepareCheckout()\r\n .then(function () {\r\n if (!basketService.checkout()) {\r\n vm.proceedingToCheckout = false;\r\n }\r\n\r\n })\r\n .catch(function (validationResult) {\r\n $log.debug('validation error: ', validationResult);\r\n basketService.getBasket(BASKET_ID).then(dataService.basketSuccess);\r\n vm.proceedingToCheckout = false;\r\n });\r\n }\r\n\r\n /**\r\n * @description Method to validate the basket and if validation is successful direct the customer to the direct checkout (PayPal Express).\r\n * @returns {void}\r\n */\r\n function directCheckout() {\r\n vm.proceedingToDirectCheckout = true;\r\n basketService.prepareCheckout().then(function (validationResult) {\r\n if (!validationResult.error) {\r\n basketService.directCheckout();\r\n } else {\r\n $log.debug('validation error: ', validationResult.errorType);\r\n basketService.getBasket(BASKET_ID).then(dataService.basketSuccess);\r\n vm.proceedingToDirectCheckout = false;\r\n }\r\n });\r\n }\r\n\r\n /**\r\n * @description Method to refresh a product view that is about to suffer changes.\r\n * @param {Object} product - The current product whose view should be refreshed.\r\n * @param {Promise} promise - A promise returned by a product update function.\r\n * @returns {Promise} a new promise.\r\n */\r\n function _refreshProductView(product, promise) {\r\n return new Promise((resolve) => {\r\n product.updating = true;\r\n promise.then(() => product.updating = false && resolve());\r\n });\r\n }\r\n\r\n /**\r\n * @description Method to refresh certain parts of the basket view that are about to suffer changes.\r\n * @param {Promise} promise - A promise returned by an update function.\r\n * @returns {Promise} a new promise.\r\n */\r\n function _refreshBasketView(promise) {\r\n const refreshPromise = new Promise((resolve) => {\r\n $timeout(function() {\r\n $scope.$apply(function() {\r\n vm.updating = true;\r\n promise.finally(() => vm.updating = false && resolve());\r\n });\r\n });\r\n });\r\n\r\n return refreshPromise;\r\n }\r\n\r\n /**\r\n * @description Method to populate the quantity selector options based on site preference.\r\n * @returns {undefined}\r\n */\r\n function populateCartQuantityOptions() {\r\n let i = 1;\r\n\r\n if (vm.maxCartQuantityPerItem <= i) {\r\n vm.quantityOptions = [i];\r\n return;\r\n }\r\n\r\n while (i <= vm.maxCartQuantityPerItem) {\r\n vm.quantityOptions.push(i);\r\n i++;\r\n }\r\n }\r\n\r\n /**\r\n * @description Method to reveal/hide coupon input.\r\n * @returns {undefined}\r\n */\r\n function toggleCouponInput() {\r\n vm.couponInputRevealed = !vm.couponInputRevealed;\r\n }\r\n\r\n /**\r\n * @description Method to update free shipping progress bar\r\n * @returns {undefined}\r\n */\r\n function updateProgressBar() {\r\n $timeout(function() {\r\n $scope.$apply(function() {\r\n $(document).find('.jwsdw-basket-progressBar-content').css('width', (100 - dataService.freeShippingPercentage()) + '%');\r\n });\r\n });\r\n }\r\n\r\n /**\r\n * @description Method to select voucher.\r\n * @param {Object} voucher current selected voucher\r\n * @returns {undefined}\r\n */\r\n function selectVoucher(voucher) {\r\n vm.selectedVoucher = voucher;\r\n }\r\n\r\n /**\r\n * @description Method to add the voucher to basket.\r\n * @param {Object} voucher current selected voucher\r\n * @returns {undefined}\r\n */\r\n function addVoucherToBasket(voucher) {\r\n // logic tries the voucher id as it was entered by the user\r\n // if no matching code can be found tries uppercase and lowercase versions of the code\r\n // if still no code is found an error message is displayed\r\n\r\n _refreshBasketView(\r\n basketService\r\n .addVoucher(voucher)\r\n .then(couponSuccess, voucherError)\r\n );\r\n }\r\n\r\n /**\r\n * @descropion Method to handle error responses from the add voucher function.\r\n * @param {Object} errorData - Error data from the endpoint.\r\n * @returns {undefined}\r\n */\r\n function voucherError(errorData) {\r\n $log.debug('Cart-AddVoucher error:', errorData);\r\n }\r\n\r\n /**\r\n * @description Method to trigger update voucher section in the basket.\r\n * @param {Object} voucherData - The activated voucher object.\r\n * @returns {Promise} A new promise for tracking the update process.\r\n */\r\n function updateVoucherSection(voucherData) {\r\n vm.voucherSectionUpdating = true;\r\n $timeout(function() {\r\n $scope.$apply(function() {\r\n dataService.voucherDataSuccess({'data': voucherData});\r\n vm.voucherSectionUpdating = false;\r\n });\r\n });\r\n }\r\n\r\n $window.jwsdwMediator.subscribe('updateVoucherSection', function(data) {\r\n let updatedVoucherData = dataService.updateVoucherData(data);\r\n updateVoucherSection(updatedVoucherData);\r\n });\r\n }\r\n}(angular));\r\n","'use strict';\r\n\r\n(function (angular) {\r\n dataService.$inject = ['$window', '$q', '$log', '$sce', '$timeout', 'basketService', 'productService', 'promotionService', 'BASKET_ID'];\r\n angular\r\n .module('jwsdw.basket')\r\n .factory('dataService', dataService);\r\n\r\n /**\r\n * @class jwsdwBasket.dataService\r\n * @description Service that provides access to the data layer of the basket\r\n * @param {Object} $window window service that provides access to the window object\r\n * @param {Object} $q promise service that provides promise functionality\r\n * @param {Object} $log log service that provides logging in angluar\r\n * @param {Object} $sce angular santize service\r\n * @param {Object} $timeout angular timeout service\r\n * @param {Object} basketService service to provide basket information\r\n * @param {Object} productService service to provide product information (used for creation of variants item)\r\n * @param {Object} promotionService service to provide promotion information\r\n * @param {String} BASKET_ID basket id of the current basket provided through demandware backend (window.jwsdwSettings) and loaded into the module as constant\r\n * @returns {Object} service object that returns public methods\r\n */\r\n function dataService($window, $q, $log, $sce, $timeout, basketService, productService, promotionService, BASKET_ID) { // eslint-disable-line max-statements\r\n var service,\r\n _ready = false,\r\n _voucherDataReady = false,\r\n _voucherSectionTransition = false,\r\n _voucherRetrievalFailed = false,\r\n _callback,\r\n _basketData,\r\n _voucherData,\r\n _totalOrderPriceAdjustment,\r\n _quantityErrors = {};\r\n\r\n //public methods\r\n service = {\r\n 'quantityError': false,\r\n 'init': init,\r\n 'ready': ready,\r\n 'voucherDataReady': voucherDataReady,\r\n 'voucherSectionTransition': voucherSectionTransition,\r\n 'voucherRetrievalFailed': voucherRetrievalFailed,\r\n 'empty': empty,\r\n 'update': update,\r\n 'basketSuccess': basketSuccess,\r\n 'voucherDataSuccess': voucherDataSuccess,\r\n 'voucherDataError': voucherDataError,\r\n 'orderTotal': orderTotal,\r\n 'merchandizeTotalGrossPrice': merchandizeTotalGrossPrice,\r\n 'adjustedMerchandizeTotalPrice': adjustedMerchandizeTotalPrice,\r\n 'shippingTotal': shippingTotal,\r\n 'totalOrderPriceAdjustment': totalOrderPriceAdjustment,\r\n 'productLevelPriceAdjustments': productLevelPriceAdjustments,\r\n 'orderCouponPriceAdjustments': orderCouponPriceAdjustments,\r\n 'orderPriceAdjustments': orderPriceAdjustments,\r\n 'productItems': productItems,\r\n 'couponItems': couponItems,\r\n 'couponGiftCertificateItems': couponGiftCertificateItems,\r\n 'loyaltyCouponItems': loyaltyCouponItems,\r\n 'giftCardItems': giftCardItems,\r\n 'isReducedProduct': isReducedProduct,\r\n 'isTaxIncluded': isTaxIncluded,\r\n 'getTaxRate': getTaxRate,\r\n 'isMixedTaxRate': isMixedTaxRate,\r\n 'hasItemDiscount': hasItemDiscount,\r\n 'productQuantity': productQuantity,\r\n 'checkValidQuantity': checkValidQuantity,\r\n 'freeShippingAmount': freeShippingAmount,\r\n 'freeShippingPercentage': freeShippingPercentage,\r\n 'isChoiceOfBonusProductLineItem': isChoiceOfBonusProductLineItem,\r\n 'applicablePaymentMethods': applicablePaymentMethods,\r\n 'isLoyaltyCustomer': isLoyaltyCustomer,\r\n 'isLoyaltyCustomerForCurrentCountry': isLoyaltyCustomerForCurrentCountry,\r\n 'isEmployeeAccount': isEmployeeAccount,\r\n 'isCallawayAccount': isCallawayAccount,\r\n 'isFranchiseStore': isFranchiseStore,\r\n 'sessionCurrency': sessionCurrency,\r\n 'agent': agent,\r\n 'isCustomerLoggedIn': isCustomerLoggedIn,\r\n 'getOriginalOrderTotal': getOriginalOrderTotal,\r\n 'errorMessages': errorMessages,\r\n 'recommendedProductItem': recommendedProductItem,\r\n 'promotionTotal': promotionTotal,\r\n 'orderLimitReached': orderLimitReached,\r\n 'refusalReason': refusalReason,\r\n 'orderLimitMsg': orderLimitMsg,\r\n 'showShippingNotification': showShippingNotification,\r\n 'selectableBonusProductsList': selectableBonusProducts,\r\n 'allBonusProductVariants': allBonusProductVariants,\r\n 'hasBonusDiscountLineItem': hasBonusDiscountLineItem,\r\n 'hideBonusProductImage': hideBonusProductImage,\r\n 'maxBonusProducts': maxBonusProducts,\r\n 'isRemovedBonusProduct': isRemovedBonusProduct,\r\n 'defaultSelectableBonusProduct': defaultSelectableBonusProduct,\r\n 'selectedBonusProductLineItems': selectedBonusProductLineItems,\r\n 'outOfStockBonus': outOfStockBonus,\r\n 'hasPriceAdjustments': hasPriceAdjustments,\r\n 'approachingDiscounts': approachingDiscounts,\r\n 'hasVouchersAvailable': hasVouchersAvailable,\r\n 'hasVouchersActivated': hasVouchersActivated,\r\n 'activatedVouchers': activatedVouchers,\r\n 'eligibleVouchers': eligibleVouchers,\r\n 'basketVouchers': basketVouchers,\r\n 'openSelectVoucherPicker': openSelectVoucherPicker,\r\n 'updateVoucherData': updateVoucherData\r\n };\r\n\r\n // expose selected methods\r\n window.basketService = {\r\n 'init': init,\r\n 'orderTotal': orderTotal,\r\n 'shippingTotal': shippingTotal,\r\n 'taxTotal': taxTotal,\r\n 'applicableCreditCards': applicableCreditCards\r\n };\r\n\r\n return service;\r\n\r\n /**\r\n * @description Method to start initialization process to retrieve basket information\r\n * @param {Function} callback callback function\r\n * @returns {void}\r\n */\r\n function init(callback) {\r\n _ready = false;\r\n _callback = callback;\r\n basketService.getBasket(BASKET_ID)\r\n .then(basketSuccess, basketError)\r\n .then(() => {\r\n /* Do not remove setTimeout!!\r\n It is essential, otherwise the browser tab is stuck in a loading state until the request finishes execution. This loading state blocks image loading. */\r\n setTimeout(() => {\r\n if (isLoyaltyCustomerForCurrentCountry()) {\r\n basketService.getLoyaltyVouchers().then(voucherDataSuccess, voucherDataError);\r\n }\r\n });\r\n });\r\n }\r\n\r\n /**\r\n * @description Method to handle successful loyalty voucher data response information.\r\n * @param {Object} voucherData parsed voucher data returned by the loyalty voucher service\r\n * @returns {Promise} a promise to be resolved.\r\n */\r\n function voucherDataSuccess(voucherData) {\r\n\r\n _voucherData = voucherData ? voucherData.data : null;\r\n _voucherDataReady = true;\r\n $timeout(() => {\r\n _voucherSectionTransition = true;\r\n }, 0);\r\n\r\n }\r\n\r\n /**\r\n * @description Method to handle successful basket response by using product items to retrieve further product information.\r\n * @param {Object} basketData parsed basket data returned by the basket service\r\n * @returns {Promise} a promise to be resolved.\r\n */\r\n function basketSuccess(basketData) {\r\n var defer = $q.defer(),\r\n productIds = basketData.products\r\n .map(function(product) {\r\n return product.id;\r\n })\r\n .filter(window.jwsdwUtil.arrayUtils.unique());\r\n\r\n\r\n _basketData = basketData;\r\n\r\n $window.jwsdwSettings.basket.id = _basketData.id;\r\n\r\n $log.debug('jwsdw.basket.dataService: Using following data to built the page: ', _basketData);\r\n productService.getProducts(productIds).then(_productDataSuccess, _productDataError).then(() => defer.resolve());\r\n\r\n return defer.promise;\r\n }\r\n\r\n /**\r\n * @description Method to handle error from getVoucher response.\r\n * @returns {void}\r\n */\r\n function voucherDataError() {\r\n _voucherRetrievalFailed = true;\r\n }\r\n\r\n /**\r\n * @description Method to handle error from basket response by using product items to retrieve further product information.\r\n * @param {Object} error error object\r\n * @returns {void}\r\n */\r\n function basketError(error) {\r\n _basketData = {\r\n 'empty': true\r\n };\r\n $log.debug('jwsdw.basket.dataService: No basket could be loaded: ', BASKET_ID, error);\r\n _ready = true;\r\n if (typeof _callback === 'function') {\r\n _callback();\r\n }\r\n }\r\n\r\n /**\r\n * @description Method to handle successful product request and trigger further update logic.\r\n * @param {Object} productData parsed product data returned by the product service\r\n * @returns {Promise} a promise to be resolved.\r\n * @private\r\n */\r\n function _productDataSuccess(productData) {\r\n var defer = $q.defer();\r\n $log.debug('jwsdw.basket.dataService: Using following product data: ', productData);\r\n update().then(function() {\r\n _checkValidQuantities();\r\n _calculateTotalListPricesForSaleProducts();\r\n _ready = true;\r\n if (typeof _callback === 'function') {\r\n _callback();\r\n }\r\n defer.resolve();\r\n });\r\n\r\n return defer.promise;\r\n }\r\n\r\n /**\r\n * @description Method to handle product data errors. This method is triggered if the product data does not\r\n * contain data for all products that were requested. This is used to handle deleted products.\r\n * @param {String[]} unavailableProductIds product ids for which no data was retrieved\r\n * @returns {void}\r\n * @private\r\n */\r\n function _productDataError(unavailableProductIds) {\r\n /*\r\n * this construct allows the sequential processing of promises.\r\n * This is neccessary since products that are not available anymore are deleted from the basket.\r\n * This changes the state of the basket. Asynchronous processing of multiple remove calls creates\r\n * a state problem where operations are done on outdated basket objects.\r\n * The array.reduce function allows to process each product id separately.\r\n * This works by setting the current value which is passed through every reduce callback to promise\r\n * and resolve it inside the callback. This creates a state were the next reduce iteration waits until the previous\r\n * iteration finishes and resolves the current value.\r\n */\r\n unavailableProductIds.reduce(_recheckAndDeleteUnavailableProducts, $q.resolve()).then(init);\r\n }\r\n\r\n /**\r\n * Method that is called with every iteration of the reduce function. It checks if the product is in the basket and then\r\n * rechecks if the product data cannot be retrieved and removes the product from the basket in this case.\r\n * @param {Object} defer promise that is resolve with every successful iteration through the reduce\r\n * function to ensure sequential processing\r\n * @param {String} productId the product id which is rechecked for availability\r\n * @returns {Object} promise that is resolved after successful processing of the function\r\n * @private\r\n */\r\n function _recheckAndDeleteUnavailableProducts(defer, productId) {\r\n var product = productItems().find(function (productItem) {\r\n return productItem.id === productId;\r\n });\r\n if (product) {\r\n return defer.then(function () {\r\n return productService.getProduct(product.id).catch(function () {\r\n return basketService.removeItem(product.basketItemId);\r\n });\r\n });\r\n }\r\n return defer;\r\n }\r\n\r\n /**\r\n * @description Method to update values and broadcast new values for the basket resource.\r\n * @returns {Object} promise that resolves if all update operations were successful\r\n */\r\n function update() {\r\n var defer = $q.defer(),\r\n promises = [];\r\n\r\n _totalOrderPriceAdjustment = _getTotalOrderPriceAdjustment();\r\n $window.jwsdwMediator.publish('setCartCount', _basketData.cartQuantity);\r\n\r\n\r\n promises.push(_extendOrderPriceAdjustmentsWithPromotionData());\r\n promises.push(_extendBasketProductsWithProductData());\r\n promises.push(_updateProductAvailabilityData());\r\n\r\n $q.all(promises).then(function () {\r\n defer.resolve();\r\n });\r\n\r\n return defer.promise;\r\n }\r\n\r\n\r\n /**\r\n * @description Method to update voucher section\r\n * @param {Object} data activated voucher data\r\n * @returns {Object} voucher data object\r\n */\r\n function updateVoucherData(data) {\r\n _voucherData.hasVouchersActivated = true;\r\n\r\n if (data && data.voucherData && data.voucherData.Emarsys_voucher_Info) {\r\n _voucherData.activatedVouchers.push(data.voucherData.Emarsys_voucher_Info);\r\n }\r\n\r\n return _voucherData;\r\n }\r\n\r\n /**\r\n * @description Method to open selectVoucherPicker\r\n * @returns {void}\r\n */\r\n function openSelectVoucherPicker() {\r\n let eligibleVouchersArray = eligibleVouchers();\r\n window.jwsdwMediator.publish('openPicker', 'selectVoucherPicker',\r\n {\r\n 'eligibleVouchersArray': eligibleVouchersArray,\r\n 'ajaxSource': 'basket'\r\n });\r\n }\r\n\r\n /**\r\n * @description Method to get the ready state of the basket.\r\n * @returns {Boolean} true if basket data is ready false otherwise\r\n */\r\n function ready() {\r\n return _ready;\r\n }\r\n\r\n /**\r\n * @description Method to get the ready state of the voucher data.\r\n * @returns {Boolean} true if loyalty voucher data was successfully retrieved.\r\n */\r\n function voucherDataReady() {\r\n return _voucherDataReady;\r\n }\r\n\r\n /**\r\n * @description Method to get the ready state of the voucher section transition.\r\n * @returns {Boolean} true if basket data is ready false otherwise\r\n */\r\n function voucherSectionTransition() {\r\n return _voucherSectionTransition;\r\n }\r\n\r\n /**\r\n * @description Method to determine whether loyalty voucher information retrieval failed.\r\n * @returns {Boolean} true if loyalty voucher information retrieval failed.\r\n */\r\n function voucherRetrievalFailed() {\r\n return _voucherRetrievalFailed;\r\n }\r\n\r\n /**\r\n * @description Method to get the empty state of the basket.\r\n * @returns {Boolean} true if basket is empty false otherwise\r\n */\r\n function empty() {\r\n return _basketData.empty;\r\n }\r\n\r\n /**\r\n * @description Method to get the order total from the basket data.\r\n * @returns {Number} the total order price\r\n */\r\n function orderTotal() {\r\n return _basketData.orderTotal;\r\n }\r\n\r\n /**\r\n * @description Method to get the error messages from the basket data.\r\n * @returns {String} the error message\r\n */\r\n function errorMessages() {\r\n return _basketData.errorMessages;\r\n }\r\n /**\r\n * @description Method to get the order total from the basket data.\r\n * @returns {Number} the total order price\r\n */\r\n function merchandizeTotalGrossPrice() {\r\n return _basketData.merchandizeTotalGrossPrice;\r\n }\r\n\r\n /**\r\n * @description Method to get the adjusted merchandize total from the basket data.\r\n * @returns {Number} the total order price\r\n */\r\n function adjustedMerchandizeTotalPrice() {\r\n return _basketData.adjustedMerchandizeTotalPrice;\r\n }\r\n\r\n /**\r\n * @description Method to get the shipping total from the basket data.\r\n * @returns {Number} the total order shipping price\r\n */\r\n function shippingTotal() {\r\n return _basketData.shippingTotal;\r\n }\r\n\r\n\r\n /**\r\n * @description Method to get coupon-based order price adjustments from the basket data.\r\n * @returns {String[]} array of order price adjustments\r\n */\r\n function orderCouponPriceAdjustments() {\r\n return _basketData.orderCouponPriceAdjustments;\r\n }\r\n\r\n /**\r\n * @description Method to get order non-coupon-based price adjustments from the basket data.\r\n * @returns {String[]} array of order price adjustments\r\n */\r\n function orderPriceAdjustments() {\r\n return _basketData.orderPriceAdjustments;\r\n }\r\n\r\n /**\r\n * @description Method to get the total order price adjustment from the basket data.\r\n * @returns {Number} total order price adjustment\r\n */\r\n function totalOrderPriceAdjustment() {\r\n return _totalOrderPriceAdjustment;\r\n }\r\n\r\n /**\r\n * @description Method to get the total product level price adjustments.\r\n * @returns {Object} a map of total product level price adjustments.\r\n */\r\n function productLevelPriceAdjustments() {\r\n return _basketData.productLevelPriceAdjustments;\r\n }\r\n\r\n /**\r\n * @description Method to get the product items from the basket data.\r\n * @returns {Object[]} array of product items\r\n */\r\n function productItems() {\r\n return _basketData.products;\r\n }\r\n\r\n /**\r\n * @description Method to get the recommended product items from the basket data.\r\n * @returns {Object[]} array of product items\r\n */\r\n function recommendedProductItem() {\r\n return _basketData.recommendedProduct;\r\n }\r\n\r\n /**\r\n * @description Method to get the selectable bonus product items from the basket data.\r\n * @returns {String[]} array of product ids\r\n */\r\n function selectableBonusProducts() {\r\n return _basketData.selectableBonusProducts;\r\n }\r\n\r\n /**\r\n * @description Method to check if the basket has a bonus line item discount.\r\n * @returns {Boolean} true if there is a bonus line item currently in basket\r\n */\r\n function hasBonusDiscountLineItem() {\r\n return _basketData.hasBonusDiscountLineItem;\r\n }\r\n\r\n /**\r\n * @description Method to check whether to hide the product image in the bonus product banner.\r\n * @returns {Boolean} true if the product image in the bonus promo banner should be hidden.\r\n */\r\n function hideBonusProductImage() {\r\n return _basketData.hideBonusProductImage;\r\n }\r\n\r\n /**\r\n * @description Method to get the max number of bonus products from the basket data.\r\n * @returns {Number} maximum number of bonus products that can be added in basket\r\n */\r\n function maxBonusProducts() {\r\n return _basketData.maxBonusProducts;\r\n }\r\n\r\n /**\r\n * @description Method to display banner if all bonus products are out of stock\r\n * @returns {Boolean} true if all bonus product variants are out of stock\r\n */\r\n function outOfStockBonus() {\r\n return _basketData.outOfStockBonus;\r\n }\r\n\r\n /**\r\n * @description Method to get the coupon items from the basket data.\r\n * @returns {Object[]} array of coupon items\r\n */\r\n function couponItems() {\r\n return _basketData.coupons;\r\n }\r\n\r\n /**\r\n * @description Method to get the loyalty coupon items from the basket data.\r\n * @returns {Object[]} array of loyalty coupon items\r\n */\r\n function couponGiftCertificateItems() {\r\n return _basketData.couponGiftCertificates;\r\n }\r\n\r\n /**\r\n * @description Method to get the gift card items from the basket data.\r\n * @returns {Object[]} array of gift card items\r\n */\r\n function giftCardItems() {\r\n return _basketData.giftCards;\r\n }\r\n\r\n /**\r\n * @description Method to get the quantity of a basket product item\r\n * @param {String} basketItemId id of the basket product item (not product id)\r\n * @returns {Number} qunatity of the requested basket item\r\n */\r\n function productQuantity(basketItemId) {\r\n let basketItem = productItems().find(function(product) {\r\n return product.basketItemId === basketItemId;\r\n });\r\n\r\n return basketItem ? basketItem.quantity : 0;\r\n }\r\n\r\n /**\r\n * @description Method to check if a product is reduced through sale price or item price adjustments.\r\n * TODO check if in use\r\n * @param {Object} product product that is checked for reductions\r\n * @param {Boolean} product.isBonusProduct true if product is bonus product\r\n * @param {Number} product.price price\r\n * @param {Number} product.priceAfterItemDiscount price after applied discounts\r\n * @returns {Boolean} true if product is reduced false otherwise\r\n */\r\n function isReducedProduct(product) {\r\n return !product.isBonusProduct && (hasItemDiscount(product) || productService.isSaleProduct(product));\r\n }\r\n\r\n /**\r\n * @description Method to check if tax is included in the total price\r\n * @returns {Boolean} true if tax is included\r\n */\r\n function isTaxIncluded() {\r\n return productItems().some(function(pli) {\r\n return pli.taxRate > 0;\r\n });\r\n }\r\n\r\n /**\r\n * @description Method to get tax rate\r\n * @returns {Number|Null} tax rate of basket or null\r\n */\r\n function getTaxRate() {\r\n if (isTaxIncluded() && !isMixedTaxRate()) {\r\n return productItems()[0].taxRate;\r\n }\r\n return null;\r\n }\r\n\r\n /**\r\n * @description Method to check if tax rates are mixed\r\n * @returns {Boolean} true if tax is mixed\r\n */\r\n function isMixedTaxRate() {\r\n return productItems().filter(window.jwsdwUtil.arrayUtils.unique('taxRate')).length > 1;\r\n }\r\n\r\n /**\r\n * @description Method to check if tax is included in the total price\r\n * @returns {Boolean} true if tax is included\r\n */\r\n function taxTotal() {\r\n return _basketData.taxTotal;\r\n }\r\n\r\n /**\r\n * @description Method to check if the bonus product has been removed from basket\r\n * @returns {Boolean} true if bonus product was removed\r\n */\r\n function isRemovedBonusProduct() {\r\n return _basketData.isRemovedBonusProduct;\r\n }\r\n\r\n /**\r\n * @description Method to return default bonus product to be displayed in basket\r\n * @returns {Object} default selectable bonus product\r\n */\r\n function defaultSelectableBonusProduct() {\r\n return _basketData.defaultSelectableBonusProduct;\r\n }\r\n\r\n /**\r\n * @description Method to return currently selected bonus product line items\r\n * @returns {Object[]} currently selected bonus product line items\r\n */\r\n function selectedBonusProductLineItems() {\r\n return _basketData.selectedBonusProductLineItems;\r\n }\r\n\r\n /**\r\n * @description Method to return all variants for a bonus product\r\n * @returns {Object[]} currently selected bonus product variants\r\n */\r\n function allBonusProductVariants() {\r\n return _basketData.allBonusProductVariants;\r\n }\r\n\r\n /**\r\n * @description Method to check if product has an item price adjustment.\r\n * @param {Object} product product that is checked for discount\r\n * @param {Number} product.price price\r\n * @param {Number} product.priceAfterItemDiscount price after applied discounts\r\n * @returns {Boolean} true if product has item price adjustments\r\n */\r\n function hasItemDiscount(product) {\r\n return product.priceAfterItemDiscount < product.price;\r\n }\r\n\r\n /**\r\n * @description Method to get the free shipping amount from the basket data.\r\n * @returns {Number} amount needed to get free shipping\r\n */\r\n function freeShippingAmount () {\r\n return _basketData.freeShippingAmount;\r\n }\r\n\r\n /**\r\n * @description Method to get the free shipping amount from the basket data.\r\n * @returns {Number} amount needed to get free shipping\r\n */\r\n function freeShippingPercentage () {\r\n return _basketData.freeShippingPercentage;\r\n }\r\n\r\n /**\r\n * @description Method to calculate the total order price adjustment value for the basket data.\r\n * @returns {Number} total order price adjustment\r\n * @private\r\n */\r\n function _getTotalOrderPriceAdjustment() {\r\n var totalDiscount = 0,\r\n discountsLength = _basketData.orderPriceAdjustments.length,\r\n i;\r\n\r\n for (i = 0; i < discountsLength; i++) {\r\n totalDiscount = totalDiscount + _basketData.orderPriceAdjustments[i].price;\r\n }\r\n\r\n return totalDiscount;\r\n }\r\n\r\n /**\r\n * @description Method to check if object of price adjustments is empty\r\n * @param {Object} priceAdjustment object to check\r\n * @returns {Number} returns number of entries in object\r\n */\r\n function hasPriceAdjustments(priceAdjustment) {\r\n return Object.keys(priceAdjustment).length;\r\n }\r\n\r\n /**\r\n * @description Method to check if bonus product is a selected choice of bonus product line item\r\n * @param {String} productId id of the product to check\r\n * @returns {Boolean} true if bonus product is selected choice of bonus product line item false otherwise\r\n */\r\n function isChoiceOfBonusProductLineItem(productId) {\r\n if (_basketData.hasOwnProperty('selectedBonusProducts') && angular.isArray(_basketData.selectedBonusProducts)) {\r\n return _basketData.selectedBonusProducts.indexOf(productId) > -1;\r\n }\r\n return false;\r\n }\r\n\r\n /**\r\n * @description Method to extend the product data in the basket item with the extended product data that contains\r\n * availability, images, prices, links and variations and promotion data for price adjustments of product items.\r\n * @returns {Object} promise\r\n * @private\r\n */\r\n function _extendBasketProductsWithProductData() {\r\n var defer = $q.defer();\r\n\r\n _basketData.products.forEach(function(product, index) {\r\n productService.getProduct(product.id).then(function (productData) {\r\n var shallowCopyOfProductData = JSON.parse(JSON.stringify(productData));\r\n // adds the basket product data to the product data and assigns it to the basket product\r\n // this is necessary since price information from the basket should not be overwritten\r\n _basketData.products[index] = Object.assign(shallowCopyOfProductData, _basketData.products[index]);\r\n });\r\n _extendProductPriceAdjustmentsWithPromotionData(product, index);\r\n });\r\n $log.debug('BasketData: ', _basketData);\r\n defer.resolve();\r\n\r\n return defer.promise;\r\n }\r\n\r\n /**\r\n * @description Method to update product availability data (stock/ats).\r\n * TODO check if promise is needed\r\n * TODO add time stamp to prevent unnecessary reuqests\r\n * @returns {Object} promise\r\n * @private\r\n */\r\n function _updateProductAvailabilityData() {\r\n var defer = $q.defer();\r\n\r\n _basketData.products.forEach(function(product, index) {\r\n productService.getAvailability(product.id).then(function (availabilityData) {\r\n _basketData.products[index].stock = availabilityData.inventory.ats;\r\n _basketData.products[index].hasOrderableVariants = productService.hasOrderableVariants(_basketData.products[index]);\r\n });\r\n });\r\n $log.debug('BasketData: ', _basketData);\r\n defer.resolve();\r\n\r\n return defer.promise;\r\n }\r\n\r\n /**\r\n * @description Method to get promotions for an item price adjustment and add promotion data to the adjustments data.\r\n * This methods also checks if coupons are connected with the price adjustment.\r\n * TODO check if promise is needed\r\n * @param {Object} product basket product item that is checked for price adjustments\r\n * @param {Object[]} product.priceAdjustments product price adjustments\r\n * @param {String} product.priceAdjustments[].promotionId promotion id\r\n * @param {String} product.priceAdjustments[].couponCode coupon code\r\n * @param {Number} productIndex index of the product item in the basket data\r\n * @returns {Promise} promise\r\n * @private\r\n */\r\n function _extendProductPriceAdjustmentsWithPromotionData(product, productIndex) {\r\n var defer = $q.defer();\r\n\r\n if (product.hasOwnProperty('priceAdjustments')) {\r\n product.priceAdjustments.forEach(function (priceAdjustment, index) {\r\n promotionService.getPromotion(priceAdjustment.promotionId).then(function (promotionData) {\r\n if (promotionData.callOutMessage) {\r\n _basketData.products[productIndex].priceAdjustments[index].callOutMessage = $sce.getTrustedHtml(promotionData.callOutMessage);\r\n }\r\n if (promotionData.promoTagName || promotionData.callOutMessage) {\r\n _basketData.products[productIndex].priceAdjustments[index].promoTagName = promotionData.promoTagName || promotionData.callOutMessage;\r\n }\r\n if (priceAdjustment.couponCode) {\r\n _setCalloutMessageToCoupon(priceAdjustment.couponCode, promotionData.callOutMessage, priceAdjustment.promotionId.includes('loyalty'));\r\n }\r\n });\r\n });\r\n }\r\n defer.resolve();\r\n\r\n return defer.promise;\r\n }\r\n\r\n /**\r\n * @description Method to get promotions for an order price adjustment and add promotion data to the adjustments data.\r\n * This methods also checks if coupons are connected with the price adjustment.\r\n * TODO check if promise is needed\r\n * TODO add promotion information for if a coupon is connected with the promotion\r\n * @returns {Object} promise\r\n * @private\r\n */\r\n function _extendOrderPriceAdjustmentsWithPromotionData() {\r\n var defer = $q.defer();\r\n\r\n _basketData.orderPriceAdjustments.forEach(function (priceAdjustment, index) {\r\n promotionService.getPromotion(priceAdjustment.promotionId).then(function (promotionData) {\r\n if (promotionData.callOutMessage) {\r\n _basketData.orderPriceAdjustments[index].callOutMessage = promotionData.callOutMessage;\r\n }\r\n if (priceAdjustment.couponCode) {\r\n _setCalloutMessageToCoupon(priceAdjustment.couponCode, promotionData.callOutMessage);\r\n }\r\n });\r\n });\r\n\r\n defer.resolve();\r\n\r\n return defer.promise;\r\n }\r\n\r\n /**\r\n * @description Method to set a callout message to the coupon item.\r\n * @param {String} couponCode code of the coupon to which the callout message should be added\r\n * @param {String} callOutMessage the callout message to add to the coupon\r\n * @param {Boolean} isLoyalty true if the coupon is a loyalty coupon\r\n * @returns {Boolean} true if a coupon was found to which the message is added false otherwise\r\n * @private\r\n */\r\n function _setCalloutMessageToCoupon(couponCode, callOutMessage, isLoyalty) {\r\n const coupons = isLoyalty ? _basketData.couponGiftCertificates : _basketData.coupons;\r\n const matchingCoupon = coupons.find(function (coupon) {\r\n return coupon.code === couponCode;\r\n });\r\n\r\n matchingCoupon.callOutMessage = matchingCoupon ? callOutMessage : null;\r\n\r\n return !!matchingCoupon;\r\n }\r\n\r\n // /**\r\n // * @description Method to set a callout name to the coupon item.\r\n // * @param {String} couponCode code of the coupon to which the callout message should be added\r\n // * @param {String} couponName the callout name to add to the coupon\r\n // * @returns {Boolean} true if a coupon was found to which the message is added false otherwise\r\n // * @private\r\n // */\r\n // function _setCouponNameToCoupon(couponCode, couponName) {\r\n // var matchingCoupon = _basketData.coupons.find(function (coupon) {\r\n // return coupon.code === couponCode;\r\n // });\r\n\r\n // matchingCoupon.couponName = matchingCoupon ? couponName : null;\r\n\r\n // return !!matchingCoupon;\r\n // }\r\n\r\n /**\r\n * @description Method to calculate the total list prices for all basket sale products. Multiplies the list price with the product quantity.\r\n * Method is not used anymore.\r\n * TODO can be removed\r\n * @returns {void}\r\n * @private\r\n */\r\n function _calculateTotalListPricesForSaleProducts() {\r\n var listPrice;\r\n productItems().forEach(function (product) {\r\n listPrice = productService.productListPrice(product);\r\n product.listPrice = listPrice;\r\n product.totalListPrice = listPrice * product.quantity;\r\n });\r\n }\r\n\r\n /**\r\n * @description Method to check all basket product items for valid quantity values.\r\n * @returns {void}\r\n * @private\r\n */\r\n function _checkValidQuantities() {\r\n _quantityErrors = {};\r\n productItems().forEach(function (product) {\r\n checkValidQuantity(product.basketItemId, product.quantity, product.stock);\r\n });\r\n }\r\n\r\n /**\r\n * @description Method to check if a basket product item has a valid quantity.\r\n * @param {String} basketItemId id of the basket product item (not product id)\r\n * @param {Number} quantity current quantity of the basket item\r\n * @param {Number} stock current stock of the basket item\r\n * @returns {Boolean} true if the quantity is not 0 and lower than the stock false otherwise\r\n */\r\n function checkValidQuantity(basketItemId, quantity, stock) {\r\n var isValid = true;\r\n if (quantity > 0 && quantity <= stock) {\r\n _removeQuantityError(basketItemId);\r\n } else {\r\n _addQuantityError(basketItemId);\r\n isValid = false;\r\n }\r\n return isValid;\r\n }\r\n\r\n /**\r\n * @description Method to add a quantity error for a basket product item.\r\n * @param {String} basketItemId id of the basket product item (not product id)\r\n * @returns {void}\r\n * @private\r\n */\r\n function _addQuantityError(basketItemId) {\r\n if (!_quantityErrors.hasOwnProperty(basketItemId)) {\r\n _quantityErrors[basketItemId] = true;\r\n }\r\n service.quantityError = true;\r\n }\r\n\r\n /**\r\n * @description Method to remove quantity error for a basket product item.\r\n * @param {String} basketItemId id of the basket product item (not product id)\r\n * @returns {void}\r\n * @private\r\n */\r\n function _removeQuantityError(basketItemId) {\r\n if (_quantityErrors[basketItemId]) {\r\n delete _quantityErrors[basketItemId];\r\n }\r\n if (Object.keys(_quantityErrors).length === 0) {\r\n service.quantityError = false;\r\n }\r\n }\r\n\r\n /**\r\n * @description Method to get the applicablePaymentMethods from the basket data.\r\n * @returns {String[]} array of applicable payment methods\r\n */\r\n function applicablePaymentMethods() {\r\n return _basketData.applicablePaymentMethods;\r\n }\r\n\r\n /**\r\n * @description Method to get the isLoyaltyCustomer from the basket data.\r\n * @returns {Boolean} whether customer is a loyalty customer\r\n */\r\n function isLoyaltyCustomer() {\r\n return _basketData.isLoyaltyCustomer;\r\n }\r\n\r\n /**\r\n * @description Method to get the isLoyaltyCustomerForCurrentCountry from the basket data.\r\n * @returns {Boolean} whether customer is a loyalty customer in the current country\r\n */\r\n function isLoyaltyCustomerForCurrentCountry() {\r\n return _basketData.isLoyaltyCustomerForCurrentCountry;\r\n }\r\n\r\n /**\r\n * @description Method to get the isEmployeeAccount from the basket data.\r\n * @returns {Boolean} whether customer is an employee\r\n */\r\n function isEmployeeAccount() {\r\n return _basketData.isEmployeeAccount;\r\n }\r\n\r\n /**\r\n * @description Method to get the isCallawayAccount from the basket data.\r\n * @returns {Boolean} whether customer is an employee\r\n */\r\n function isCallawayAccount() {\r\n return _basketData.isCallawayAccount;\r\n }\r\n\r\n /**\r\n * @description Method to get the isFranchiseStore from the basket data.\r\n * @returns {Boolean} whether customer is an employee\r\n */\r\n function isFranchiseStore() {\r\n return _basketData.isFranchiseStore;\r\n }\r\n\r\n /**\r\n * @description Method to get the agent from the basket data.\r\n * @returns {Boolean} whether customer is an agent\r\n */\r\n function agent() {\r\n return _basketData.agent;\r\n }\r\n\r\n /**\r\n * @description Method to determine whether the current customer is logged in.\r\n * @returns {Boolean} true if the customer is logged in.\r\n */\r\n function isCustomerLoggedIn() {\r\n return _basketData.isCustomerLoggedIn;\r\n }\r\n\r\n /**\r\n * @description Method to get the original order total.\r\n * @returns {Number} the original order total, computed by adding all of the products' list prices.\r\n */\r\n function getOriginalOrderTotal() {\r\n return _basketData.originalOrderTotal;\r\n }\r\n\r\n /**\r\n * @description Method to get the sessionCurrency from the basket data.\r\n * @returns {String} currency code\r\n */\r\n function sessionCurrency() {\r\n return _basketData.sessionCurrency;\r\n }\r\n\r\n /**\r\n * @description Method to get the applicableCreditCards from the basket data.\r\n * @returns {Object[]} array of applicable credit cards\r\n */\r\n function applicableCreditCards() {\r\n return _basketData.applicableCreditCards;\r\n }\r\n\r\n /**\r\n * @description Method to get the non coupon promotion totals from the basket data.\r\n * @returns {Object} object that contains the total non coupon promotion prices for every promotion\r\n */\r\n function promotionTotal() {\r\n return _basketData.promotionTotal;\r\n }\r\n\r\n /**\r\n * @description Method to get determine whether the employee order limit has been reached.\r\n * @returns {Boolean} true if the order limit has been reached/exceeded.\r\n */\r\n function orderLimitReached() {\r\n return _basketData.orderLimitReached;\r\n }\r\n\r\n /**\r\n * @description Method to get the basket refusal reason.\r\n * @returns {String} the refusal reason code.\r\n */\r\n function refusalReason() {\r\n return _basketData.refusalReason;\r\n }\r\n\r\n /**\r\n * @description Method to get the basket order limit error message\r\n * @returns {String} the error message\r\n */\r\n function orderLimitMsg() {\r\n return _basketData.orderLimitMsg;\r\n }\r\n\r\n /**\r\n * @description Method to determine whether to show free shipping notification message\r\n * @returns {Boolean} true if after applying coupon code, free shipping is no longer available\r\n */\r\n function showShippingNotification() {\r\n return _basketData.showShippingNotification;\r\n }\r\n\r\n /**\r\n * @description Method to retrieve approaching discounts\r\n * @returns {Boolean} true if after applying coupon code, free shipping is no longer available\r\n */\r\n function approachingDiscounts() {\r\n return _basketData.approachingDiscounts;\r\n }\r\n\r\n\r\n /**\r\n * @description Method to get the loyalty voucher items from the basket data.\r\n * @returns {Object[]} array of loyalty voucher items\r\n */\r\n function basketVouchers() {\r\n return _voucherData ? _voucherData.basketVouchers : null;\r\n }\r\n\r\n /**\r\n * @description Method to retrieve if customer has loyalty vouchers available\r\n * @returns {Boolean} true if has loyalty vouchers available\r\n */\r\n function hasVouchersAvailable() {\r\n return _voucherData ? _voucherData.hasVouchersAvailable : null;\r\n }\r\n\r\n /**\r\n * @description Method to retrieve if customer has loyalty vouchers active\r\n * @returns {Boolean} true if has loyalty vouchers active\r\n */\r\n function hasVouchersActivated() {\r\n return _voucherData ? _voucherData.hasVouchersActivated : null;\r\n }\r\n\r\n /**\r\n * @description Method to retrieve all active vouchers from a customer\r\n * @returns {Object[]} array of active voucher items\r\n */\r\n function activatedVouchers() {\r\n return _voucherData ? _voucherData.activatedVouchers : null;\r\n }\r\n\r\n /**\r\n * @description Method to retrieve all eligible vouchers from a customer\r\n * @returns {Object[]} array of redeemable voucher items\r\n */\r\n function eligibleVouchers() {\r\n let eligibleVouchersArray = [];\r\n if (_voucherData) {\r\n eligibleVouchersArray = _voucherData.redeemableVouchers.concat(_voucherData.exclusiveVouchers);\r\n }\r\n return eligibleVouchersArray;\r\n }\r\n\r\n /**\r\n * @description Method to retrieve all loyalty coupon items from a customer\r\n * @returns {Object[]} array of active voucher items\r\n */\r\n function loyaltyCouponItems() {\r\n return _basketData ? _basketData.loyaltyCouponItems : [];\r\n }\r\n }\r\n}(angular));\r\n","'use strict';\r\n(function (window, document, $) {\r\n $(document).on('click', '.jwsdw-confirmationSelectVoucherPicker-button-unlockVoucher', function(e) {\r\n e.preventDefault();\r\n let $form = $('#jwsdw-selectVoucher-form');\r\n let voucherId = $(this).attr('data-voucher-id');\r\n let source = $(this).attr('data-ajax-source');\r\n $(this).spinner().start();\r\n _activateLoyaltyVoucher(voucherId, $form, source, $(this));\r\n });\r\n\r\n $(document).on('click', '.jwsdw-confirmationSelectVoucherPicker-button-goBack', function(e) {\r\n e.preventDefault();\r\n window.jwsdwMediator.publish('closePicker', 'confirmationSelectVoucherPicker', true);\r\n });\r\n\r\n /**\r\n * @description Method to activate loyalty voucher\r\n * @param {string} voucherId - Selected voucher ID.\r\n * @param {jQuery} $formElement - form element element\r\n * @param {String} source - ajax call source\r\n * @param {jQuery} $submitButton - button element\r\n * @returns {void}\r\n */\r\n function _activateLoyaltyVoucher(voucherId, $formElement, source, $submitButton) {\r\n const data = {};\r\n const method = $formElement.attr('method');\r\n const url = $formElement.attr('action');\r\n data.source = source;\r\n data.voucherId = voucherId;\r\n data[window.jwsdwSettings.csrfTokenName] = window.jwsdwSettings.csrfTokenValue;\r\n $.ajax({\r\n 'url': url,\r\n 'method': method,\r\n 'data': data,\r\n 'success': (response) => {\r\n activatedVoucherSuccess(response, $submitButton);\r\n },\r\n 'error': (response) => {\r\n activatedVoucherError(response, $submitButton);\r\n }\r\n });\r\n }\r\n\r\n /**\r\n * @description Handler for voucher activation successful.\r\n * @param {Object} data - response data.\r\n * @param {JQuery} $button - button element\r\n * @returns {void}\r\n */\r\n function activatedVoucherSuccess(data, $button) {\r\n window.jwsdwMediator.publish(`updateVoucherSection`, data);\r\n window.jwsdwMediator.publish('closePicker', 'confirmationSelectVoucherPicker', true);\r\n window.jwsdwMediator.publish('closePicker', 'selectVoucherPicker', true);\r\n $button.spinner().stop();\r\n }\r\n\r\n /**\r\n * @description Handler for voucher activation error.\r\n * @param {Object} data - response data.\r\n * @param {JQuery} $button - button element\r\n * @returns {void}\r\n */\r\n function activatedVoucherError(data, $button) {\r\n let $errorBanner = $('.jwsdw-selectVoucherPicker-vouchers-notificationBanner');\r\n if (data) {\r\n $errorBanner.removeClass('jws-hidden');\r\n }\r\n window.jwsdwMediator.publish('closePicker', 'confirmationSelectVoucherPicker', true);\r\n $button.spinner().stop();\r\n }\r\n}(window, document, jQuery));\r\n\r\n","'use strict';\r\n\r\n(function (angular) {\r\n\r\n // initialize basket angular app\r\n // bootstrap app manually as only the first app on a page can be initialized by data-ng-app (which is the framework/header)\r\n angular.bootstrap(document.getElementById('jwsdw-basket-module'), ['jwsdw.basket']);\r\n}(angular));\r\n\r\n(function (document, $) {\r\n $(document).on('click', '.jwsdw-basket-coupon-accordion-button', function () {\r\n $(this).attr('aria-expanded', $(this).attr('aria-expanded') === 'true' ? 'false' : 'true');\r\n });\r\n}(document, jQuery));"],"names":["angular","ngTouch","module","makeSwipeDirective","directiveName","direction","eventName","directive","$parse","$swipe","scope","element","attr","startCoords","valid","swipeHandler","pointerTypes","isDefined","push","bind","start","coords","event","cancel","end","validSwipe","deltaY","Math","abs","y","deltaX","x","$apply","triggerHandler","$event","info","angularVersion","factory","POINTER_EVENTS","mouse","move","touch","pointer","getCoordinates","originalEvent","touches","length","e","changedTouches","clientX","clientY","getEvents","eventType","res","forEach","pointerType","join","eventHandlers","totalX","totalY","lastPos","active","events","on","preventDefault","window","config","$compileProvider","debugInfoEnabled","$inject","constant","jwsdwSettings","basket","id","listPriceBook","salePriceBook","productGetImageBaseUrl","BasketController","$scope","$log","$anchorScroll","$window","$location","$timeout","dataService","productService","basketService","contentService","BASKET_ID","SETTINGS","trackAddToBasketService","vm","this","_initObserver","recommendedProduct","let","recommendationBlock","observer","IntersectionObserver","entries","entry","isIntersecting","sendEvent","sendRecommendedProductImpressions","jwsdwApi","tracking","ensureConsent","disconnect","root","rootMargin","threshold","document","getElementById","observe","recommendedProductObserver","removeItem","product","markForRemoval","markedForRemoval","removing","basketItemId","then","removed","tileHeight","outerHeight","fadeOut","basketSuccess","basketData","updateProduct","itemId","initialProductId","variantId","quantity","addItem","_refreshBasketView","updateBonusProduct","addBonusItem","couponSuccess","couponItem","couponItems","concat","couponGiftCertificateItems","find","coupon","code","toUpperCase","couponCode","couponError","errorData","$","validate","showErrors","basketCouponCode","details","message","_refreshProductView","promise","Promise","updating","finally","populateCartQuantityOptions","i","maxCartQuantityPerItem","quantityOptions","updateProgressBar","css","freeShippingPercentage","voucherError","debug","updateVoucherSection","voucherData","voucherSectionUpdating","voucherDataSuccess","data","proceedingToCheckout","proceedingToDirectCheckout","sessionError","invalidProductError","quantityError","bonusProductActive","gPayLoaded","couponInputRevealed","recommendedProductDismissed","refusalReason","search","reason","undefined","currentVoucher","wishlistCount","maxWishlistItemsForGuest","wishlist","onRemoveButtonClick","onRemoveCancelButtonClick","updateQuantity","checkValidQuantity","stock","addCoupon","removeCoupon","couponId","removeBonusCoupon","toggleBonusProduct","checkout","prepareCheckout","catch","validationResult","getBasket","directCheckout","error","errorType","onEditButtonClick","isBonus","jwsdwMediator","publish","openPriceOverridePicker","regex","RegExp","adjustmentTotal","priceAdjustments","filter","priceAdjustment","toString","promotionId","test","manualAdjustment","price","productId","oldPrice","priceAfterItemDiscount","openVoucherPicker","getContent","response","width","content","isVisible","level","err","onMoveToWishlistButtonClick","markedForWishlist","onMoveToWishlistCancelButtonClick","moveItemToWishlist","movingToWishlist","customerAuthenticated","showMaxGuestWishlistMessage","callback","addToWishlist","addToWishlistSuccess","addToWishlistError","products","pid","color","items","movedToWishlist","toggleCouponInput","addRecommendedProduct","productID","isRemovedBonusProduct","onRemoveRecommButtonClick","selectVoucher","voucher","selectedVoucher","addVoucherToBasket","addVoucher","$onInit","init","errorMessage","errorMessages","productItems","hasOwnProperty","isBonusProduct","sessionStorage","setItem","recommendedProductItem","googlePay","applicablePaymentMethods","indexOf","getScript","onLoaded","orderLimitReached","replace","orderLimitMsg","showShippingNotification","subscribe","cartQuantity","productCount","$watch","updateVoucherData","$locationProvider","html5Mode","controller","$q","$sce","promotionService","_callback","_basketData","_voucherData","_totalOrderPriceAdjustment","_ready","_voucherDataReady","_voucherSectionTransition","_voucherRetrievalFailed","_quantityErrors","service","ready","voucherDataReady","voucherSectionTransition","voucherRetrievalFailed","empty","update","voucherDataError","orderTotal","merchandizeTotalGrossPrice","adjustedMerchandizeTotalPrice","shippingTotal","totalOrderPriceAdjustment","productLevelPriceAdjustments","orderCouponPriceAdjustments","orderPriceAdjustments","coupons","couponGiftCertificates","loyaltyCouponItems","giftCardItems","giftCards","isReducedProduct","hasItemDiscount","isSaleProduct","isTaxIncluded","getTaxRate","isMixedTaxRate","taxRate","productQuantity","basketItem","freeShippingAmount","isChoiceOfBonusProductLineItem","isArray","selectedBonusProducts","isLoyaltyCustomer","isLoyaltyCustomerForCurrentCountry","isEmployeeAccount","isCallawayAccount","isFranchiseStore","sessionCurrency","agent","isCustomerLoggedIn","getOriginalOrderTotal","originalOrderTotal","promotionTotal","selectableBonusProductsList","selectableBonusProducts","allBonusProductVariants","hasBonusDiscountLineItem","hideBonusProductImage","maxBonusProducts","defaultSelectableBonusProduct","selectedBonusProductLineItems","outOfStockBonus","hasPriceAdjustments","Object","keys","approachingDiscounts","hasVouchersAvailable","hasVouchersActivated","activatedVouchers","eligibleVouchers","basketVouchers","openSelectVoucherPicker","eligibleVouchersArray","ajaxSource","Emarsys_voucher_Info","taxTotal","applicableCreditCards","basketError","setTimeout","getLoyaltyVouchers","defer","productIds","map","jwsdwUtil","arrayUtils","unique","getProducts","_productDataSuccess","_productDataError","resolve","productData","_checkValidQuantities","_calculateTotalListPricesForSaleProducts","unavailableProductIds","reduce","_recheckAndDeleteUnavailableProducts","productItem","getProduct","promises","_getTotalOrderPriceAdjustment","_extendOrderPriceAdjustmentsWithPromotionData","_extendBasketProductsWithProductData","_updateProductAvailabilityData","all","some","pli","totalDiscount","discountsLength","index","shallowCopyOfProductData","JSON","parse","stringify","assign","_extendProductPriceAdjustmentsWithPromotionData","getAvailability","availabilityData","inventory","ats","hasOrderableVariants","productIndex","getPromotion","promotionData","callOutMessage","getTrustedHtml","promoTagName","_setCalloutMessageToCoupon","includes","isLoyalty","matchingCoupon","listPrice","productListPrice","totalListPrice","isValid","_removeQuantityError","_addQuantityError","redeemableVouchers","exclusiveVouchers","_activateLoyaltyVoucher","voucherId","$formElement","source","$submitButton","method","url","csrfTokenName","csrfTokenValue","ajax","success","activatedVoucherSuccess","activatedVoucherError","$button","spinner","stop","$errorBanner","removeClass","$form","jQuery","bootstrap"],"mappings":"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"}