Your IP : 216.73.216.52


Current Path : /proc/thread-self/cwd/static/frontend/Magento/blank/it_IT/js/bundle/
Upload File :
Current File : //proc/thread-self/cwd/static/frontend/Magento/blank/it_IT/js/bundle/bundle1.js

require.config({"config": {
        "jsbuild":{"StripeIntegration_Payments/js/view/payment/method-renderer/stripe_payments_multishipping.js":"define(\n    [\n        'ko',\n        'Magento_Checkout/js/view/payment/default',\n        'Magento_Ui/js/model/messageList',\n        'Magento_Checkout/js/model/quote',\n        'Magento_Customer/js/model/customer',\n        'StripeIntegration_Payments/js/action/post-update-cart',\n        'StripeIntegration_Payments/js/action/post-restore-quote',\n        'StripeIntegration_Payments/js/action/get-requires-action',\n        'StripeIntegration_Payments/js/view/checkout/trialing_subscriptions',\n        'StripeIntegration_Payments/js/stripe',\n        'stripe_payments_express',\n        'mage/translate',\n        'mage/url',\n        'jquery',\n        'Magento_Checkout/js/action/place-order',\n        'Magento_Checkout/js/model/payment/additional-validators',\n        'Magento_Checkout/js/action/redirect-on-success',\n        'mage/storage',\n        'mage/url',\n        'Magento_CheckoutAgreements/js/model/agreement-validator',\n        'Magento_Customer/js/customer-data',\n        'Magento_Checkout/js/model/payment-service'\n    ],\n    function (\n        ko,\n        Component,\n        globalMessageList,\n        quote,\n        customer,\n        updateCartAction,\n        restoreQuoteAction,\n        getRequiresAction,\n        trialingSubscriptions,\n        stripe,\n        stripeExpress,\n        $t,\n        url,\n        $,\n        placeOrderAction,\n        additionalValidators,\n        redirectOnSuccessAction,\n        storage,\n        urlBuilder,\n        agreementValidator,\n        customerData,\n        paymentService\n    ) {\n        'use strict';\n\n        return Component.extend({\n            externalRedirectUrl: null,\n            defaults: {\n                template: 'StripeIntegration_Payments/payment/element',\n                stripePaymentsShowApplePaySection: false\n            },\n            redirectAfterPlaceOrder: false,\n            elements: null,\n            initParams: null,\n            paymentElement: null,\n            zeroDecimalCurrencies: ['BIF','CLP','DJF','GNF','JPY','KMF','KRW','MGA','PYG','RWF','UGX','VND','VUV','XAF','XOF','XPF'],\n\n            initObservable: function ()\n            {\n                this._super()\n                    .observe([\n                        'paymentElement',\n                        'isPaymentFormComplete',\n                        'isPaymentFormVisible',\n                        'isLoading',\n                        'stripePaymentsError',\n                        'permanentError',\n                        'isOrderPlaced',\n                        'isInitializing',\n                        'isInitialized',\n                        'useQuoteBillingAddress',\n                        'cvcToken',\n                        'paymentElementPaymentMethod',\n\n                        // Saved payment methods dropdown\n                        'dropdownOptions',\n                        'selection',\n                        'isDropdownOpen'\n                    ]);\n\n                var self = this;\n\n                this.isPaymentFormVisible(false);\n                this.isOrderPlaced(false);\n                this.isInitializing(true);\n                this.isInitialized(false);\n                this.useQuoteBillingAddress(false);\n                this.cvcToken(null);\n                this.collectCvc = ko.computed(this.shouldCollectCvc.bind(this));\n                this.isAmex = ko.computed(this.isAmexSelected.bind(this));\n                this.cardCvcElement = null;\n\n                var currentTotals = quote.totals();\n                var currentShippingAddress = quote.shippingAddress();\n                var currentBillingAddress = quote.billingAddress();\n\n                quote.totals.subscribe(function (totals)\n                {\n                    if (!totals || !totals.grand_total || !totals.quote_currency_code)\n                    {\n                        return;\n                    }\n\n                    if (!currentTotals || !currentTotals.grand_total || !currentTotals.quote_currency_code)\n                    {\n                        currentTotals = totals;\n                        return;\n                    }\n\n                    var amount1 = totals.grand_total;\n                    var amount2 = currentTotals.grand_total;\n                    var currency1 = totals.quote_currency_code;\n                    var currency2 = currentTotals.quote_currency_code;\n\n                    if (amount1 === amount2 && currency1 === currency2)\n                    {\n                        return;\n                    }\n\n                    currentTotals = totals;\n\n                    self.onQuoteTotalsChanged.bind(self)();\n                    self.isOrderPlaced(false);\n                }, this);\n\n                quote.paymentMethod.subscribe(function (method)\n                {\n                    if (method.method == this.getCode() && !this.isInitializing())\n                    {\n                        // We intentionally re-create the element because its container element may have changed\n                        this.initPaymentForm();\n                    }\n                }, this);\n\n                quote.billingAddress.subscribe(function(address)\n                {\n                    if (address && self.paymentElement && self.paymentElement.update && !self.isPaymentFormComplete())\n                    {\n                        // Remove the postcode & country fields if a billing address has been specified\n                        self.paymentElement.update(self.getPaymentElementUpdateOptions());\n                    }\n                });\n\n                return this;\n            },\n\n            initSavedPaymentMethods: function()\n            {\n                // If it is already initialized, do not re-initialize\n                if (this.dropdownOptions())\n                {\n                    return;\n                }\n\n                var options = [];\n                var methods = this.getStripeParam(\"savedMethods\");\n                if (methods)\n                {\n                    for (var i in methods)\n                    {\n                        if (methods.hasOwnProperty(i))\n                        {\n                            // We do this because some themes and libraries extend all objects with their own methods\n                            options.push(methods[i]);\n                        }\n                    }\n                }\n\n                if (options.length > 0)\n                {\n                    this.isPaymentFormVisible(false);\n                    this.selection(options[0]);\n                }\n                else\n                {\n                    this.isPaymentFormVisible(true);\n                    this.selection(false);\n                }\n\n                this.dropdownOptions(options);\n            },\n\n            shouldCollectCvc: function()\n            {\n                var selection = this.selection();\n\n                if (!selection)\n                    return false;\n\n                if (selection.type != 'card')\n                    return false;\n\n                return !!selection.cvc;\n            },\n\n            isAmexSelected: function()\n            {\n                var selection = this.selection();\n\n                if (!selection)\n                    return false;\n\n                if (selection.type != 'card')\n                    return false;\n\n                return (selection.brand == \"amex\");\n            },\n\n            newPaymentMethod: function()\n            {\n                this.messageContainer.clear();\n\n                this.selection({\n                    type: 'new',\n                    value: 'new',\n                    icon: false,\n                    label: $t('New payment method')\n                });\n                this.isDropdownOpen(false);\n                this.isPaymentFormVisible(true);\n                if (!this.isInitialized())\n                {\n                    this.onContainerRendered();\n                    this.isInitialized(true);\n                }\n            },\n\n            getPaymentMethodId: function()\n            {\n                var selection = this.selection();\n\n                if (selection && typeof selection.value != \"undefined\" && selection.value != \"new\")\n                {\n                    return selection.value;\n                }\n\n                var paymentMethod = this.paymentElementPaymentMethod();\n                if (paymentMethod && paymentMethod.id)\n                {\n                    return paymentMethod.id;\n                }\n\n                return null;\n            },\n\n            toggleDropdown: function()\n            {\n                this.isDropdownOpen(!this.isDropdownOpen());\n            },\n\n            getStripeParam: function(param)\n            {\n                var params = this.getInitParams();\n\n                if (!params)\n                {\n                    return null;\n                }\n\n                if (typeof params[param] != \"undefined\")\n                {\n                    return params[param];\n                }\n\n                return null;\n            },\n\n            onQuoteTotalsChanged: function()\n            {\n                if (!this.elements || !this.elements.update)\n                {\n                    return;\n                }\n\n                try\n                {\n                    this.elements.update(this.getElementsOptions(true));\n                }\n                catch (e)\n                {\n                    this.elements.update(this.getElementsOptions(false));\n                }\n            },\n\n            getInitParams: function()\n            {\n                return window.checkoutConfig.payment.stripe_payments.initParams;\n            },\n\n            onPaymentElementContainerRendered: function()\n            {\n                var self = this;\n                this.isLoading(true);\n                stripe.initStripe(this.getInitParams(), function(err)\n                {\n                    if (err)\n                        return self.crash(err);\n\n                    self.initSavedPaymentMethods();\n                    self.initPaymentForm();\n                });\n            },\n\n            onContainerRendered: function()\n            {\n                this.onPaymentElementContainerRendered();\n            },\n\n            getCardCVCOptions: function()\n            {\n                return {\n                  style: {\n                    base: {\n                  //     iconColor: '#c4f0ff',\n                  //     color: '#fff',\n                  //     fontWeight: '500',\n                  //     fontFamily: 'Roboto, Open Sans, Segoe UI, sans-serif',\n                      fontSize: '16px',\n                  //     fontSmoothing: 'antialiased',\n                  //     ':-webkit-autofill': {\n                  //       color: '#fce883',\n                  //     },\n                  //     '::placeholder': {\n                  //       color: '#87BBFD',\n                  //     },\n                  //   },\n                  //   invalid: {\n                  //     iconColor: '#FFC7EE',\n                  //     color: '#FFC7EE',\n                    },\n                  },\n                };\n            },\n\n            onCvcContainerRendered: function()\n            {\n                var self = this;\n                var params = this.getInitParams();\n\n                stripe.initStripe(params, function(err)\n                {\n                    if (err)\n                        return self.crash(err);\n\n                    var options = {};\n                    if (params && params.locale)\n                    {\n                        options.locale = params.locale;\n                    }\n\n                    try\n                    {\n                        var elements = stripe.stripeJs.elements(options);\n                        self.cardCvcElement = elements.create('cardCvc', self.getCardCVCOptions());\n                        self.cardCvcElement.mount('#stripe-card-cvc-element');\n                        self.cardCvcElement.on('change', self.onCvcChange.bind(self));\n                    }\n                    catch (e)\n                    {\n                        this.crash(e.message);\n                    }\n                });\n            },\n\n            onCvcChange: function(event)\n            {\n                if (event.error)\n                    this.selection().cvcError = event.error.message;\n                else\n                    this.selection().cvcError = null;\n            },\n\n            crash: function(message)\n            {\n                this.isLoading(false);\n                var userError = this.getStripeParam(\"userError\");\n                if (userError)\n                    this.permanentError(userError);\n                else\n                    this.permanentError($t(\"Sorry, this payment method is not available. Please contact us for assistance.\"));\n\n                console.error(\"Error: \" + message);\n            },\n\n            softCrash: function(message)\n            {\n                var userError = this.getStripeParam(\"userError\");\n                if (userError)\n                    this.showError(userError);\n                else\n                    this.showError($t(\"Sorry, this payment method is not available. Please contact us for assistance.\"));\n\n                console.error(\"Error: \" + message);\n            },\n\n            isCollapsed: function()\n            {\n                if (this.isChecked() == this.getCode())\n                {\n                    return false;\n                }\n                else\n                {\n                    return true;\n                }\n            },\n\n            initPaymentForm: function()\n            {\n                this.isInitializing(false);\n                this.isLoading(false);\n\n                if (this.isCollapsed()) // Don't render PE with a height of 0\n                    return;\n\n                if (document.getElementById('stripe-payment-element') === null)\n                    return this.crash(\"Cannot initialize Payment Element on a DOM that does not contain a div.stripe-payment-element.\");\n\n                if (!stripe.stripeJs)\n                    return this.crash(\"Stripe.js could not be initialized.\");\n\n                if (this.getStripeParam(\"isOrderPlaced\"))\n                    this.isOrderPlaced(true);\n\n                try\n                {\n                    try\n                    {\n                        this.elements = stripe.stripeJs.elements(this.getElementsOptions(true));\n                    }\n                    catch (e)\n                    {\n                        console.warn(\"Could not filter Stripe payment method types: \" + e.message);\n                        this.elements = stripe.stripeJs.elements(this.getElementsOptions(false));\n                    }\n                    this.paymentElement = this.elements.create('payment', this.getPaymentElementOptions());\n                    this.paymentElement.mount('#stripe-payment-element');\n                    this.paymentElement.on('change', this.onChange.bind(this));\n                }\n                catch (e)\n                {\n                    this.crash(e.message);\n                }\n            },\n\n            getElementsOptions: function(filterPaymentMethods)\n            {\n                var options = window.checkoutConfig.payment.stripe_payments.elementOptions;\n\n                if (!filterPaymentMethods && options.payment_method_types)\n                    delete options.payment_method_types;\n\n                if (options.mode != \"setup\")\n                {\n                    options.amount = this.getElementsAmount();\n                    options.currency = this.getElementsCurrency();\n                }\n\n                return options;\n            },\n\n            getPaymentElementOptions: function()\n            {\n                var options = {};\n\n                var params = this.getInitParams();\n                if (params && typeof params.wallets != \"undefined\" && params.wallets)\n                    options.wallets = params.wallets;\n\n                var billingAddress = quote.billingAddress();\n\n                if (billingAddress)\n                {\n                    try\n                    {\n                        this.useQuoteBillingAddress(true);\n\n                        var hasState = (billingAddress.region || billingAddress.regionCode || billingAddress.regionId);\n\n                        options.fields = {\n                            billingDetails: {\n                                name: 'never',\n                                email: 'never',\n                                phone: (billingAddress.telephone ? 'never' : 'auto'),\n                                address: {\n                                    line1: ((billingAddress.street.length > 0) ? 'never' : 'auto'),\n                                    line2: ((billingAddress.street.length > 0) ? 'never' : 'auto'),\n                                    city: billingAddress.city ? 'never' : 'auto',\n                                    state: hasState ? 'never' : 'auto',\n                                    country: billingAddress.countryId ? 'never' : 'auto',\n                                    postalCode: billingAddress.postcode ? 'never' : 'auto'\n                                }\n                            }\n                        };\n                    }\n                    catch (e)\n                    {\n                        this.useQuoteBillingAddress(false);\n\n                        options.fields = {};\n                        console.warn('Could not retrieve billing address: '  + e.message);\n                    }\n\n                    // Set the default billing address in order to enable the Link payment method\n                    var billingDetails = this.getBillingDetails();\n\n                    if (billingDetails)\n                    {\n                        options.defaultValues = {\n                            billingDetails: billingDetails\n                        };\n                    }\n                }\n                else\n                {\n                    this.useQuoteBillingAddress(false);\n                }\n\n                if (params.layout)\n                {\n                    options.layout = params.layout;\n                }\n\n                return options;\n            },\n\n            getPaymentElementUpdateOptions: function()\n            {\n                var options = this.getPaymentElementOptions();\n\n                if (options.wallets)\n                {\n                    delete options.wallets;\n                }\n\n                return options;\n            },\n\n            onChange: function(event)\n            {\n                this.isLoading(false);\n                this.isPaymentFormComplete(event.complete);\n            },\n\n            getElementsAmount: function()\n            {\n                var totals = quote.totals();\n\n                if (totals && totals.grand_total)\n                {\n                    var amount = totals.grand_total;\n                    return this.convertToStripeAmount(amount, this.getElementsCurrency());\n                }\n\n                return 0;\n            },\n\n            getElementsCurrency: function()\n            {\n                var totals = quote.totals();\n                if (totals && totals.quote_currency_code)\n                {\n                    var currency = totals.quote_currency_code;\n                    return currency.toLowerCase();\n                }\n\n                return 'USD';\n            },\n\n            isBillingAddressSet: function()\n            {\n                return quote.billingAddress() && quote.billingAddress().canUseForBilling();\n            },\n\n            convertToStripeAmount: function(amount, currencyCode)\n            {\n                var code = currencyCode.toUpperCase();\n\n                if (this.zeroDecimalCurrencies.indexOf(code) >= 0)\n                {\n                    return Math.round(amount);\n                }\n                else\n                {\n                    return Math.round(amount * 100);\n                }\n            },\n\n            isPlaceOrderEnabled: function()\n            {\n                if (this.stripePaymentsError())\n                    return false;\n\n                if (this.permanentError())\n                    return false;\n\n                return this.isBillingAddressSet();\n            },\n\n            getAddressField: function(field)\n            {\n                if (!quote.billingAddress())\n                    return null;\n\n                var address = quote.billingAddress();\n\n                if (!address[field] || address[field].length == 0)\n                    return null;\n\n                return address[field];\n            },\n\n            getBillingDetails: function()\n            {\n                var details = {};\n                var address = {};\n\n                if (this.getAddressField('city'))\n                    address.city = this.getAddressField('city');\n\n                if (this.getAddressField('countryId'))\n                    address.country = this.getAddressField('countryId');\n\n                if (this.getAddressField('postcode'))\n                    address.postal_code = this.getAddressField('postcode');\n\n                if (this.getAddressField('region'))\n                    address.state = this.getAddressField('region');\n\n                if (this.getAddressField('street'))\n                {\n                    var street = this.getAddressField('street');\n                    address.line1 = street[0];\n\n                    if (street.length > 1)\n                        address.line2 = street[1];\n                }\n\n                if (Object.keys(address).length > 0)\n                    details.address = address;\n\n                if (this.getAddressField('telephone'))\n                    details.phone = this.getAddressField('telephone');\n\n                if (this.getAddressField('firstname'))\n                    details.name = this.getAddressField('firstname') + ' ' + this.getAddressField('lastname');\n\n                if (quote.guestEmail)\n                    details.email = quote.guestEmail;\n                else if (customerData.email)\n                    details.email = customerData.email;\n\n                if (Object.keys(details).length > 0)\n                    return details;\n\n                return null;\n            },\n\n            config: function()\n            {\n                return window.checkoutConfig.payment[this.getCode()];\n            },\n\n            isActive: function(parents)\n            {\n                return true;\n            },\n\n            placeOrder: function()\n            {\n                this.messageContainer.clear();\n\n                if (!this.isPaymentFormComplete() && !this.getPaymentMethodId())\n                    return this.showError($t('Please complete your payment details.'));\n\n                if (!this.validate())\n                    return;\n\n                this.clearErrors();\n                this.isPlaceOrderActionAllowed(false);\n                this.isLoading(true);\n                this.cvcToken(null);\n\n                var params = { };\n\n                if (this.useQuoteBillingAddress())\n                {\n                    params.payment_method_data = {\n                        billing_details: {\n                            address: this.getStripeFormattedAddress(quote.billingAddress()),\n                            email: this.getBillingEmail(),\n                            name: this.getNameFromAddress(quote.billingAddress()),\n                            phone: this.getBillingPhone()\n                        }\n                    };\n                }\n\n                if (this.hasShipping())\n                {\n                    params.shipping = {\n                        address: this.getStripeFormattedAddress(quote.shippingAddress()),\n                        name: this.getNameFromAddress(quote.shippingAddress())\n                    };\n                }\n\n                var self = this;\n\n                if (this.isSavedCardSelected() && this.selection().cvc)\n                {\n                    stripe.stripeJs.createToken('cvc_update', this.cardCvcElement).then(function(result)\n                    {\n                        if (result.error)\n                        {\n                            self.showError(result.error.message);\n                        }\n                        else if (result.token)\n                        {\n                            self.cvcToken(result.token.id);\n                            self.placeOrderWithSavedPaymentMethod.bind(self)();\n                        }\n                        else\n                        {\n                            self.showError('Could not perform CVC check.');\n                        }\n                    });\n                }\n                else if (this.isSavedPaymentMethodSelected())\n                {\n                    this.placeOrderWithSavedPaymentMethod();\n                }\n                else\n                {\n                    this.createPaymentMethod(this.onPaymentMethodCreatedForOrderPlacement.bind(this));\n                }\n\n                return false;\n            },\n\n            hasShipping: function()\n            {\n                return (quote && quote.shippingMethod() && quote.shippingMethod().method_code);\n            },\n\n            createPaymentMethod: function(callback)\n            {\n                this.paymentElementPaymentMethod(null);\n\n                var self = this;\n\n                var paymentMethodData = {\n                    elements: this.elements,\n                    params: {}\n                };\n\n                var confirmParams = this.getConfirmParams();\n                var billingDetails = null;\n                if (confirmParams &&\n                    confirmParams.confirmParams &&\n                    confirmParams.confirmParams.payment_method_data &&\n                    confirmParams.confirmParams.payment_method_data.billing_details\n                )\n                {\n                    billingDetails = confirmParams.confirmParams.payment_method_data.billing_details;\n                }\n\n                if (billingDetails)\n                {\n                    paymentMethodData.params.billing_details = confirmParams.confirmParams.payment_method_data.billing_details;\n                }\n                else\n                {\n                    return this.showError($t(\"Please specify a billing address.\"));\n                }\n\n                this.elements.submit().then(function()\n                {\n                    stripe.stripeJs.createPaymentMethod(paymentMethodData).then(function(result)\n                    {\n                        if (result.error)\n                        {\n                            self.showError(result.error.message);\n                            console.error(result.error.message);\n                        }\n                        else\n                        {\n                            self.paymentElementPaymentMethod(result.paymentMethod);\n                            callback(result.paymentMethod);\n                        }\n                    });\n                },\n                function(result)\n                {\n                    if (result.error)\n                    {\n                        self.showError(result.error.message);\n                        console.error(result.error.message);\n                    }\n                    else\n                    {\n                        self.showError(\"A payment submission error has occurred.\");\n                        console.error(result);\n                    }\n                });\n            },\n\n            isSavedPaymentMethodSelected: function()\n            {\n                var selectedMethodType = this.getSelectedMethod(\"type\");\n\n                if (!selectedMethodType) // There is no saved PMs dropdown\n                    return false;\n\n                if (selectedMethodType != 'new') // A saved PMs is selected\n                    return true;\n\n                return false; // New PM is selected\n            },\n\n            isSavedCardSelected: function()\n            {\n                var selectedMethodType = this.getSelectedMethod(\"type\");\n\n                if (!selectedMethodType) // There is no saved PMs dropdown\n                    return false;\n\n                if (selectedMethodType == 'card') // A saved PMs is selected\n                    return true;\n\n                return false; // New PM is selected\n            },\n\n            placeOrderWithSavedPaymentMethod: function()\n            {\n                var self = this;\n                var placeNewOrder = this.placeNewOrder.bind(this);\n\n                if (this.isOrderPlaced()) // The order was already placed but either 3D Secure failed or the customer pressed the back button from an external payment page\n                {\n                    updateCartAction(this.getData(), this.onCartUpdated.bind(this));\n                }\n                else\n                {\n                    try\n                    {\n                        placeNewOrder();\n                    }\n                    catch (e)\n                    {\n                        this.showError($t(\"The order could not be placed. Please contact us for assistance.\"));\n                        console.error(e.message);\n                    }\n                }\n            },\n\n            onPaymentMethodCreatedForOrderPlacement: function(paymentMethod)\n            {\n                var placeNewOrder = this.placeNewOrder.bind(this);\n                var self = this;\n\n                if (self.isOrderPlaced()) // The order was already placed but either 3D Secure failed or the customer pressed the back button from an external payment page\n                {\n                    updateCartAction(this.getData(), this.onCartUpdated.bind(this));\n                }\n                else\n                {\n                    try\n                    {\n                        placeNewOrder();\n                    }\n                    catch (e)\n                    {\n                        self.showError($t(\"The order could not be placed. Please contact us for assistance.\"));\n                        console.error(e.message);\n                    }\n                }\n            },\n\n            onCartUpdated: function(result, outcome, response)\n            {\n                var placeNewOrder = this.placeNewOrder.bind(this);\n                var onOrderPlaced = this.onOrderPlaced.bind(this);\n                try\n                {\n                    var data = JSON.parse(result);\n                    if (data.error)\n                    {\n                        this.showError(data.error);\n                    }\n                    else if (data.redirect)\n                    {\n                        $.mage.redirect(data.redirect);\n                    }\n                    else if (data.placeNewOrder)\n                    {\n                        placeNewOrder();\n                    }\n                    else\n                    {\n                        onOrderPlaced();\n                    }\n                }\n                catch (e)\n                {\n                    this.showError($t(\"The order could not be placed. Please contact us for assistance.\"));\n                    console.error(e.message);\n                }\n            },\n\n            placeNewOrder: function()\n            {\n                var self = this;\n\n                this.isLoading(false); // Needed for the terms and conditions checkbox\n                this.getPlaceOrderDeferredObject()\n                    .fail(this.handlePlaceOrderErrors.bind(this))\n                    .done(this.onOrderPlaced.bind(this))\n                    .always(function(response, status, xhr)\n                    {\n                        if (status != \"success\")\n                        {\n                            self.isLoading(false);\n                            self.isPlaceOrderEnabled(true);\n                        }\n                    });\n            },\n\n            getSelectedMethod: function(param)\n            {\n                var selection = this.selection();\n                if (!selection)\n                    return null;\n\n                if (typeof selection[param] == \"undefined\")\n                    return null;\n\n                return selection[param];\n            },\n\n            // Called when:\n            // - A brand new order has just been placed\n            // - After updateCartAction() with placeNewOrder == false\n            onOrderPlaced: function(result, outcome, response)\n            {\n                if (!this.isOrderPlaced() && isNaN(result))\n                {\n                    return this.softCrash(\"The order was placed but the response from the server did not include a numeric order ID.\");\n                }\n                else\n                {\n                    this.isOrderPlaced(true);\n                }\n\n                this.isLoading(true);\n                var self = this;\n                var handleNextActions = this.handleNextActions.bind(this);\n                getRequiresAction(function(clientSecret)\n                {\n                    try\n                    {\n                        if (clientSecret && clientSecret.length)\n                        {\n                            stripe.stripeJs.handleNextAction({\n                              clientSecret: clientSecret\n                            }).then(self.onConfirm.bind(self));\n                        }\n                        else\n                        {\n                            // No further actions are needed\n                            self.onConfirm(null);\n                        }\n                    }\n                    catch (e)\n                    {\n                        restoreQuoteAction();\n                        self.showError(\"The order was placed but we could not confirm if the payment was successful.\");\n                        console.error(e);\n                    }\n\n                });\n            },\n\n            isSuccessful: function(stripeObject)\n            {\n\n                if (stripeObject.status == \"requires_action\" &&\n                    stripeObject.next_action &&\n                    stripeObject.next_action.type &&\n                    stripeObject.next_action.type != \"use_stripe_sdk\"\n                )\n                {\n                    // This is the case for vouchers, where an offline payment is required\n                    return true;\n                }\n\n\n                return (['processing', 'requires_capture', 'succeeded'].indexOf(stripeObject.status) >= 0);\n            },\n\n            // Called when:\n            // - A brand new order has just been placed\n            // - After updateCartAction() with placeNewOrder == false\n            handleNextActions: function(stripeObject)\n            {\n                if (!this.isOrderPlaced())\n                {\n                    return this.softCrash(\"Cannot handleNextActions without placing the order first\");\n                }\n\n                var self = this;\n\n                if (this.isSuccessful(stripeObject))\n                {\n                    this.onConfirm(null);\n                }\n                else if (stripeObject.status == \"requires_action\")\n                {\n                    // Non-card based confirms may redirect the customer externally. We restore the quote just before it in case the\n                    // customer clicks the back button on the browser before authenticating the payment.\n                    restoreQuoteAction(function()\n                    {\n                        stripe.stripeJs.handleNextAction({\n                          clientSecret: stripeObject.client_secret\n                        }).then(self.onConfirm.bind(self));\n                    });\n                }\n                else if (stripeObject.status == \"requires_confirmation\")\n                {\n                    // This should only hit when a payment failed with a saved PM, and then the customer switched to PaymentElement to enter a new payment method\n                    restoreQuoteAction(function()\n                    {\n                        // We pass null because we do not want to update the PM. It has already been updated with stripe.updatePaymentIntent\n                        updateCartAction(self.getData(), self.onCartUpdated.bind(self));\n                    });\n                }\n                else if (stripeObject.status == \"requires_payment_method\")\n                {\n                    restoreQuoteAction(function()\n                    {\n                        updateCartAction(self.getData(), self.onCartUpdated.bind(self));\n                    });\n                }\n                else\n                {\n                    restoreQuoteAction(function()\n                    {\n                        self.showError($t(\"The order could not be placed. Please contact us for assistance.\"));\n                        console.error(\"Could not finalize order bacause the payment intent is in status \" + stripeObject.status);\n                    });\n                }\n            },\n\n            getConfirmParams: function()\n            {\n                var params = {\n                    elements: this.elements,\n                    confirmParams: {\n                        return_url: this.getStripeParam(\"successUrl\")\n                    }\n                };\n\n                this.getPaymentElementOptions();\n                if (this.useQuoteBillingAddress())\n                {\n                    params.confirmParams.payment_method_data = {\n                        billing_details: {\n                            address: this.getStripeFormattedAddress(quote.billingAddress()),\n                            email: this.getBillingEmail(),\n                            name: this.getNameFromAddress(quote.billingAddress()),\n                            phone: this.getBillingPhone()\n                        }\n                    };\n                }\n\n                return params;\n            },\n\n            getStripeFormattedAddress: function(address)\n            {\n                var stripeAddress = {};\n\n                stripeAddress.state = address.region ? address.region : null;\n                stripeAddress.postal_code = address.postcode ? address.postcode : null;\n                stripeAddress.country = address.countryId ? address.countryId : null;\n                stripeAddress.city = address.city ? address.city : null;\n\n                if (address.street && address.street.length > 0)\n                {\n                    stripeAddress.line1 = address.street[0];\n\n                    if (address.street.length > 1)\n                    {\n                        stripeAddress.line2 = address.street[1];\n                    }\n                    else\n                    {\n                        stripeAddress.line2 = null;\n                    }\n                }\n                else\n                {\n                    stripeAddress.line1 = null;\n                    stripeAddress.line2 = null;\n                }\n\n                return stripeAddress;\n            },\n\n            getBillingEmail: function()\n            {\n                if (quote.guestEmail)\n                {\n                    return quote.guestEmail;\n                }\n                else if (window.checkoutConfig.customerData && window.checkoutConfig.customerData.email)\n                {\n                    return window.checkoutConfig.customerData.email;\n                }\n\n                return null;\n            },\n\n            getNameFromAddress: function(address)\n            {\n                if (!address)\n                    return null;\n\n                var parts = [];\n                if (address.firstname)\n                    parts.push(address.firstname);\n\n                if (address.middlename)\n                    parts.push(address.middlename);\n\n                if (address.lastname)\n                    parts.push(address.lastname);\n\n                return parts.join(\" \");\n            },\n\n            getBillingPhone: function()\n            {\n                var billingAddress = quote.billingAddress();\n                if (!billingAddress)\n                    return null;\n\n                if (billingAddress.telephone)\n                    return billingAddress.telephone;\n\n                return null;\n            },\n\n            onConfirm: function(result)\n            {\n                this.isLoading(false);\n                if (result && result.error)\n                {\n                    this.showError(result.error.message);\n                }\n                else\n                {\n                    customerData.invalidate(['cart']);\n                    var successUrl = this.getStripeParam(\"successUrl\");\n                    $.mage.redirect(successUrl);\n                }\n            },\n\n            /**\n             * @return {*}\n             */\n            getPlaceOrderDeferredObject: function()\n            {\n                return placeOrderAction(this.getData(), this.messageContainer);\n            },\n\n            getClientSecretFromResponse: function(response)\n            {\n                if (typeof response != \"string\")\n                {\n                    return null;\n                }\n\n                if (response.indexOf(\"Authentication Required: \") >= 0)\n                {\n                    return response.substring(\"Authentication Required: \".length);\n                }\n\n                return null;\n            },\n\n            handleCardPayment: function(paymentIntent, done)\n            {\n                try\n                {\n                    stripe.stripeJs.handleCardPayment(paymentIntent.client_secret).then(function(result)\n                    {\n                        if (result.error)\n                            return done(result.error.message);\n\n                        return done();\n                    });\n                }\n                catch (e)\n                {\n                    done(e.message);\n                }\n            },\n            handleCardAction: function(paymentIntent, done)\n            {\n                try\n                {\n                    stripe.stripeJs.handleCardAction(paymentIntent.client_secret).then(function(result)\n                    {\n                        if (result.error)\n                            return done(result.error.message);\n\n                        return done();\n                    });\n                }\n                catch (e)\n                {\n                    done(e.message);\n                }\n            },\n\n            authenticateCustomer: function(clientSecret, done)\n            {\n                try\n                {\n                    stripe.stripeJs.handleNextAction({\n                      clientSecret: clientSecret\n                    }).then(function(result)\n                    {\n                        if (result.error)\n                            return done(result.error.message);\n\n                        done();\n                    });\n                }\n                catch (e)\n                {\n                    done(e.message);\n                }\n            },\n\n            handlePlaceOrderErrors: function (result)\n            {\n                if (result && result.responseJSON && result.responseJSON.message)\n                {\n                    var clientSecret = this.getClientSecretFromResponse(result.responseJSON.message);\n\n                    if (clientSecret)\n                    {\n                        var self = this;\n                        return this.authenticateCustomer(clientSecret, function(err)\n                        {\n                            if (err)\n                                return self.showError(err);\n\n                            self.placeNewOrder.bind(self)();\n                        });\n                    }\n                    else\n                    {\n                        this.showError(result.responseJSON.message);\n                    }\n                }\n                else\n                {\n                    this.showError($t(\"The order could not be placed. Please contact us for assistance.\"));\n\n                    if (result && result.responseText)\n                        console.error(result.responseText);\n                    else\n                        console.error(result);\n                }\n            },\n\n            showError: function(message)\n            {\n                this.isLoading(false);\n                this.isPlaceOrderEnabled(true);\n                this.messageContainer.addErrorMessage({ \"message\": message });\n            },\n\n            validate: function(elm)\n            {\n                return this.validateCvc() && agreementValidator.validate() && additionalValidators.validate();\n            },\n\n            validateCvc: function()\n            {\n                if (!this.selection())\n                    return true;\n\n                if (this.selection().type != \"card\")\n                    return true;\n\n                if (this.selection().cvc != 1)\n                    return true;\n\n                if (typeof this.selection().cvcError == \"undefined\")\n                {\n                    this.showError($t(\"Please enter your card's security code.\"));\n                    return false;\n                }\n                else if (!this.selection().cvcError)\n                {\n                    return true;\n                }\n                else\n                {\n                    this.showError(this.selection().cvcError);\n                    return false;\n                }\n\n                return true;\n            },\n\n            getCode: function()\n            {\n                return 'stripe_payments';\n            },\n\n            getData: function()\n            {\n                var data = {\n                    'method': this.item.method,\n                    'additional_data': {\n                        'payment_element': true,\n                        'payment_method': this.getPaymentMethodId(),\n                        'manual_authentication': 'card'\n                    }\n                };\n\n                if (this.cvcToken())\n                {\n                    data.additional_data.cvc_token = this.cvcToken();\n                }\n\n                return data;\n            },\n\n            clearErrors: function()\n            {\n                this.stripePaymentsError(null);\n            }\n\n        });\n    }\n);\n","StripeIntegration_Payments/js/view/ui_components/setup_element.js":"define(\n    [\n        'ko',\n        'uiComponent',\n        'StripeIntegration_Payments/js/action/list-payment-methods',\n        'StripeIntegration_Payments/js/action/add-payment-method',\n        'StripeIntegration_Payments/js/action/delete-payment-method',\n        'StripeIntegration_Payments/js/stripe',\n        'Magento_Ui/js/model/messageList',\n        'Magento_Customer/js/model/customer',\n        'mage/translate',\n        'jquery',\n        'mage/storage',\n        'Magento_Customer/js/customer-data',\n        'Magento_Ui/js/model/messages',\n        'uiLayout'\n    ],\n    function (\n        ko,\n        Component,\n        listPaymentMethodsAction,\n        addPaymentMethodAction,\n        deletePaymentMethodAction,\n        stripe,\n        globalMessageList,\n        customer,\n        $t,\n        $,\n        storage,\n        customerData,\n        messagesModel,\n        layout\n    ) {\n        'use strict';\n\n        return Component.extend({\n            externalRedirectUrl: null,\n            defaults: {\n                template: 'StripeIntegration_Payments/setup_element',\n            },\n            elements: null,\n            initParams: null,\n\n            initObservable: function ()\n            {\n                this._super()\n                    .observe([\n                        'paymentElement',\n                        'isPaymentFormComplete',\n                        'isPaymentFormVisible',\n                        'isLoading',\n                        'stripePaymentsError',\n                        'permanentError',\n                        'isOrderPlaced',\n                        'isInitialized',\n                        'savedPaymentMethods',\n                        'processingSavedPaymentMethods'\n                    ]);\n\n                var self = this;\n\n                this.isPaymentFormVisible(false);\n                this.isOrderPlaced(false);\n                this.isInitialized(false);\n                this.processingSavedPaymentMethods(false);\n\n                this.hasPaymentMethods = ko.computed(this.hasPaymentMethodsComputed.bind(this));\n\n                this.messageContainer = new messagesModel();\n\n                var messagesComponent = {\n                    parent: this.name,\n                    name: this.name + '.messages',\n                    displayArea: 'messages',\n                    component: 'Magento_Ui/js/view/messages',\n                    config: {\n                        messageContainer: this.messageContainer,\n                        autoHideTimeOut: -1\n                    }\n                };\n\n                layout([messagesComponent]);\n\n                return this;\n            },\n\n            getStripeParam: function(param)\n            {\n                if (typeof window.initParams == \"undefined\")\n                    return null;\n\n                if (typeof window.initParams[param] == \"undefined\")\n                    return null;\n\n                return window.initParams[param];\n            },\n\n            onPaymentElementContainerRendered: function()\n            {\n                var self = this;\n                this.isLoading(true);\n                this.listPaymentMethods();\n                var initParams = window.initParams;\n\n                stripe.initStripe(initParams, function(err)\n                {\n                    if (err)\n                        return self.crash(err);\n\n                    self.initSetupElement(initParams);\n                });\n            },\n\n            onContainerRendered: function()\n            {\n                this.onPaymentElementContainerRendered();\n            },\n\n            crash: function(message)\n            {\n                this.isLoading(false);\n                this.permanentError($t(\"Sorry, an error has occurred. Please contact us for assistance.\"));\n                console.error(\"Error: \" + message);\n            },\n\n            softCrash: function(message)\n            {\n                this.showError($t(\"Sorry, an error has occurred. Please contact us for assistance.\"));\n                this.stripePaymentsError(message);\n                console.error(\"Error: \" + message);\n            },\n\n            initSetupElement: function(params)\n            {\n                if (document.getElementById('stripe-setup-element') === null)\n                    return this.crash(\"Cannot initialize Payment Element on a DOM that does not contain a div.stripe-setup-element.\");\n\n                if (!stripe.stripeJs)\n                    return this.crash(\"Stripe.js could not be initialized.\");\n\n                var elements = this.elements = stripe.stripeJs.elements({\n                    mode: \"setup\",\n                    setup_future_usage: \"on_session\",\n                    locale: params.locale,\n                    currency: params.currency,\n                    appearance: this.getStripePaymentElementOptions(),\n                    paymentMethodCreation: \"manual\"\n                });\n\n                this.paymentElement = elements.create('payment');\n                this.paymentElement.mount('#stripe-setup-element');\n                this.paymentElement.on('change', this.onChange.bind(this));\n                this.isLoading(false);\n            },\n\n            onChange: function(event)\n            {\n                this.isLoading(false);\n                this.isPaymentFormComplete(event.complete);\n            },\n\n            getStripePaymentElementOptions: function()\n            {\n                return {\n                  theme: 'stripe',\n                  variables: {\n                    colorText: '#32325d',\n                    fontFamily: '\"Open Sans\",\"Helvetica Neue\", Helvetica, Arial, sans-serif',\n                  },\n                };\n            },\n\n            getAddressField: function(field)\n            {\n                var address = [];\n\n                if (typeof address[field] == \"undefined\")\n                    return null;\n\n                if (typeof address[field] !== \"string\" && typeof address[field] !== \"object\")\n                    return null;\n\n                if (address[field].length == 0)\n                    return null;\n\n                return address[field];\n            },\n\n            getBillingDetails: function()\n            {\n                var details = {};\n                var address = {};\n\n                if (this.getAddressField('city'))\n                    address.city = this.getAddressField('city');\n\n                if (this.getAddressField('countryId'))\n                    address.country = this.getAddressField('countryId');\n\n                if (this.getAddressField('postcode'))\n                    address.postal_code = this.getAddressField('postcode');\n\n                if (this.getAddressField('region'))\n                    address.state = this.getAddressField('region');\n\n                if (this.getAddressField('street'))\n                {\n                    var street = this.getAddressField('street');\n                    address.line1 = street[0];\n\n                    if (street.length > 1)\n                        address.line2 = street[1];\n                }\n\n                if (Object.keys(address).length > 0)\n                    details.address = address;\n\n                if (this.getAddressField('telephone'))\n                    details.phone = this.getAddressField('telephone');\n\n                if (this.getAddressField('firstname'))\n                    details.name = this.getAddressField('firstname') + ' ' + this.getAddressField('lastname');\n\n                if (customerData.email)\n                    details.email = customerData.email;\n\n                if (Object.keys(details).length > 0)\n                    return details;\n\n                return null;\n            },\n\n            config: function()\n            {\n                return self.initParams;\n            },\n\n            onClick: function(result, outcome, response)\n            {\n                if (!this.isPaymentFormComplete())\n                    return this.showError($t('Please complete the payment method details.'));\n\n                this.clearErrors();\n\n                this.isLoading(true);\n                var onPaymentMethodCreated = this.onPaymentMethodCreated.bind(this);\n                var onFail = this.onFail.bind(this);\n\n                this.createPaymentMethod(onPaymentMethodCreated, onFail);\n            },\n\n            createPaymentMethod: function(onPaymentMethodCreated, onFail)\n            {\n                var paymentMethodData = {\n                    elements: this.elements,\n                    params: {}\n                };\n\n                this.elements.submit().then(function()\n                {\n                    stripe.stripeJs.createPaymentMethod(paymentMethodData).then(onPaymentMethodCreated, onFail);\n                }, onFail);\n\n            },\n\n            onPaymentMethodCreated: function(result)\n            {\n                var self = this;\n\n                if (result.error)\n                {\n                    this.showError(result.error.message);\n                }\n                else\n                {\n                    addPaymentMethodAction(result.paymentMethod.id, function(response, status, xhr)\n                    {\n                        self.isLoading(false);\n                        if (status == \"success\")\n                        {\n                            try\n                            {\n                                var data = JSON.parse(response);\n\n                                var methods = self.savedPaymentMethods();\n                                if (!methods)\n                                {\n                                    methods = [];\n                                }\n\n                                var isDuplicate = false;\n                                var newMethods = [];\n\n                                for (var i in methods)\n                                {\n                                    if (methods[i].fingerprint != data.fingerprint)\n                                    {\n                                        newMethods.push(methods[i]);\n                                    }\n                                    else\n                                    {\n                                        isDuplicate = true;\n                                    }\n                                }\n\n                                newMethods.push(data);\n\n                                self.savedPaymentMethods(newMethods);\n\n                                if (isDuplicate)\n                                {\n                                    self.showSuccessMessage($t(\"An existing payment method has been updated.\"));\n                                }\n                                else\n                                {\n                                    self.showSuccessMessage($t(\"The payment method has been saved.\"));\n                                }\n                                self.clearFormData();\n                            }\n                            catch (e)\n                            {\n                                console.warn(e);\n                                self.showError($t(\"The payment method could not be saved: %1\").replace(\"%1\", e.message));\n                            }\n                        }\n                        else if (response && response.responseJSON && response.responseJSON.message)\n                        {\n                            self.showError(response.responseJSON.message);\n                        }\n                        else\n                        {\n                            self.showError(\"Sorry, the payment methods could not be added.\");\n                            console.warn(response);\n                        }\n                    });\n                }\n            },\n\n            clearFormData: function()\n            {\n                this.paymentElement.clear();\n                $('html, body').animate({ scrollTop: $(\"#my-saved-payment-methods-table\").offset().top - 100}, 500);\n            },\n\n            onFail: function(result)\n            {\n                this.showError(\"Could not set up the payment method. Please try again.\");\n                console.error(result);\n            },\n\n            showError: function(message)\n            {\n                this.isLoading(false);\n                this.messageContainer.addErrorMessage({ \"message\": message });\n            },\n\n            showSuccessMessage: function(message)\n            {\n                this.isLoading(false);\n                this.messageContainer.addSuccessMessage({ \"message\": message });\n            },\n\n            validate: function(elm)\n            {\n                return true;\n            },\n\n            getCode: function()\n            {\n                return 'stripe_payments';\n            },\n\n            clearErrors: function()\n            {\n                this.messageContainer.clear();\n                this.stripePaymentsError(null);\n            },\n\n            hasPaymentMethodsComputed: function()\n            {\n                return this.savedPaymentMethods() && this.savedPaymentMethods().length > 0;\n            },\n\n            removePaymentMethod: function(fingerprint)\n            {\n                var methods = this.savedPaymentMethods();\n                if (!methods)\n                {\n                    methods = [];\n                }\n\n                var newMethods = [];\n\n                for (var i in methods)\n                {\n                    if (methods[i].fingerprint != fingerprint)\n                    {\n                        newMethods.push(methods[i]);\n                    }\n                }\n\n                return newMethods;\n            },\n\n            deletePaymentMethod: function(paymentMethod)\n            {\n                var sure = confirm($t(\"Are you sure you want to delete this payment method?\"));\n\n                if (!sure)\n                    return;\n\n                var self = this;\n                this.processingSavedPaymentMethods(true);\n                deletePaymentMethodAction(paymentMethod.id, paymentMethod.fingerprint, function(response, status, xhr)\n                {\n                    self.processingSavedPaymentMethods(false);\n                    if (status == \"success\")\n                    {\n                        try\n                        {\n                            var data = JSON.parse(response);\n                            self.showSuccessMessage(data);\n\n                            var newMethods = self.removePaymentMethod(paymentMethod.fingerprint);\n                            self.savedPaymentMethods(newMethods);\n                        }\n                        catch (e)\n                        {\n                            self.showError($t(\"The payment methods could not be deleted: %1\").replace(\"%1\", e.message));\n                        }\n                    }\n                    else\n                    {\n                        self.showError($t(\"The payment methods could not be deleted: %1\").replace(\"%1\", response));\n                    }\n                });\n            },\n\n            listPaymentMethods: function()\n            {\n                var self = this;\n                this.processingSavedPaymentMethods(true);\n\n                listPaymentMethodsAction(function(response, status, xhr)\n                {\n                    self.processingSavedPaymentMethods(false);\n                    if (status == \"success\")\n                    {\n                        try\n                        {\n                            var data = JSON.parse(response);\n                            var methods = [];\n\n                            for (var fingerprint in data)\n                            {\n                                methods.push(data[fingerprint]);\n                            }\n\n                            self.savedPaymentMethods(methods);\n                        }\n                        catch (e)\n                        {\n                            console.warn(e);\n                            console.warn(response);\n                        }\n                    }\n                });\n            }\n\n        });\n    }\n);\n","StripeIntegration_Payments/js/view/multishipping/method-renderer/payment_element.js":"define(\n    [\n        'ko',\n        'StripeIntegration_Payments/js/view/payment/method-renderer/stripe_payments_multishipping',\n        'StripeIntegration_Payments/js/stripe',\n        'Magento_Ui/js/model/messageList',\n        'Magento_Checkout/js/model/quote',\n        'Magento_Customer/js/model/customer',\n        'Magento_Checkout/js/action/set-payment-information',\n        'mage/translate',\n        'mage/url',\n        'jquery',\n        'Magento_Checkout/js/model/payment/additional-validators',\n        'mage/storage',\n        'mage/url',\n        'Magento_CheckoutAgreements/js/model/agreement-validator',\n        'Magento_Customer/js/customer-data',\n        'Magento_Ui/js/modal/alert',\n        'domReady!'\n    ],\n    function (\n        ko,\n        Component,\n        stripe,\n        globalMessageList,\n        quote,\n        customer,\n        setPaymentInformationAction,\n        $t,\n        url,\n        $,\n        additionalValidators,\n        storage,\n        urlBuilder,\n        agreementValidator,\n        customerData,\n        alert\n    ) {\n        'use strict';\n\n        return Component.extend({\n            defaults: {\n                template: 'StripeIntegration_Payments/multishipping/payment_element',\n                continueSelector: '#payment-continue',\n                cardElement: null,\n                token: ko.observable(null),\n                params: null,\n                captureMethod: 'automatic'\n            },\n\n            initObservable: function ()\n            {\n                this._super();\n\n                $(this.continueSelector).click(this.onContinue.bind(this));\n\n                return this;\n            },\n\n            onPaymentElementContainerRendered: function()\n            {\n                var self = this;\n                this.isLoading(true);\n\n                this.params = window.initParams;\n\n                stripe.initStripe(this.params, function(err)\n                {\n                    if (err)\n                        return self.crash(err);\n\n                    self.initSavedPaymentMethods.bind(self)();\n                    self.initPaymentForm.bind(self)();\n                });\n            },\n\n            onContainerRendered: function()\n            {\n                this.onPaymentElementContainerRendered();\n                this.isInitialized(true);\n            },\n\n            initPaymentForm: function()\n            {\n                this.isInitializing(false);\n                this.isLoading(false);\n\n                if (this.isCollapsed()) // Don't render PE with a height of 0\n                    return;\n\n                if (document.getElementById('stripe-payment-element') === null)\n                    return this.crash(\"Cannot initialize Card Element on a DOM that does not contain a div.stripe-card-element.\");\n\n                if (!stripe.stripeJs)\n                    return this.crash(\"Stripe.js could not be initialized.\");\n\n                try\n                {\n                    var elementOptions = this.getElementsOptions(true);\n                    elementOptions.setupFutureUsage = 'on_session';\n                    elementOptions.captureMethod = this.captureMethod;\n                    this.elements = stripe.stripeJs.elements(this.getElementsOptions(true));\n                }\n                catch (e)\n                {\n                    console.warn(\"Could not filter Stripe payment method types: \" + e.message);\n                    this.elements = stripe.stripeJs.elements(this.getElementsOptions(false));\n                }\n\n                this.paymentElement = this.elements.create('payment', this.getPaymentElementOptions());\n                this.paymentElement.mount('#stripe-payment-element');\n                this.paymentElement.on('change', this.onChange.bind(this));\n\n            },\n\n            onSetPaymentMethodFail: function(result)\n            {\n                this.token(null);\n                this.isLoading(false);\n                console.error(result);\n            },\n\n            onContinue: function(e)\n            {\n                // If we already have a tokenized payment method, don't do anything\n                if (this.token())\n                    return;\n\n                var self = this;\n\n                if (!this.isStripeMethodSelected())\n                    return;\n\n                e.preventDefault();\n                e.stopPropagation();\n\n                if (!this.validatePaymentMethod())\n                    return;\n\n                this.isLoading(true);\n\n                if (this.getSelectedMethod(\"type\") && this.getSelectedMethod(\"type\") != \"new\")\n                {\n                    self.token(this.getSelectedMethod(\"value\"));\n                    setPaymentInformationAction(this.messageContainer, this.getData()).then(function(){\n                        $(self.continueSelector).click();\n                    }).fail(self.onSetPaymentMethodFail.bind(self));\n                }\n                else\n                {\n                    this.createPaymentMethod(function(err)\n                    {\n                        if (err)\n                            return self.showError(err);\n\n                        $(self.continueSelector).click();\n                    });\n                }\n            },\n\n            createPaymentMethod: function(done)\n            {\n                var self = this;\n\n                var paymentMethodData = {\n                    elements: this.elements,\n                    params: {}\n                };\n\n                var confirmParams = this.getConfirmParams();\n                var billingDetails = null;\n                if (confirmParams &&\n                    confirmParams.confirmParams &&\n                    confirmParams.confirmParams.payment_method_data &&\n                    confirmParams.confirmParams.payment_method_data.billing_details\n                )\n                {\n                    billingDetails = confirmParams.confirmParams.payment_method_data.billing_details;\n                }\n\n                if (billingDetails)\n                {\n                    paymentMethodData.params.billing_details = confirmParams.confirmParams.payment_method_data.billing_details;\n                }\n                else\n                {\n                    return this.showError($t(\"Please specify a billing address.\"));\n                }\n\n                this.elements.submit().then(function() {\n                    stripe.stripeJs.createPaymentMethod(paymentMethodData).then(function(result)\n                    {\n                        if (result.error)\n                        {\n                            self.showError(result.error.message);\n                            console.error(result.error.message);\n                        }\n                        else\n                        {\n                            self.token(result.paymentMethod.id);\n\n                            setPaymentInformationAction(self.messageContainer, self.getData()).then(function()\n                            {\n                                done();\n                            }).fail(self.onSetPaymentMethodFail.bind(self));\n                        }\n                    });\n                });\n\n            },\n\n            getData: function()\n            {\n                var data = {\n                    'method': this.item.method,\n                    'additional_data': {\n                        'payment_element': true,\n                        'cc_stripejs_token': this.token(),\n                        'manual_authentication': 'card'\n                    }\n                };\n\n                return data;\n            },\n\n            showError: function(message)\n            {\n                this.isLoading(false);\n                alert({ content: message });\n            },\n\n            validatePaymentMethod: function ()\n            {\n                var methods = $('[name^=\"payment[\"]'), isValid = false;\n\n                if (methods.length === 0)\n                    this.showError( $.mage.__('We can\\'t complete your order because you don\\'t have a payment method set up.') );\n                else if (methods.filter('input:radio:checked').length)\n                    return true;\n                else\n                    this.showError( $.mage.__('Please choose a payment method.') );\n\n                return isValid;\n            },\n\n            isStripeMethodSelected: function()\n            {\n                var methods = $('[name^=\"payment[\"]');\n\n                if (methods.length === 0)\n                    return false;\n\n                var stripe = methods.filter(function(index, value)\n                {\n                    if (value.id == \"p_method_stripe_payments\")\n                        return value;\n                });\n\n                if (stripe.length == 0)\n                    return false;\n\n                return stripe[0].checked;\n            }\n        });\n    }\n);\n","StripeIntegration_Payments/js/view/subscription_update/review.js":"define(\n    [\n        'ko',\n        'Magento_Checkout/js/view/payment/default',\n        'Magento_Ui/js/model/messageList',\n        'Magento_Checkout/js/model/quote',\n        'Magento_Customer/js/model/customer',\n        'StripeIntegration_Payments/js/helper/subscriptions',\n        'StripeIntegration_Payments/js/model/upcomingInvoice',\n        'mage/translate',\n        'jquery',\n        'Magento_Checkout/js/action/place-order',\n        'Magento_Checkout/js/model/payment/additional-validators',\n        'Magento_CheckoutAgreements/js/model/agreement-validator',\n        'Magento_CheckoutAgreements/js/model/agreements-assigner'\n    ],\n    function (\n        ko,\n        Component,\n        globalMessageList,\n        quote,\n        customer,\n        subscriptions,\n        upcomingInvoice,\n        $t,\n        $,\n        placeOrderAction,\n        additionalValidators,\n        agreementValidator,\n        agreementsAssigner\n    ) {\n        'use strict';\n\n        return Component.extend({\n            defaults: {\n                template: 'StripeIntegration_Payments/subscription_update/review',\n            },\n            currentTotals: null,\n            newPrice: ko.observable(\"--\"),\n            prorationFee: ko.observable(\"--\"),\n            unusedTime: ko.observable(\"--\"),\n            isPlaceOrderEnabled: ko.observable(false),\n            credit: ko.observable(null),\n\n            initObservable: function ()\n            {\n                this._super()\n                    .observe([\n                        'isLoading',\n                        'stripePaymentsError',\n                        'permanentError',\n                        'userError'\n                    ]);\n\n                var self = this;\n\n                this.initParams = window.checkoutConfig.payment.stripe_payments.initParams;\n\n                upcomingInvoice.initialize();\n                var onUpcomingInvoiceChanged = this.onUpcomingInvoiceChanged.bind(this);\n                upcomingInvoice.onChange(onUpcomingInvoiceChanged);\n\n                this.hasProrationFee = ko.computed(function(){\n                    return self.prorationFee() && self.prorationFee() != \"--\";\n                });\n\n                return this;\n            },\n\n            getConfig: function(key)\n            {\n                return subscriptions.getConfig(key);\n            },\n\n            crash: function(message)\n            {\n                this.isLoading(false);\n                if (this.userError())\n                    this.showError(this.userError());\n                else\n                    this.permanentError($t(\"Sorry, this payment method is not available. Please contact us for assistance.\"));\n\n                console.error(\"Error: \" + message);\n            },\n\n            softCrash: function(message)\n            {\n                this.isLoading(false);\n                if (this.userError())\n                    this.showError(this.userError());\n                else\n                    this.showError($t(\"Sorry, this payment method is not available. Please contact us for assistance.\"));\n\n                console.error(\"Error: \" + message);\n            },\n\n            onChange: function(event)\n            {\n                this.isLoading(false);\n            },\n\n            placeOrder: function()\n            {\n                if (!this.validate())\n                    return;\n\n                var self = this;\n                this.isPlaceOrderEnabled(false);\n                this.isLoading(true);\n\n                this.getPlaceOrderDeferredObject()\n                    .fail(this.handlePlaceOrderErrors.bind(this))\n                    .done(this.onOrderPlaced.bind(this))\n                    .always(function(){\n                        self.isLoading(false);\n                        self.isPlaceOrderEnabled(true);\n                    });\n            },\n\n            getPlaceOrderDeferredObject: function()\n            {\n                return placeOrderAction(this.getData(), this.messageContainer);\n            },\n\n            handlePlaceOrderErrors: function (result)\n            {\n                if (result && result.responseJSON && result.responseJSON.message)\n                    this.showError(result.responseJSON.message);\n                else\n                {\n                    this.showError($t(\"Sorry, the subscription could not be updated. Please contact us for assistance.\"));\n\n                    if (result && result.responseText)\n                        console.error(result.responseText);\n                    else\n                        console.error(result);\n                }\n            },\n\n            onOrderPlaced: function(result, outcome, response)\n            {\n                if (result && !isNaN(result))\n                {\n                    $.mage.redirect(subscriptions.getSuccessUrl());\n                    return;\n                }\n\n                try\n                {\n                    var jsonResponse = JSON.parse(result);\n                    if (jsonResponse && jsonResponse.error)\n                    {\n                        return this.showError(jsonResponse.error);\n                    }\n                    else\n                    {\n                        console.warn(\"The order could not be placed. The server response was: \" + result);\n                        return this.showError($t(\"Sorry, the subscription could not be updated. Please contact us for assistance.\"));\n                    }\n                }\n                catch (e)\n                {\n                    console.warn(\"The order could not be placed. The error was: \" + e);\n                        return this.showError($t(\"Sorry, the subscription could not be updated. Please contact us for assistance.\"));\n                }\n            },\n\n            getData: function()\n            {\n                var data = {\n                    'method': \"stripe_payments\",\n                    'additional_data': {\n                        'is_subscription_update': true\n                    }\n                };\n\n                agreementsAssigner(data);\n\n                return data;\n            },\n\n            showError: function(message)\n            {\n                this.isLoading(false);\n                this.messageContainer.addErrorMessage({ \"message\": message });\n            },\n\n            validate: function(elm)\n            {\n                return agreementValidator.validate() && additionalValidators.validate();\n            },\n\n            getCode: function()\n            {\n                return 'stripe_payments';\n            },\n\n            clearErrors: function()\n            {\n                this.stripePaymentsError(null);\n            },\n\n            onUpcomingInvoiceChanged: function(result, outcome, response)\n            {\n                try\n                {\n                    var params = JSON.parse(result);\n\n                    this.resetTotals();\n\n                    if (params && params.error)\n                    {\n                        this.userError(params.error);\n                        return this.softCrash(params.error);\n                    }\n\n                    if (!params || !params.upcomingInvoice)\n                        return this.softCrash(\"Could not retrieve upcoming invoice\");\n\n                    if (params.upcomingInvoice.new_price &&\n                        params.upcomingInvoice.new_price.label &&\n                        params.upcomingInvoice.new_price.label.length > 0)\n                    {\n                        this.newPrice(params.upcomingInvoice.new_price.label);\n                    }\n\n                    if (params.upcomingInvoice.proration_fee &&\n                        params.upcomingInvoice.proration_fee.label &&\n                        params.upcomingInvoice.proration_fee.label.length > 0)\n                    {\n                        this.prorationFee(params.upcomingInvoice.proration_fee.label);\n                    }\n\n                    if (params.upcomingInvoice.unused_time &&\n                        params.upcomingInvoice.unused_time.label &&\n                        params.upcomingInvoice.unused_time.label.length > 0)\n                    {\n                        this.unusedTime(params.upcomingInvoice.unused_time.label);\n                    }\n\n                    if (params.upcomingInvoice.credit)\n                    {\n                        this.credit(params.upcomingInvoice.credit);\n                    }\n\n                    this.isPlaceOrderEnabled(true);\n                }\n                catch (e)\n                {\n                    console.warn(\"Could not calculate subscription update prices\");\n                    console.warn(e);\n                }\n            },\n\n            resetTotals: function()\n            {\n                this.newPrice(\"--\");\n                this.prorationFee(\"--\");\n                this.unusedTime(\"--\");\n            },\n\n            getCancelUrl: function()\n            {\n                return subscriptions.getCancelUrl();\n            }\n\n        });\n    }\n);\n","StripeIntegration_Payments/js/view/subscription_update/sidebar.js":"define([\n    'ko',\n    'uiComponent',\n    'Magento_Checkout/js/model/totals',\n    'Magento_Checkout/js/model/quote',\n    'Magento_Customer/js/customer-data',\n    'StripeIntegration_Payments/js/helper/subscriptions',\n    'mage/translate',\n    'jquery'\n],\nfunction (\n    ko,\n    Component,\n    totals,\n    quote,\n    customerData,\n    subscriptions,\n    $t,\n    $\n)\n{\n    'use strict';\n\n    return Component.extend({\n        isDisplayed: ko.observable(false),\n        isLoading: totals.isLoading,\n\n        initialize: function()\n        {\n            this._super();\n\n            this.isDisplayed(subscriptions.displaySidebar());\n\n            // var self = this;\n\n            // window.addEventListener('hashchange', function()\n            // {\n            //     self.isDisplayed(subscriptions.displaySidebar());\n            // });\n        },\n\n        getConfig: function(key)\n        {\n            return subscriptions.getConfig(key);\n        },\n\n        cancelUpdate: function()\n        {\n            var cancelUrl = subscriptions.getCancelUrl();\n            var yes = confirm($t(\"Are you sure you want to cancel the subscription update?\"));\n            if (yes)\n            {\n                $.mage.redirect(cancelUrl);\n            }\n        },\n\n    });\n});\n","StripeIntegration_Payments/js/view/checkout/trialing_subscriptions.js":"define(\n    [\n        'ko',\n        'Magento_Checkout/js/view/summary/abstract-total',\n        'Magento_Checkout/js/model/quote',\n        'Magento_Catalog/js/price-utils',\n        'Magento_Checkout/js/model/totals',\n        'mage/translate',\n        'StripeIntegration_Payments/js/action/get-trialing-subscriptions',\n        'Magento_Customer/js/customer-data'\n    ],\n    function (ko, Component, quote, priceUtils, totals, $t, getTrialingSubscriptions, customerData) {\n        \"use strict\";\n        return Component.extend({\n            defaults: {\n                isFullTaxSummaryDisplayed: window.checkoutConfig.isFullTaxSummaryDisplayed || false,\n                template: 'StripeIntegration_Payments/checkout/trialing_subscriptions',\n                trialingSubscriptions: ko.observable(window.checkoutConfig.payment.stripe_payments.trialingSubscriptions),\n                fetching: ko.observable(false)\n            },\n            totals: quote.getTotals(),\n            isTaxDisplayedInGrandTotal: window.checkoutConfig.includeTaxInGrandTotal || false,\n\n            initialize: function ()\n            {\n                this._super();\n\n                this.observe(['trialingSubscriptions']);\n                this.trialingSubscriptions(window.checkoutConfig.payment.stripe_payments.trialingSubscriptions);\n\n                this.getFormattedSubscriptionsPrice = ko.computed(function()\n                {\n                    var price = -this.getAmount('subscriptions_total');\n                    return this.getFormattedPrice(price);\n                }, this);\n\n                this.getFormattedShipping = ko.computed(function()\n                {\n                    var price = -this.getAmount('shipping_total');\n                    return this.getFormattedPrice(price);\n                }, this);\n\n                this.getFormattedTax = ko.computed(function()\n                {\n                    var price = -this.getAmount('tax_total');\n                    return this.getFormattedPrice(price);\n                }, this);\n\n                this.getFormattedDiscount = ko.computed(function()\n                {\n                    var price = this.getAmount('discount_total');\n                    return this.getFormattedPrice(price);\n                }, this);\n\n                this.hasTrialingSubscriptions = ko.computed(function()\n                {\n                    return this.getAmount('subscriptions_total') !== 0;\n                }, this);\n\n                this.hasShipping = ko.computed(function()\n                {\n                    return this.getAmount('shipping_total') !== 0;\n                }, this);\n\n                this.hasTax = ko.computed(function()\n                {\n                    return this.getAmount('tax_total') !== 0;\n                }, this);\n\n                this.hasDiscount = ko.computed(function()\n                {\n                    return this.getAmount('discount_total') !== 0;\n                }, this);\n\n                this.trialingSubscriptions(this.getTrialSubscriptions());\n\n                var grandTotal = quote.totals().grand_total;\n\n                quote.totals.subscribe(function (totals)\n                {\n                    if (grandTotal == quote.totals().grand_total)\n                        return;\n\n                    grandTotal = quote.totals().grand_total;\n\n                    this.refresh(quote);\n                }, this);\n            },\n\n            isDisplayed: function()\n            {\n                return this.isFullMode() && this.getPureValue() !== 0;\n            },\n\n            getTrialSubscriptions: function()\n            {\n                if (\n                    window.checkoutConfig &&\n                    window.checkoutConfig.payment &&\n                    window.checkoutConfig.payment.stripe_payments &&\n                    window.checkoutConfig.payment.stripe_payments.hasTrialSubscriptions &&\n                    window.checkoutConfig.payment.stripe_payments.trialingSubscriptions\n                )\n                {\n                    return window.checkoutConfig.payment.stripe_payments.trialingSubscriptions;\n                }\n\n                return null;\n            },\n\n            refresh: function(quote)\n            {\n                if (!this.getTrialSubscriptions())\n                    return;\n\n                if (this.fetching())\n                    return;\n\n                var self = this;\n                this.fetching(true);\n\n                getTrialingSubscriptions(quote)\n                    .always(function()\n                    {\n                        self.fetching(false);\n                    })\n                    .done(function (subscriptions)\n                    {\n                        try {\n                            var data = JSON.parse(subscriptions);\n                            window.checkoutConfig.payment.stripe_payments.trialingSubscriptions = data;\n                            self.trialingSubscriptions(data);\n                        } catch (e) {\n                            console.warn('Could not retrieve trial subscriptions: ' + e.message);\n                            self.trialingSubscriptions(window.checkoutConfig.payment.stripe_payments.trialingSubscriptions);\n                        }\n                    })\n                    .fail(function (xhr, textStatus, errorThrown)\n                    {\n                        console.warn(console.warn('Could not retrieve trial subscriptions: ' + xhr.responseText));\n                    });\n            },\n\n            discountTitle: function()\n            {\n                return $t('Trial Discount');\n            },\n\n            shippingTitle: function()\n            {\n                return $t('Trial Shipping');\n            },\n\n            taxTitle: function()\n            {\n                return $t('Trial Tax');\n            },\n\n            getAmount: function(key)\n            {\n                var config = this.trialingSubscriptions();\n\n                if (config == null)\n                    return 0;\n\n                if ((key in config) && !isNaN(config[key]))\n                    return config[key];\n\n                return 0;\n            },\n\n            getPureValue: function()\n            {\n                var price = this.getAmount('discount_total') -\n                            this.getAmount('subscriptions_total') -\n                            this.getAmount('shipping_total') -\n                            this.getAmount('tax_total') +\n                            this.getAmount('tax_inclusive');\n\n                return Math.round(price * 10000) / 10000;\n            },\n\n            getBasePureValue: function()\n            {\n                var price = this.getAmount('base_discount_total') -\n                            this.getAmount('base_subscriptions_total') -\n                            this.getAmount('base_shipping_total') -\n                            this.getAmount('base_tax_total') +\n                            this.getAmount('base_tax_inclusive');\n\n                return Math.round(price * 10000) / 10000;\n            },\n\n            getTaxAmount: function()\n            {\n                return this.getAmount('tax_total');\n            },\n\n            config: function()\n            {\n                return window.checkoutConfig.payment.stripe_payments;\n            }\n        });\n    }\n);\n","StripeIntegration_Payments/js/view/checkout/cart/totals/initial_fee.js":"define(\n    [\n        'StripeIntegration_Payments/js/view/checkout/summary/initial_fee'\n    ],\n    function (Component) {\n        'use strict';\n\n        return Component.extend(\n        {\n            isDisplayed: function ()\n            {\n                return this.getPureValue() !== 0;\n            }\n        });\n    }\n);\n","StripeIntegration_Payments/js/view/checkout/summary/initial_fee.js":"define(\n    [\n        'Magento_Checkout/js/view/summary/abstract-total',\n        'Magento_Checkout/js/model/quote',\n        'Magento_Catalog/js/price-utils',\n        'Magento_Checkout/js/model/totals'\n    ],\n    function (Component, quote, priceUtils, totals) {\n        \"use strict\";\n        return Component.extend({\n            defaults: {\n                isFullTaxSummaryDisplayed: window.checkoutConfig.isFullTaxSummaryDisplayed || false,\n                template: 'StripeIntegration_Payments/checkout/summary/initial_fee'\n            },\n            totals: quote.getTotals(),\n            isTaxDisplayedInGrandTotal: window.checkoutConfig.includeTaxInGrandTotal || false,\n\n            isDisplayed: function() {\n                return this.isFullMode() && this.getPureValue() !== 0;\n            },\n\n            getValue: function() {\n                var price = 0;\n                if (this.totals() && totals.getSegment('initial_fee')) {\n                    price = totals.getSegment('initial_fee').value;\n                }\n                return this.getFormattedPrice(price);\n            },\n            getPureValue: function() {\n                var price = 0;\n                if (this.totals() && totals.getSegment('initial_fee')) {\n                    price = totals.getSegment('initial_fee').value;\n                }\n                return price;\n            }\n        });\n    }\n);\n","StripeIntegration_Payments/js/view/checkout/summary/prorations.js":"define(\n    [\n        'ko',\n        'mage/translate',\n        'Magento_Checkout/js/view/summary/abstract-total',\n        'Magento_Checkout/js/model/quote',\n        'Magento_Catalog/js/price-utils',\n        'Magento_Checkout/js/model/totals',\n        'StripeIntegration_Payments/js/helper/subscriptions',\n        'StripeIntegration_Payments/js/model/upcomingInvoice'\n    ],\n    function (\n        ko,\n        $t,\n        Component,\n        quote,\n        priceUtils,\n        totals,\n        subscriptions,\n        upcomingInvoice\n    ) {\n        \"use strict\";\n\n        return Component.extend({\n            defaults: {\n                template: 'StripeIntegration_Payments/checkout/summary/prorations'\n            },\n            totals: quote.getTotals(),\n            prorationAdjustment: ko.observable(0),\n            baseProrationAdjustment: ko.observable(0),\n\n            initialize: function()\n            {\n                this._super();\n                upcomingInvoice.initialize();\n                upcomingInvoice.onChange(this.onUpcomingInvoiceChanged.bind(this));\n            },\n\n            isDisplayed: function()\n            {\n                return subscriptions.isSubscriptionUpdate() && this.isFullMode() && this.getPureValue() !== 0;\n            },\n\n            getValue: function()\n            {\n                var price = this.getPureValue();\n                return this.getFormattedPrice(price);\n            },\n\n            getPureValue: function()\n            {\n                var price = 0;\n                if (subscriptions.isSubscriptionUpdate() && this.prorationAdjustment()) {\n                    price = this.prorationAdjustment();\n                }\n                return price;\n            },\n\n            getBasePureValue: function()\n            {\n                var price = 0;\n                if (subscriptions.isSubscriptionUpdate() && this.baseProrationAdjustment()) {\n                    price = this.baseProrationAdjustment();\n                }\n                return price;\n            },\n\n            onUpcomingInvoiceChanged: function(result, outcome, response)\n            {\n                try\n                {\n                    var params = JSON.parse(result);\n\n                    if (params && params.error)\n                    {\n                        return;\n                    }\n\n                    if (!params || !params.upcomingInvoice)\n                        return;\n\n                    if (!isNaN(params.upcomingInvoice.proration_adjustment))\n                    {\n                        this.prorationAdjustment(params.upcomingInvoice.proration_adjustment);\n                    }\n\n                    if (!isNaN(params.upcomingInvoice.base_proration_adjustment))\n                    {\n                        this.baseProrationAdjustment(params.upcomingInvoice.base_proration_adjustment);\n                    }\n                }\n                catch (e)\n                {\n                    console.warn(\"Could not calculate sidebar proration amount\");\n                    console.warn(e);\n                }\n            },\n        });\n    }\n);\n","StripeIntegration_Payments/js/model/upcomingInvoice.js":"define(\n    [\n        'ko',\n        'Magento_Checkout/js/model/quote',\n        'StripeIntegration_Payments/js/action/get-upcoming-invoice',\n    ],\n    function (\n        ko,\n        quote,\n        getUpcomingInvoiceAction\n    ) {\n        'use strict';\n\n        return {\n            upcomingInvoiceRequest: null,\n            initialized: false,\n            currentTotals: null,\n            callbacks: [],\n\n            initialize: function()\n            {\n                if (this.initialized)\n                    return;\n\n                this.initialized = true;\n\n                this.watchTotals();\n                getUpcomingInvoiceAction(this.upcomingInvoiceChanged.bind(this));\n            },\n\n            watchTotals: function()\n            {\n                this.currentTotals = quote.totals();\n                var upcomingInvoiceChanged = this.upcomingInvoiceChanged.bind(this);\n                var self = this;\n\n                quote.totals.subscribe(function (totals)\n                {\n                    if (JSON.stringify(totals.total_segments) == JSON.stringify(self.currentTotals.total_segments))\n                        return;\n\n                    self.currentTotals = totals;\n\n                    getUpcomingInvoiceAction(upcomingInvoiceChanged);\n                }, self);\n            },\n\n            upcomingInvoiceChanged: function(result, outcome, response)\n            {\n                this.upcomingInvoiceRequest = {\n                    result: result,\n                    outcome: outcome,\n                    response: response\n                };\n\n                for (var i = 0; i < this.callbacks.length; i++)\n                {\n                    this.callbacks[i](result, outcome, response);\n                }\n            },\n\n            onChange: function(callback)\n            {\n                this.callbacks.push(callback);\n\n                if (this.upcominInvoiceRequest)\n                {\n                    callback(this.upcominInvoiceRequest.result, this.upcominInvoiceRequest.outcome, this.upcominInvoiceRequest.response);\n                }\n            }\n        };\n    }\n);\n","Magento_ProductVideo/js/load-player.js":"/**\n * Copyright \u00a9 Magento, Inc. All rights reserved.\n * See COPYING.txt for license details.\n */\n\n/**\n @version 0.0.1\n @requires jQuery & jQuery UI\n */\ndefine([\n    'jquery',\n    'jquery-ui-modules/widget',\n    'vimeoWrapper'\n], function ($) {\n    'use strict';\n\n    var videoRegister = {\n        _register: {},\n\n        /**\n         * Checks, if api is already registered\n         *\n         * @param {String} api\n         * @returns {bool}\n         */\n        isRegistered: function (api) {\n            return this._register[api] !== undefined;\n        },\n\n        /**\n         * Checks, if api is loaded\n         *\n         * @param {String} api\n         * @returns {bool}\n         */\n        isLoaded: function (api) {\n            return this._register[api] !== undefined && this._register[api] === true;\n        },\n\n        /**\n         * Register new video api\n         * @param {String} api\n         * @param {bool} loaded\n         */\n        register: function (api, loaded) {\n            loaded = loaded || false;\n            this._register[api] = loaded;\n        }\n    };\n\n    $.widget('mage.productVideoLoader', {\n\n        /**\n         * @private\n         */\n        _create: function () {\n            switch (this.element.data('type')) {\n                case 'youtube':\n                    this.element.videoYoutube();\n                    this._player = this.element.data('mageVideoYoutube');\n                    break;\n\n                case 'vimeo':\n                    this.element.videoVimeo();\n                    this._player = this.element.data('mageVideoVimeo');\n                    break;\n                default:\n                    throw {\n                        name: 'Video Error',\n                        message: 'Unknown video type',\n\n                        /**\n                         * join name with message\n                         */\n                        toString: function () {\n                            return this.name + ': ' + this.message;\n                        }\n                    };\n            }\n        },\n\n        /**\n         * Initializes variables\n         * @private\n         */\n        _initialize: function () {\n            this._params = this.element.data('params') || {};\n            this._code = this.element.data('code');\n            this._width = this.element.data('width');\n            this._height = this.element.data('height');\n            this._autoplay = !!this.element.data('autoplay');\n            this._playing = this._autoplay || false;\n            this._loop = this.element.data('loop');\n            this._rel = this.element.data('related');\n            this.useYoutubeNocookie = this.element.data('youtubenocookie') || false;\n\n            this._responsive = this.element.data('responsive') !== false;\n\n            if (this._responsive === true) {\n                this.element.addClass('responsive');\n            }\n\n            this._calculateRatio();\n        },\n\n        /**\n         * Abstract play command\n         */\n        play: function () {\n            this._player.play();\n        },\n\n        /**\n         * Abstract pause command\n         */\n        pause: function () {\n            this._player.pause();\n        },\n\n        /**\n         * Abstract stop command\n         */\n        stop: function () {\n            this._player.stop();\n        },\n\n        /**\n         * Abstract playing command\n         */\n        playing: function () {\n            return this._player.playing();\n        },\n\n        /**\n         * Calculates ratio for responsive videos\n         * @private\n         */\n        _calculateRatio: function () {\n            if (!this._responsive) {\n                return;\n            }\n            this.element.css('paddingBottom', this._height / this._width * 100 + '%');\n        }\n    });\n\n    $.widget('mage.videoYoutube', $.mage.productVideoLoader, {\n\n        /**\n         * Initialization of the Youtube widget\n         * @private\n         */\n        _create: function () {\n            var self = this;\n\n            this._initialize();\n\n            this.element.append('<div></div>');\n\n            this._on(window, {\n\n                /**\n                 * Handle event\n                 */\n                'youtubeapiready': function () {\n                    var host = 'https://www.youtube.com';\n\n                    if (self.useYoutubeNocookie) {\n                        host = 'https://www.youtube-nocookie.com';\n                    }\n\n                    if (self._player !== undefined) {\n                        return;\n                    }\n                    self._autoplay = true;\n\n                    if (self._autoplay) {\n                        self._params.autoplay = 1;\n                    }\n\n                    if (!self._rel) {\n                        self._params.rel = 0;\n                    }\n\n                    self._player = new window.YT.Player(self.element.children(':first')[0], {\n                        height: self._height,\n                        width: self._width,\n                        videoId: self._code,\n                        playerVars: self._params,\n                        host: host,\n                        events: {\n\n                            /**\n                             * Get duration\n                             */\n                            'onReady': function onPlayerReady() {\n                                self._player.getDuration();\n                                self.element.closest('.fotorama__stage__frame')\n                                    .addClass('fotorama__product-video--loaded');\n                            },\n\n                            /**\n                             * Event observer\n                             */\n                            onStateChange: function (data) {\n                                switch (window.parseInt(data.data, 10)) {\n                                    case 1:\n                                        self._playing = true;\n                                        break;\n                                    default:\n                                        self._playing = false;\n                                        break;\n                                }\n\n                                self._trigger('statechange', {}, data);\n\n                                if (data.data === window.YT.PlayerState.ENDED && self._loop) {\n                                    self._player.playVideo();\n                                }\n                            }\n                        }\n\n                    });\n                }\n            });\n\n            this._loadApi();\n        },\n\n        /**\n         * Loads Youtube API and triggers event, when loaded\n         * @private\n         */\n        _loadApi: function () {\n            var element,\n                scriptTag;\n\n            if (videoRegister.isRegistered('youtube')) {\n                if (videoRegister.isLoaded('youtube')) {\n                    $(window).trigger('youtubeapiready');\n                }\n\n                return;\n            }\n\n            // if script already loaded by other library\n            if (window.YT) {\n                videoRegister.register('youtube', true);\n                $(window).trigger('youtubeapiready');\n\n                return;\n            }\n            videoRegister.register('youtube');\n\n            element = document.createElement('script');\n            scriptTag = document.getElementsByTagName('script')[0];\n\n            element.async = true;\n            element.src = 'https://www.youtube.com/iframe_api';\n            scriptTag.parentNode.insertBefore(element, scriptTag);\n\n            /**\n             * Event observe and handle\n             */\n            window.onYouTubeIframeAPIReady = function () {\n                $(window).trigger('youtubeapiready');\n                videoRegister.register('youtube', true);\n            };\n        },\n\n        /**\n         * Play command for Youtube\n         */\n        play: function () {\n            this._player.playVideo();\n            this._playing = true;\n        },\n\n        /**\n         * Pause command for Youtube\n         */\n        pause: function () {\n            this._player.pauseVideo();\n            this._playing = false;\n        },\n\n        /**\n         * Stop command for Youtube\n         */\n        stop: function () {\n            this._player.stopVideo();\n            this._playing = false;\n        },\n\n        /**\n         * Playing command for Youtube\n         */\n        playing: function () {\n            return this._playing;\n        },\n\n        /**\n         * stops and unloads player\n         * @private\n         */\n        _destroy: function () {\n            this.stop();\n        }\n    });\n\n    $.widget('mage.videoVimeo', $.mage.productVideoLoader, {\n\n        /**\n         * Initialize the Vimeo widget\n         * @private\n         */\n        _create: function () {\n            var timestamp,\n                additionalParams = '',\n                src,\n                id;\n\n            this._initialize();\n            timestamp = new Date().getTime();\n            this._autoplay = true;\n\n            if (this._autoplay) {\n                additionalParams += '&autoplay=1';\n            }\n\n            if (this._loop) {\n                additionalParams += '&loop=1';\n            }\n            src = 'https://player.vimeo.com/video/' +\n                this._code + '?api=1&player_id=vimeo' +\n                this._code +\n                timestamp +\n                additionalParams;\n            id = 'vimeo' + this._code + timestamp;\n            this.element.append(\n                $('<iframe></iframe>')\n                    .attr('frameborder', 0)\n                    .attr('id', id)\n                    .attr('width', this._width)\n                    .attr('height', this._height)\n                    .attr('src', src)\n                    .attr('webkitallowfullscreen', '')\n                    .attr('mozallowfullscreen', '')\n                    .attr('allowfullscreen', '')\n                    .attr('referrerPolicy', 'origin')\n                    .attr('allow', 'autoplay')\n            );\n\n            /* eslint-disable no-undef */\n            this._player = new Vimeo.Player(this.element.children(':first')[0]);\n\n            this._player.ready().then(function () {\n                $('#' + id).closest('.fotorama__stage__frame').addClass('fotorama__product-video--loaded');\n            });\n        },\n\n        /**\n         * Play command for Vimeo\n         */\n        play: function () {\n            this._player.play();\n            this._playing = true;\n        },\n\n        /**\n         * Pause command for Vimeo\n         */\n        pause: function () {\n            this._player.pause();\n            this._playing = false;\n        },\n\n        /**\n         * Stop command for Vimeo\n         */\n        stop: function () {\n            this._player.unload();\n            this._playing = false;\n        },\n\n        /**\n         * Playing command for Vimeo\n         */\n        playing: function () {\n            return this._playing;\n        }\n    });\n});\n","Magento_ProductVideo/js/fotorama-add-video-events.js":"/**\n * Copyright \u00a9 Magento, Inc. All rights reserved.\n * See COPYING.txt for license details.\n */\n\ndefine([\n    'jquery',\n    'jquery-ui-modules/widget',\n    'catalogGallery',\n    'loadPlayer'\n], function ($) {\n    'use strict';\n\n    /**\n     * @private\n     */\n    var allowBase = true; //global var is needed because fotorama always fully reloads events in case of fullscreen\n\n    /**\n     * @private\n     */\n    function parseHref(href) {\n        var a = document.createElement('a');\n\n        a.href = href;\n\n        return a;\n    }\n\n    /**\n     * @private\n     */\n    function parseURL(href, forceVideo) {\n        var id,\n            type,\n            ampersandPosition,\n            vimeoRegex,\n            useYoutubeNocookie = false;\n\n        /**\n         * Get youtube ID\n         * @param {String} srcid\n         * @returns {{}}\n         */\n        function _getYoutubeId(srcid) {\n            if (srcid) {\n                ampersandPosition = srcid.indexOf('&');\n\n                if (ampersandPosition === -1) {\n                    return srcid;\n                }\n\n                srcid = srcid.substring(0, ampersandPosition);\n            }\n\n            return srcid;\n        }\n\n        if (typeof href !== 'string') {\n            return href;\n        }\n\n        href = parseHref(href);\n\n        if (href.host.match(/youtube\\.com/) && href.search) {\n            id = href.search.split('v=')[1];\n\n            if (id) {\n                id = _getYoutubeId(id);\n                type = 'youtube';\n            }\n        } else if (href.host.match(/youtube\\.com|youtu\\.be|youtube-nocookie.com/)) {\n            id = href.pathname.replace(/^\\/(embed\\/|v\\/)?/, '').replace(/\\/.*/, '');\n            type = 'youtube';\n\n            if (href.host.match(/youtube-nocookie.com/)) {\n                useYoutubeNocookie = true;\n            }\n        } else if (href.host.match(/vimeo\\.com/)) {\n            type = 'vimeo';\n            vimeoRegex = new RegExp(['https?:\\\\/\\\\/(?:www\\\\.|player\\\\.)?vimeo.com\\\\/(?:channels\\\\/(?:\\\\w+\\\\/)',\n                '?|groups\\\\/([^\\\\/]*)\\\\/videos\\\\/|album\\\\/(\\\\d+)\\\\/video\\\\/|video\\\\/|)(\\\\d+)(?:$|\\\\/|\\\\?)'\n            ].join(''));\n            id = href.href.match(vimeoRegex)[3];\n        }\n\n        if ((!id || !type) && forceVideo) {\n            id = href.href;\n            type = 'custom';\n        }\n\n        return id ? {\n            id: id, type: type, s: href.search.replace(/^\\?/, ''), useYoutubeNocookie: useYoutubeNocookie\n        } : false;\n    }\n\n    //create AddFotoramaVideoEvents widget\n    $.widget('mage.AddFotoramaVideoEvents', {\n        options: {\n            videoData: '',\n            videoSettings: '',\n            optionsVideoData: '',\n            dataMergeStrategy: 'replace'\n        },\n\n        /**\n         * @private\n         */\n        onVimeoJSFramework: function () {},\n        defaultVideoData: [],\n        PV: 'product-video', // [CONST]\n        VU: 'video-unplayed',\n        PVLOADED: 'fotorama__product-video--loaded', // [CONST]\n        PVLOADING: 'fotorama__product-video--loading', // [CONST]\n        VID: 'video', // [CONST]\n        VI: 'vimeo', // [CONST]\n        FTVC: 'fotorama__video-close',\n        FTAR: 'fotorama__arr',\n        fotoramaSpinner: 'fotorama__spinner',\n        fotoramaSpinnerShow: 'fotorama__spinner--show',\n        TI: 'video-thumb-icon',\n        isFullscreen: false,\n        FTCF: '[data-gallery-role=\"fotorama__fullscreen-icon\"]',\n        Base: 0, //on check for video is base this setting become true if there is any video with base role\n        MobileMaxWidth: 768,\n        GP: 'gallery-placeholder', //gallery placeholder class is needed to find and erase <script> tag\n        videoData: null,\n        videoDataPlaceholder: [{\n            id: '',\n            isBase: true,\n            mediaType: 'image',\n            provider: ''\n        }],\n\n        /**\n         * Creates widget\n         * @private\n         */\n        _create: function () {\n            $(this.element).data('gallery') ?\n                this._onGalleryLoaded() :\n                $(this.element).on('gallery:loaded', this._onGalleryLoaded.bind(this));\n        },\n\n        /**\n         *\n         * @private\n         */\n        _initialize: function () {\n            if (!this.defaultVideoData.length) {\n                this.defaultVideoData = this.options.videoData;\n            }\n\n            // If product does not have images, no video data generated,\n            // but for configurable product we still need a video data, in case of 'prepend' gallery strategy.\n            if (!this.defaultVideoData.length && !this.options.videoData.length) {\n                this.defaultVideoData = this.options.videoData = this.videoDataPlaceholder;\n            }\n\n            this.clearEvents();\n\n            if (this._checkForVideoExist()) {\n                this._checkFullscreen();\n                this._listenForFullscreen();\n                this._isVideoBase();\n                this._initFotoramaVideo();\n                this._attachFotoramaEvents();\n            }\n        },\n\n        /**\n         * Callback which fired after gallery gets initialized.\n         */\n        _onGalleryLoaded: function () {\n            this.fotoramaItem = $(this.element).find('.fotorama-item');\n            this._initialize();\n        },\n\n        /**\n         * Clear gallery events to prevent duplicated calls.\n         *\n         * @private\n         */\n        clearEvents: function () {\n            if (this.fotoramaItem !== undefined) {\n                this.fotoramaItem.off(\n                    'fotorama:show.' + this.PV +\n                    ' fotorama:showend.' + this.PV +\n                    ' fotorama:fullscreenenter.' + this.PV +\n                    ' fotorama:fullscreenexit.' + this.PV\n                );\n            }\n        },\n\n        /**\n         *\n         * @param {Object} options\n         * @private\n         */\n        _setOptions: function (options) {\n            if (options.videoData && options.videoData.length) {\n                this.options.videoData = options.videoData;\n            }\n\n            this._loadVideoData(options);\n            this._initialize();\n        },\n\n        /**\n         * Set video data for configurable product.\n         *\n         * @param {Object} options\n         * @private\n         */\n        _loadVideoData: function (options) {\n            if (options.selectedOption) {\n                if (options.dataMergeStrategy === 'prepend') {\n                    this.options.videoData = [].concat(\n                        this.options.optionsVideoData[options.selectedOption],\n                        this.defaultVideoData\n                    );\n                } else {\n                    this.options.videoData = this.options.optionsVideoData[options.selectedOption];\n                }\n            } else {\n                this.options.videoData = this.defaultVideoData;\n            }\n        },\n\n        /**\n         *\n         * @private\n         */\n        _checkFullscreen: function () {\n            if (this.fotoramaItem.data('fotorama').fullScreen || false) {\n                this.isFullscreen = true;\n            }\n        },\n\n        /**\n         *\n         * @private\n         */\n        _listenForFullscreen: function () {\n            this.fotoramaItem.on('fotorama:fullscreenenter.' + this.PV, $.proxy(function () {\n                this.isFullscreen = true;\n            }, this));\n\n            this.fotoramaItem.on('fotorama:fullscreenexit.' + this.PV, $.proxy(function () {\n                this.isFullscreen = false;\n                this._hideVideoArrows();\n            }, this));\n        },\n\n        /**\n         *\n         * @param {Object} inputData\n         * @param {bool} isJSON\n         * @returns {{}}\n         * @private\n         */\n        _createVideoData: function (inputData, isJSON) {\n            var videoData = [],\n                dataUrl,\n                tmpVideoData,\n                tmpInputData,\n                i;\n\n            if (isJSON) {\n                inputData = JSON.parse(inputData);\n            }\n\n            for (i = 0; i < inputData.length; i++) {\n                tmpInputData = inputData[i];\n                dataUrl = '';\n                tmpVideoData = {\n                    mediaType: '',\n                    isBase: '',\n                    id: '',\n                    provider: ''\n                };\n                tmpVideoData.mediaType = this.VID;\n\n                if (tmpInputData.mediaType !== 'external-video') {\n                    tmpVideoData.mediaType = tmpInputData.mediaType;\n                }\n\n                tmpVideoData.isBase = tmpInputData.isBase;\n\n                if (tmpInputData.videoUrl && tmpInputData.videoUrl !== null) {\n                    dataUrl = tmpInputData.videoUrl;\n                    dataUrl = parseURL(dataUrl);\n                    tmpVideoData.id = dataUrl.id;\n                    tmpVideoData.provider = dataUrl.type;\n                    tmpVideoData.videoUrl = tmpInputData.videoUrl;\n                    tmpVideoData.useYoutubeNocookie = dataUrl.useYoutubeNocookie;\n                }\n\n                videoData.push(tmpVideoData);\n            }\n\n            return videoData;\n        },\n\n        /**\n         *\n         * @param {Object} fotorama\n         * @param {bool} isBase\n         * @private\n         */\n        _createCloseVideo: function (fotorama, isBase) {\n            var closeVideo;\n\n            this.fotoramaItem.find('.' + this.FTVC).remove();\n            this.fotoramaItem.append('<div class=\"' + this.FTVC + '\"></div>');\n            this.fotoramaItem.css('position', 'relative');\n            closeVideo = this.fotoramaItem.find('.' + this.FTVC);\n            this._closeVideoSetEvents(closeVideo, fotorama);\n\n            if (\n                isBase &&\n                this.options.videoData[fotorama.activeIndex].isBase &&\n                $(window).width() > this.MobileMaxWidth) {\n                this._showCloseVideo();\n            }\n        },\n\n        /**\n         *\n         * @private\n         */\n        _hideCloseVideo: function () {\n            this.fotoramaItem\n                .find('.' + this.FTVC)\n                .removeClass('fotorama-show-control');\n        },\n\n        /**\n         *\n         * @private\n         */\n        _showCloseVideo: function () {\n            this.fotoramaItem\n                .find('.' + this.FTVC)\n                .addClass('fotorama-show-control');\n        },\n\n        /**\n         *\n         * @param {jQuery} $closeVideo\n         * @param {jQuery} fotorama\n         * @private\n         */\n        _closeVideoSetEvents: function ($closeVideo, fotorama) {\n            $closeVideo.on('click', $.proxy(function () {\n                this._unloadVideoPlayer(fotorama.activeFrame.$stageFrame.parent(), fotorama, true);\n                this._hideCloseVideo();\n            }, this));\n        },\n\n        /**\n         *\n         * @returns {Boolean}\n         * @private\n         */\n        _checkForVideoExist: function () {\n            var key, result, checker, videoSettings;\n\n            if (!this.options.videoData) {\n                return false;\n            }\n\n            if (!this.options.videoSettings) {\n                return false;\n            }\n\n            result = this._createVideoData(this.options.videoData, false);\n            checker = false;\n            videoSettings = this.options.videoSettings[0];\n            videoSettings.playIfBase = parseInt(videoSettings.playIfBase, 10);\n            videoSettings.showRelated = parseInt(videoSettings.showRelated, 10);\n            videoSettings.videoAutoRestart = parseInt(videoSettings.videoAutoRestart, 10);\n\n            for (key in result) {\n                if (result[key].mediaType === this.VID) {\n                    checker = true;\n                }\n            }\n\n            if (checker) {\n                this.options.videoData = result;\n            }\n\n            return checker;\n        },\n\n        /**\n         *\n         * @private\n         */\n        _isVideoBase: function () {\n            var allVideoData = this.options.videoData,\n                videoItem,\n                allVideoDataKeys,\n                key,\n                i;\n\n            allVideoDataKeys = Object.keys(allVideoData);\n\n            for (i = 0; i < allVideoDataKeys.length; i++) {\n                key = allVideoDataKeys[i];\n                videoItem = allVideoData[key];\n\n                if (\n                    videoItem.mediaType === this.VID && videoItem.isBase &&\n                    this.options.videoSettings[0].playIfBase && allowBase\n                ) {\n                    this.Base = true;\n                    allowBase = false;\n                }\n            }\n\n            if (!this.isFullscreen) {\n                this._createCloseVideo(this.fotoramaItem.data('fotorama'), this.Base);\n            }\n        },\n\n        /**\n         *\n         * @param {Event} e\n         * @private\n         */\n        _initFotoramaVideo: function (e) {\n            var fotorama = this.fotoramaItem.data('fotorama'),\n                thumbsParent,\n                thumbs,\n                t;\n\n            if (!fotorama.activeFrame.$navThumbFrame) {\n                this.fotoramaItem.on('fotorama:showend.' + this.PV, $.proxy(function (evt, fotoramaData) {\n                    $(fotoramaData.activeFrame.$stageFrame).removeAttr('href');\n                }, this));\n\n                this._startPrepareForPlayer(e, fotorama);\n\n                return null;\n            }\n\n            fotorama.data.map($.proxy(this._setItemType, this));\n            thumbsParent = fotorama.activeFrame.$navThumbFrame.parent();\n            thumbs = thumbsParent.find('.fotorama__nav__frame:visible');\n\n            for (t = 0; t < thumbs.length; t++) {\n                this._setThumbsIcon(thumbs.eq(t), t);\n                this._checkForVideo(e, fotorama, t + 1);\n            }\n\n            this.fotoramaItem.on('fotorama:showend.' + this.PV, $.proxy(function (evt, fotoramaData) {\n                $(fotoramaData.activeFrame.$stageFrame).removeAttr('href');\n            }, this));\n        },\n\n        /**\n         *\n         * @param {Object} elem\n         * @param {Number} i\n         * @private\n         */\n        _setThumbsIcon: function (elem, i) {\n            var fotorama = this.fotoramaItem.data('fotorama');\n\n            if (fotorama.options.nav === 'dots' && elem.hasClass(this.TI)) {\n                elem.removeClass(this.TI);\n            }\n\n            if (this.options.videoData[i].mediaType === this.VID &&\n                fotorama.data[i].type ===  this.VID &&\n                fotorama.options.nav === 'thumbs') {\n                elem.addClass(this.TI);\n            }\n        },\n\n        /**\n         * Temporary solution with adding types for configurable product items\n         *\n         * @param {Object} item\n         * @param {Number} i\n         * @private\n         */\n        _setItemType: function (item, i) {\n            !item.type && (item.type = this.options.videoData[i].mediaType);\n        },\n\n        /**\n         * Attach\n         *\n         * @private\n         */\n        _attachFotoramaEvents: function () {\n            this.fotoramaItem.on('fotorama:showend.' + this.PV, $.proxy(function (e, fotorama) {\n                this._startPrepareForPlayer(e, fotorama);\n            }, this));\n\n            this.fotoramaItem.on('fotorama:show.' + this.PV, $.proxy(function (e, fotorama) {\n                this._unloadVideoPlayer(fotorama.activeFrame.$stageFrame.parent(), fotorama, true);\n            }, this));\n\n            this.fotoramaItem.on('fotorama:fullscreenexit.' + this.PV, $.proxy(function (e, fotorama) {\n                fotorama.activeFrame.$stageFrame.find('.' + this.PV).remove();\n                this._startPrepareForPlayer(e, fotorama);\n            }, this));\n        },\n\n        /**\n         * Start prepare for player\n         *\n         * @param {Event} e\n         * @param {jQuery} fotorama\n         * @private\n         */\n        _startPrepareForPlayer: function (e, fotorama) {\n            this._unloadVideoPlayer(fotorama.activeFrame.$stageFrame.parent(), fotorama, false);\n            this._checkForVideo(e, fotorama, fotorama.activeFrame.i);\n            this._checkForVideo(e, fotorama, fotorama.activeFrame.i - 1);\n            this._checkForVideo(e, fotorama, fotorama.activeFrame.i + 1);\n        },\n\n        /**\n         * Check for video\n         *\n         * @param {Event} e\n         * @param {jQuery} fotorama\n         * @param {Number} number\n         * @private\n         */\n        _checkForVideo: function (e, fotorama, number) {\n            var videoData = this.options.videoData[number - 1],\n                $image = fotorama.data[number - 1];\n\n            if ($image) {\n                !$image.type && this._setItemType($image, number - 1);\n\n                if ($image.type === 'image') {\n                    $image.$navThumbFrame && $image.$navThumbFrame.removeClass(this.TI);\n                    this._hideCloseVideo();\n\n                    return;\n                } else if ($image.$navThumbFrame && $image.type === 'video') {\n                    !$image.$navThumbFrame.hasClass(this.TI) && $image.$navThumbFrame.addClass(this.TI);\n                }\n\n                $image = $image.$stageFrame;\n            }\n\n            if ($image && videoData && videoData.mediaType === this.VID) {\n                $(fotorama.activeFrame.$stageFrame).removeAttr('href');\n                this._prepareForVideoContainer($image, videoData, fotorama, number);\n            }\n\n            if (this.isFullscreen && this.fotoramaItem.data('fotorama').activeFrame.i === number) {\n                this.fotoramaItem.data('fotorama').activeFrame.$stageFrame.trigger('click');\n            }\n        },\n\n        /**\n         * Prepare for video container\n         *\n         * @param {jQuery} $image\n         * @param {Object} videoData\n         * @param {Object} fotorama\n         * @param {Number} number\n         * @private\n         */\n        _prepareForVideoContainer: function ($image, videoData, fotorama, number) {\n            $image.addClass('fotorama-video-container').addClass(this.VU);\n            this._createVideoContainer(videoData, $image);\n            this._setVideoEvent($image, this.PV, fotorama, number);\n        },\n\n        /**\n         * Create video container\n         *\n         * @param {Object} videoData\n         * @param {jQuery} $image\n         * @private\n         */\n        _createVideoContainer: function (videoData, $image) {\n            var videoSettings;\n\n            videoSettings = this.options.videoSettings[0];\n            $image.find('.' + this.PV).remove();\n            $image.append(\n                '<div class=\"' +\n                this.PV +\n                '\" data-related=\"' +\n                videoSettings.showRelated +\n                '\" data-loop=\"' +\n                videoSettings.videoAutoRestart +\n                '\" data-type=\"' +\n                videoData.provider +\n                '\" data-code=\"' +\n                videoData.id +\n                '\"  data-youtubenocookie=\"' +\n                videoData.useYoutubeNocookie +\n                '\" data-width=\"100%\" data-height=\"100%\"></div>'\n            );\n        },\n\n        /**\n         *\n         * @param {Object} $image\n         * @param {Object} PV\n         * @param {Object} fotorama\n         * @param {Number} number\n         * @private\n         */\n        _setVideoEvent: function ($image, PV, fotorama, number) {\n            $image.find('.magnify-lens').remove();\n            $image\n                .off('click tap', $.proxy(this._clickHandler, this))\n                .on('click tap', $.proxy(this._clickHandler, this));\n            this._handleBaseVideo(fotorama, number); //check for video is it base and handle it if it's base\n        },\n\n        /**\n         * Hides preview arrows above video player.\n         * @private\n         */\n        _hideVideoArrows: function () {\n            var arrows = $('.' + this.FTAR);\n\n            arrows.removeClass('fotorama__arr--shown');\n            arrows.removeClass('fotorama__arr--hidden');\n        },\n\n        /**\n         * @private\n         */\n        _showLoader: function () {\n            var spinner = this.fotoramaItem.find('.' + this.fotoramaSpinner);\n\n            spinner.addClass(this.fotoramaSpinnerShow);\n            this.fotoramaItem.data('fotorama').activeFrame.$stageFrame.addClass(this.PVLOADING);\n        },\n\n        /**\n         * @private\n         */\n        _hideLoader: function () {\n            var spinner = this.fotoramaItem.find('.' + this.fotoramaSpinner);\n\n            spinner.removeClass(this.fotoramaSpinnerShow);\n            this.fotoramaItem.data('fotorama').activeFrame.$stageFrame.removeClass(this.PVLOADING);\n        },\n\n        /**\n         * @param {Event} event\n         * @private\n         */\n        _clickHandler: function (event) {\n            var type;\n\n            if ($(event.target).hasClass(this.VU) && $(event.target).find('iframe').length === 0) {\n                $(event.target).removeClass(this.VU);\n                type = $(event.target).find('.' + this.PV).data('type');\n\n                if (type === this.VI) {\n                    $(event.target).find('.' + this.PV).productVideoLoader();\n                } else if (type === this.VI) {\n                    this._showLoader();\n                    this.onVimeoJSFramework = function () {\n                        $(event.target).find('.' + this.PV).productVideoLoader();\n                        this._hideLoader();\n                    }.bind(this);\n                } else {\n                    $(event.target).find('.' + this.PV).productVideoLoader();\n                }\n\n                $('.' + this.FTAR).addClass(this.isFullscreen ? 'fotorama__arr--shown' : 'fotorama__arr--hidden');\n                $('.' + this.FTVC).addClass('fotorama-show-control');\n            }\n        },\n\n        /**\n         * Handle base video\n         * @param {Object} fotorama\n         * @param {Number} srcNumber\n         * @private\n         */\n        _handleBaseVideo: function (fotorama, srcNumber) {\n            var videoData = this.options.videoData,\n                activeIndex = fotorama.activeIndex,\n                number = parseInt(srcNumber, 10),\n                activeIndexIsBase = videoData[activeIndex];\n\n            if (!this.Base) {\n                return;\n            }\n\n            if (activeIndexIsBase && number === 1 && $(window).width() > this.MobileMaxWidth) {\n                setTimeout($.proxy(function () {\n                    fotorama.requestFullScreen();\n                    this.fotoramaItem.data('fotorama').activeFrame.$stageFrame.trigger('click');\n                    this.Base = false;\n                }, this), 50);\n            }\n        },\n\n        /**\n         * Destroy video player\n         * @param {jQuery} $wrapper\n         * @param {jQuery} current\n         * @param {bool} close\n         * @private\n         */\n        _unloadVideoPlayer: function ($wrapper, current, close) {\n            var self = this;\n\n            if (!$wrapper) {\n                return;\n            }\n\n            $wrapper.find('.' + this.PVLOADED).removeClass(this.PVLOADED);\n            this._hideLoader();\n\n            $wrapper.find('.' + this.PV).each(function () {\n                var $item = $(this).parent(),\n                    cloneVideoDiv,\n                    iframeElement = $(this).find('iframe'),\n                    currentIndex,\n                    itemIndex;\n\n                if (iframeElement.length === 0) {\n                    return;\n                }\n\n                currentIndex = current.activeFrame.$stageFrame.index();\n                itemIndex = $item.index();\n\n                if (currentIndex === itemIndex && !close) {\n                    return;\n                }\n\n                if (currentIndex !== itemIndex && close) {\n                    return;\n                }\n\n                iframeElement.remove();\n                cloneVideoDiv = $(this).clone();\n                $(this).remove();\n                $item.append(cloneVideoDiv);\n                $item.addClass(self.VU);\n\n                self._hideCloseVideo();\n                self._hideVideoArrows();\n\n                if (self.isFullscreen && !self.fotoramaItem.data('fotorama').options.fullscreen.arrows) {\n                    if ($('.' + self.FTAR + '--prev').is(':focus') || $('.' + self.FTAR + '--next').is(':focus')) {\n                        $(self.FTCF).trigger('focus');\n                    }\n                }\n            });\n        }\n    });\n\n    return $.mage.AddFotoramaVideoEvents;\n});\n","Magento_Checkout/js/empty-cart.js":"/**\n * Copyright \u00a9 Magento, Inc. All rights reserved.\n * See COPYING.txt for license details.\n */\n\ndefine(['Magento_Customer/js/customer-data'], function (customerData) {\n    'use strict';\n\n    return function () {\n        var cartData = customerData.get('cart');\n\n        customerData.getInitCustomerData().done(function () {\n            if (cartData().items && cartData().items.length !== 0) {\n                customerData.reload(['cart'], false);\n            }\n        });\n    };\n});\n","Magento_Checkout/js/proceed-to-checkout.js":"/**\n * Copyright \u00a9 Magento, Inc. All rights reserved.\n * See COPYING.txt for license details.\n */\n\ndefine([\n    'jquery',\n    'Magento_Customer/js/model/authentication-popup',\n    'Magento_Customer/js/customer-data'\n], function ($, authenticationPopup, customerData) {\n    'use strict';\n\n    return function (config, element) {\n        $(element).on('click', function (event) {\n            var cart = customerData.get('cart'),\n                customer = customerData.get('customer');\n\n            event.preventDefault();\n\n            if (!customer().firstname && cart().isGuestCheckoutAllowed === false) {\n                authenticationPopup.showModal();\n\n                return false;\n            }\n            $(element).attr('disabled', true);\n            location.href = config.checkoutUrl;\n        });\n\n    };\n});\n","Magento_Checkout/js/shopping-cart.js":"/**\n * Copyright \u00a9 Magento, Inc. All rights reserved.\n * See COPYING.txt for license details.\n */\n\ndefine([\n    'jquery',\n    'Magento_Ui/js/modal/confirm',\n    'jquery-ui-modules/widget',\n    'mage/translate'\n], function ($, confirm) {\n    'use strict';\n\n    $.widget('mage.shoppingCart', {\n        /** @inheritdoc */\n        _create: function () {\n            var items, i, reload;\n\n            $(this.options.emptyCartButton).on('click', $.proxy(function () {\n                this._confirmClearCart();\n            }, this));\n            items = $.find('[data-role=\"cart-item-qty\"]');\n\n            for (i = 0; i < items.length; i++) {\n                $(items[i]).on('keypress', $.proxy(function (event) { //eslint-disable-line no-loop-func\n                    var keyCode = event.keyCode ? event.keyCode : event.which;\n\n                    if (keyCode == 13) { //eslint-disable-line eqeqeq\n                        $(this.options.emptyCartButton).attr('name', 'update_cart_action_temp');\n                        $(this.options.updateCartActionContainer)\n                            .attr('name', 'update_cart_action').attr('value', 'update_qty');\n\n                    }\n                }, this));\n            }\n            $(this.options.continueShoppingButton).on('click', $.proxy(function () {\n                location.href = this.options.continueShoppingUrl;\n            }, this));\n\n            $(document).on('ajax:removeFromCart', $.proxy(function () {\n                reload = true;\n                $('div.block.block-minicart').on('dropdowndialogclose', $.proxy(function () {\n                    if (reload === true) {\n                        location.reload();\n                        reload = false;\n                    }\n                    $('div.block.block-minicart').off('dropdowndialogclose');\n                }));\n            }, this));\n            $(document).on('ajax:updateItemQty', $.proxy(function () {\n                reload = true;\n                $('div.block.block-minicart').on('dropdowndialogclose', $.proxy(function () {\n                    if (reload === true) {\n                        location.reload();\n                        reload = false;\n                    }\n                    $('div.block.block-minicart').off('dropdowndialogclose');\n                }));\n            }, this));\n        },\n\n        /**\n         * Display confirmation modal for clearing the cart\n         * @private\n         */\n        _confirmClearCart: function () {\n            var self = this;\n\n            confirm({\n                content: $.mage.__('Are you sure you want to remove all items from your shopping cart?'),\n                actions: {\n                    /**\n                     * Confirmation modal handler to execute clear cart action\n                     */\n                    confirm: function () {\n                        self.clearCart();\n                    }\n                }\n            });\n        },\n\n        /**\n         * Prepares the form and submit to clear the cart\n         * @public\n         */\n        clearCart: function () {\n            $(this.options.emptyCartButton).attr('name', 'update_cart_action_temp');\n            $(this.options.updateCartActionContainer)\n                .attr('name', 'update_cart_action').attr('value', 'empty_cart');\n\n            if ($(this.options.emptyCartButton).parents('form').length > 0) {\n                $(this.options.emptyCartButton).parents('form').trigger('submit');\n            }\n        }\n    });\n\n    return $.mage.shoppingCart;\n});\n","Magento_Checkout/js/checkout-data.js":"/**\n * Copyright \u00a9 Magento, Inc. All rights reserved.\n * See COPYING.txt for license details.\n */\n\n/**\n * Checkout adapter for customer data storage\n *\n * @api\n */\ndefine([\n    'jquery',\n    'Magento_Customer/js/customer-data',\n    'mageUtils',\n    'jquery/jquery-storageapi'\n], function ($, storage, utils) {\n    'use strict';\n\n    var cacheKey = 'checkout-data',\n\n        /**\n         * @param {Object} data\n         */\n        saveData = function (data) {\n            storage.set(cacheKey, data);\n        },\n\n        /**\n         * @return {*}\n         */\n        initData = function () {\n            return {\n                'selectedShippingAddress': null, //Selected shipping address pulled from persistence storage\n                'shippingAddressFromData': null, //Shipping address pulled from persistence storage\n                'newCustomerShippingAddress': null, //Shipping address pulled from persistence storage for customer\n                'selectedShippingRate': null, //Shipping rate pulled from persistence storage\n                'selectedPaymentMethod': null, //Payment method pulled from persistence storage\n                'selectedBillingAddress': null, //Selected billing address pulled from persistence storage\n                'billingAddressFromData': null, //Billing address pulled from persistence storage\n                'newCustomerBillingAddress': null //Billing address pulled from persistence storage for new customer\n            };\n        },\n\n        /**\n         * @return {*}\n         */\n        getData = function () {\n            var data = storage.get(cacheKey)();\n\n            if ($.isEmptyObject(data)) {\n                data = $.initNamespaceStorage('mage-cache-storage').localStorage.get(cacheKey);\n\n                if ($.isEmptyObject(data)) {\n                    data = initData();\n                    saveData(data);\n                }\n            }\n\n            return data;\n        };\n\n    return {\n        /**\n         * Setting the selected shipping address pulled from persistence storage\n         *\n         * @param {Object} data\n         */\n        setSelectedShippingAddress: function (data) {\n            var obj = getData();\n\n            obj.selectedShippingAddress = data;\n            saveData(obj);\n        },\n\n        /**\n         * Pulling the selected shipping address from persistence storage\n         *\n         * @return {*}\n         */\n        getSelectedShippingAddress: function () {\n            return getData().selectedShippingAddress;\n        },\n\n        /**\n         * Setting the shipping address pulled from persistence storage\n         *\n         * @param {Object} data\n         */\n        setShippingAddressFromData: function (data) {\n            var obj = getData();\n\n            obj.shippingAddressFromData = utils.filterFormData(data);\n            saveData(obj);\n        },\n\n        /**\n         * Pulling the shipping address from persistence storage\n         *\n         * @return {*}\n         */\n        getShippingAddressFromData: function () {\n            return getData().shippingAddressFromData;\n        },\n\n        /**\n         * Setting the shipping address pulled from persistence storage for new customer\n         *\n         * @param {Object} data\n         */\n        setNewCustomerShippingAddress: function (data) {\n            var obj = getData();\n\n            obj.newCustomerShippingAddress = data;\n            saveData(obj);\n        },\n\n        /**\n         * Pulling the shipping address from persistence storage for new customer\n         *\n         * @return {*}\n         */\n        getNewCustomerShippingAddress: function () {\n            return getData().newCustomerShippingAddress;\n        },\n\n        /**\n         * Setting the selected shipping rate pulled from persistence storage\n         *\n         * @param {Object} data\n         */\n        setSelectedShippingRate: function (data) {\n            var obj = getData();\n\n            obj.selectedShippingRate = data;\n            saveData(obj);\n        },\n\n        /**\n         * Pulling the selected shipping rate from local storage\n         *\n         * @return {*}\n         */\n        getSelectedShippingRate: function () {\n            return getData().selectedShippingRate;\n        },\n\n        /**\n         * Setting the selected payment method pulled from persistence storage\n         *\n         * @param {Object} data\n         */\n        setSelectedPaymentMethod: function (data) {\n            var obj = getData();\n\n            obj.selectedPaymentMethod = data;\n            saveData(obj);\n        },\n\n        /**\n         * Pulling the payment method from persistence storage\n         *\n         * @return {*}\n         */\n        getSelectedPaymentMethod: function () {\n            return getData().selectedPaymentMethod;\n        },\n\n        /**\n         * Setting the selected billing address pulled from persistence storage\n         *\n         * @param {Object} data\n         */\n        setSelectedBillingAddress: function (data) {\n            var obj = getData();\n\n            obj.selectedBillingAddress = data;\n            saveData(obj);\n        },\n\n        /**\n         * Pulling the selected billing address from persistence storage\n         *\n         * @return {*}\n         */\n        getSelectedBillingAddress: function () {\n            return getData().selectedBillingAddress;\n        },\n\n        /**\n         * Setting the billing address pulled from persistence storage\n         *\n         * @param {Object} data\n         */\n        setBillingAddressFromData: function (data) {\n            var obj = getData();\n\n            obj.billingAddressFromData = utils.filterFormData(data);\n            saveData(obj);\n        },\n\n        /**\n         * Pulling the billing address from persistence storage\n         *\n         * @return {*}\n         */\n        getBillingAddressFromData: function () {\n            return getData().billingAddressFromData;\n        },\n\n        /**\n         * Setting the billing address pulled from persistence storage for new customer\n         *\n         * @param {Object} data\n         */\n        setNewCustomerBillingAddress: function (data) {\n            var obj = getData();\n\n            obj.newCustomerBillingAddress = data;\n            saveData(obj);\n        },\n\n        /**\n         * Pulling the billing address from persistence storage for new customer\n         *\n         * @return {*}\n         */\n        getNewCustomerBillingAddress: function () {\n            return getData().newCustomerBillingAddress;\n        },\n\n        /**\n         * Pulling the email address from persistence storage\n         *\n         * @return {*}\n         */\n        getValidatedEmailValue: function () {\n            var obj = getData();\n\n            return obj.validatedEmailValue ? obj.validatedEmailValue : '';\n        },\n\n        /**\n         * Setting the email address pulled from persistence storage\n         *\n         * @param {String} email\n         */\n        setValidatedEmailValue: function (email) {\n            var obj = getData();\n\n            obj.validatedEmailValue = email;\n            saveData(obj);\n        },\n\n        /**\n         * Pulling the email input field value from persistence storage\n         *\n         * @return {*}\n         */\n        getInputFieldEmailValue: function () {\n            var obj = getData();\n\n            return obj.inputFieldEmailValue ? obj.inputFieldEmailValue : '';\n        },\n\n        /**\n         * Setting the email input field value pulled from persistence storage\n         *\n         * @param {String} email\n         */\n        setInputFieldEmailValue: function (email) {\n            var obj = getData();\n\n            obj.inputFieldEmailValue = email;\n            saveData(obj);\n        },\n\n        /**\n         * Pulling the checked email value from persistence storage\n         *\n         * @return {*}\n         */\n        getCheckedEmailValue: function () {\n            var obj = getData();\n\n            return obj.checkedEmailValue ? obj.checkedEmailValue : '';\n        },\n\n        /**\n         * Setting the checked email value pulled from persistence storage\n         *\n         * @param {String} email\n         */\n        setCheckedEmailValue: function (email) {\n            var obj = getData();\n\n            obj.checkedEmailValue = email;\n            saveData(obj);\n        }\n    };\n});\n","Magento_Checkout/js/checkout-loader.js":"/**\n * Copyright \u00a9 Magento, Inc. All rights reserved.\n * See COPYING.txt for license details.\n */\ndefine([\n    'rjsResolver'\n], function (resolver) {\n    'use strict';\n\n    /**\n     * Removes provided loader element from DOM.\n     *\n     * @param {HTMLElement} $loader - Loader DOM element.\n     */\n    function hideLoader($loader) {\n        $loader.parentNode.removeChild($loader);\n    }\n\n    /**\n     * Initializes assets loading process listener.\n     *\n     * @param {Object} config - Optional configuration\n     * @param {HTMLElement} $loader - Loader DOM element.\n     */\n    function init(config, $loader) {\n        resolver(hideLoader.bind(null, $loader));\n    }\n\n    return init;\n});\n","Magento_Checkout/js/discount-codes.js":"/**\n * Copyright \u00a9 Magento, Inc. All rights reserved.\n * See COPYING.txt for license details.\n */\n\ndefine([\n    'jquery',\n    'jquery-ui-modules/widget'\n], function ($) {\n    'use strict';\n\n    $.widget('mage.discountCode', {\n        options: {\n        },\n\n        /** @inheritdoc */\n        _create: function () {\n            this.couponCode = $(this.options.couponCodeSelector);\n            this.removeCoupon = $(this.options.removeCouponSelector);\n\n            $(this.options.applyButton).on('click', $.proxy(function () {\n                this.couponCode.attr('data-validate', '{required:true}');\n                this.removeCoupon.attr('value', '0');\n                $(this.element).validation().trigger('submit');\n            }, this));\n\n            $(this.options.cancelButton).on('click', $.proxy(function () {\n                this.couponCode.removeAttr('data-validate');\n                this.removeCoupon.attr('value', '1');\n                this.element.trigger('submit');\n            }, this));\n        }\n    });\n\n    return $.mage.discountCode;\n});\n","Magento_Checkout/js/region-updater.js":"/**\n * Copyright \u00a9 Magento, Inc. All rights reserved.\n * See COPYING.txt for license details.\n */\n\ndefine([\n    'jquery',\n    'mage/template',\n    'underscore',\n    'jquery-ui-modules/widget',\n    'mage/validation'\n], function ($, mageTemplate, _) {\n    'use strict';\n\n    $.widget('mage.regionUpdater', {\n        options: {\n            regionTemplate:\n                '<option value=\"<%- data.value %>\" <% if (data.isSelected) { %>selected=\"selected\"<% } %>>' +\n                    '<%- data.title %>' +\n                '</option>',\n            isRegionRequired: true,\n            isZipRequired: true,\n            isCountryRequired: true,\n            currentRegion: null,\n            isMultipleCountriesAllowed: true\n        },\n\n        /**\n         *\n         * @private\n         */\n        _create: function () {\n            this._initCountryElement();\n\n            this.currentRegionOption = this.options.currentRegion;\n            this.regionTmpl = mageTemplate(this.options.regionTemplate);\n\n            this._updateRegion(this.element.find('option:selected').val());\n\n            $(this.options.regionListId).on('change', $.proxy(function (e) {\n                this.setOption = false;\n                this.currentRegionOption = $(e.target).val();\n            }, this));\n\n            $(this.options.regionInputId).on('focusout', $.proxy(function () {\n                this.setOption = true;\n            }, this));\n        },\n\n        /**\n         *\n         * @private\n         */\n        _initCountryElement: function () {\n\n            if (this.options.isMultipleCountriesAllowed) {\n                this.element.parents('div.field').show();\n                this.element.on('change', $.proxy(function (e) {\n                    // clear region inputs on country change\n                    $(this.options.regionListId).val('');\n                    $(this.options.regionInputId).val('');\n                    this._updateRegion($(e.target).val());\n                }, this));\n\n                if (this.options.isCountryRequired) {\n                    this.element.addClass('required-entry');\n                    this.element.parents('div.field').addClass('required');\n                }\n            } else {\n                this.element.parents('div.field').hide();\n            }\n        },\n\n        /**\n         * Remove options from dropdown list\n         *\n         * @param {Object} selectElement - jQuery object for dropdown list\n         * @private\n         */\n        _removeSelectOptions: function (selectElement) {\n            selectElement.find('option').each(function (index) {\n                if (index) {\n                    $(this).remove();\n                }\n            });\n        },\n\n        /**\n         * Render dropdown list\n         * @param {Object} selectElement - jQuery object for dropdown list\n         * @param {String} key - region code\n         * @param {Object} value - region object\n         * @private\n         */\n        _renderSelectOption: function (selectElement, key, value) {\n            selectElement.append($.proxy(function () {\n                var name = value.name.replace(/[!\"#$%&'()*+,.\\/:;<=>?@[\\\\\\]^`{|}~]/g, '\\\\$&'),\n                    tmplData,\n                    tmpl;\n\n                if (value.code && $(name).is('span')) {\n                    key = value.code;\n                    value.name = $(name).text();\n                }\n\n                tmplData = {\n                    value: key,\n                    title: value.name,\n                    isSelected: false\n                };\n\n                if (this.options.defaultRegion === key) {\n                    tmplData.isSelected = true;\n                }\n\n                tmpl = this.regionTmpl({\n                    data: tmplData\n                });\n\n                return $(tmpl);\n            }, this));\n        },\n\n        /**\n         * Takes clearError callback function as first option\n         * If no form is passed as option, look up the closest form and call clearError method.\n         * @private\n         */\n        _clearError: function () {\n            var args = ['clearError', this.options.regionListId, this.options.regionInputId, this.options.postcodeId];\n\n            if (this.options.clearError && typeof this.options.clearError === 'function') {\n                this.options.clearError.call(this);\n            } else {\n                if (!this.options.form) {\n                    this.options.form = this.element.closest('form').length ? $(this.element.closest('form')[0]) : null;\n                }\n\n                this.options.form = $(this.options.form);\n\n                this.options.form && this.options.form.data('validator') &&\n                    this.options.form.validation.apply(this.options.form, _.compact(args));\n\n                // Clean up errors on region & zip fix\n                $(this.options.regionInputId).removeClass('mage-error').parent().find('.mage-error').remove();\n                $(this.options.regionListId).removeClass('mage-error').parent().find('.mage-error').remove();\n                $(this.options.postcodeId).removeClass('mage-error').parent().find('.mage-error').remove();\n            }\n        },\n\n        /**\n         * Update dropdown list based on the country selected\n         *\n         * @param {String} country - 2 uppercase letter for country code\n         * @private\n         */\n        _updateRegion: function (country) {\n            // Clear validation error messages\n            var regionList = $(this.options.regionListId),\n                regionInput = $(this.options.regionInputId),\n                postcode = $(this.options.postcodeId),\n                label = regionList.parent().siblings('label'),\n                container = regionList.parents('div.field'),\n                regionsEntries,\n                regionId,\n                regionData;\n\n            this._clearError();\n            this._checkRegionRequired(country);\n\n            // Populate state/province dropdown list if available or use input box\n            if (this.options.regionJson[country]) {\n                this._removeSelectOptions(regionList);\n                regionsEntries = _.pairs(this.options.regionJson[country]);\n                regionsEntries.sort(function (a, b) {\n                    return a[1].name > b[1].name ? 1 : -1;\n                });\n                $.each(regionsEntries, $.proxy(function (key, value) {\n                    regionId = value[0];\n                    regionData = value[1];\n                    this._renderSelectOption(regionList, regionId, regionData);\n                }, this));\n\n                if (this.currentRegionOption) {\n                    regionList.val(this.currentRegionOption);\n                }\n\n                if (this.setOption) {\n                    regionList.find('option').filter(function () {\n                        return this.text === regionInput.val();\n                    }).attr('selected', true);\n                }\n\n                if (this.options.isRegionRequired) {\n                    regionList.addClass('required-entry').prop('disabled', false);\n                    container.addClass('required').show();\n                } else {\n                    regionList.removeClass('required-entry validate-select').removeAttr('data-validate');\n                    container.removeClass('required');\n\n                    if (!this.options.optionalRegionAllowed) { //eslint-disable-line max-depth\n                        regionList.hide();\n                        container.hide();\n                    } else {\n                        regionList.prop('disabled', false).show();\n                    }\n                }\n\n                regionList.show();\n                regionInput.hide();\n                label.attr('for', regionList.attr('id'));\n            } else {\n                this._removeSelectOptions(regionList);\n\n                if (this.options.isRegionRequired) {\n                    regionInput.addClass('required-entry').prop('disabled', false);\n                    container.addClass('required').show();\n                } else {\n                    if (!this.options.optionalRegionAllowed) { //eslint-disable-line max-depth\n                        regionInput.attr('disabled', 'disabled');\n                        container.hide();\n                    }\n                    container.removeClass('required');\n                    regionInput.removeClass('required-entry');\n                }\n\n                regionList.removeClass('required-entry').prop('disabled', 'disabled').hide();\n                regionInput.show();\n                label.attr('for', regionInput.attr('id'));\n            }\n\n            // If country is in optionalzip list, make postcode input not required\n            if (this.options.isZipRequired) {\n                $.inArray(country, this.options.countriesWithOptionalZip) >= 0 ?\n                    postcode.removeClass('required-entry').closest('.field').removeClass('required') :\n                    postcode.addClass('required-entry').closest('.field').addClass('required');\n            }\n\n            // Add defaultvalue attribute to state/province select element\n            regionList.attr('defaultvalue', this.options.defaultRegion);\n            this.options.form.find('[type=\"submit\"]').prop('disabled', false).show();\n        },\n\n        /**\n         * Check if the selected country has a mandatory region selection\n         *\n         * @param {String} country - Code of the country - 2 uppercase letter for country code\n         * @private\n         */\n        _checkRegionRequired: function (country) {\n            var self = this;\n\n            this.options.isRegionRequired = false;\n            $.each(this.options.regionJson.config['regions_required'], function (index, elem) {\n                if (elem === country) {\n                    self.options.isRegionRequired = true;\n                }\n            });\n        }\n    });\n\n    return $.mage.regionUpdater;\n});\n","Magento_Checkout/js/sidebar.js":"/**\n * Copyright \u00a9 Magento, Inc. All rights reserved.\n * See COPYING.txt for license details.\n */\n\ndefine([\n    'jquery',\n    'Magento_Customer/js/model/authentication-popup',\n    'Magento_Customer/js/customer-data',\n    'Magento_Ui/js/modal/alert',\n    'Magento_Ui/js/modal/confirm',\n    'underscore',\n    'jquery-ui-modules/widget',\n    'mage/decorate',\n    'mage/collapsible',\n    'mage/cookies',\n    'jquery-ui-modules/effect-fade'\n], function ($, authenticationPopup, customerData, alert, confirm, _) {\n    'use strict';\n\n    $.widget('mage.sidebar', {\n        options: {\n            isRecursive: true,\n            minicart: {\n                maxItemsVisible: 3\n            }\n        },\n        scrollHeight: 0,\n        shoppingCartUrl: window.checkout.shoppingCartUrl,\n\n        /**\n         * Create sidebar.\n         * @private\n         */\n        _create: function () {\n            this._initContent();\n        },\n\n        /**\n         * Update sidebar block.\n         */\n        update: function () {\n            $(this.options.targetElement).trigger('contentUpdated');\n            this._calcHeight();\n        },\n\n        /**\n         * @private\n         */\n        _initContent: function () {\n            var self = this,\n                events = {};\n\n            this.element.decorate('list', this.options.isRecursive);\n\n            /**\n             * @param {jQuery.Event} event\n             */\n            events['click ' + this.options.button.close] = function (event) {\n                event.stopPropagation();\n                $(self.options.targetElement).dropdownDialog('close');\n            };\n            events['click ' + this.options.button.checkout] = $.proxy(function () {\n                var cart = customerData.get('cart'),\n                    customer = customerData.get('customer'),\n                    element = $(this.options.button.checkout);\n\n                if (!customer().firstname && cart().isGuestCheckoutAllowed === false) {\n                    // set URL for redirect on successful login/registration. It's postprocessed on backend.\n                    $.cookie('login_redirect', this.options.url.checkout);\n\n                    if (this.options.url.isRedirectRequired) {\n                        element.prop('disabled', true);\n                        location.href = this.options.url.loginUrl;\n                    } else {\n                        authenticationPopup.showModal();\n                    }\n\n                    return false;\n                }\n                element.prop('disabled', true);\n                location.href = this.options.url.checkout;\n            }, this);\n\n            /**\n             * @param {jQuery.Event} event\n             */\n            events['click ' + this.options.button.remove] =  function (event) {\n                event.stopPropagation();\n                confirm({\n                    content: self.options.confirmMessage,\n                    actions: {\n                        /** @inheritdoc */\n                        confirm: function () {\n                            self._removeItem($(event.currentTarget));\n                        },\n\n                        /** @inheritdoc */\n                        always: function (e) {\n                            e.stopImmediatePropagation();\n                        }\n                    }\n                });\n            };\n\n            /**\n             * @param {jQuery.Event} event\n             */\n            events['keyup ' + this.options.item.qty] = function (event) {\n                self._showItemButton($(event.target));\n            };\n\n            /**\n             * @param {jQuery.Event} event\n             */\n            events['change ' + this.options.item.qty] = function (event) {\n                self._showItemButton($(event.target));\n            };\n\n            /**\n             * @param {jQuery.Event} event\n             */\n            events['click ' + this.options.item.button] = function (event) {\n                event.stopPropagation();\n                self._updateItemQty($(event.currentTarget));\n            };\n\n            /**\n             * @param {jQuery.Event} event\n             */\n            events['focusout ' + this.options.item.qty] = function (event) {\n                self._validateQty($(event.currentTarget));\n            };\n\n            this._on(this.element, events);\n            this._calcHeight();\n        },\n\n        /**\n         * @param {HTMLElement} elem\n         * @private\n         */\n        _showItemButton: function (elem) {\n            var itemId = elem.data('cart-item'),\n                itemQty = elem.data('item-qty');\n\n            if (this._isValidQty(itemQty, elem.val())) {\n                $('#update-cart-item-' + itemId).show('fade', 300);\n            } else if (elem.val() == 0) { //eslint-disable-line eqeqeq\n                this._hideItemButton(elem);\n            } else {\n                this._hideItemButton(elem);\n            }\n        },\n\n        /**\n         * @param {*} origin - origin qty. 'data-item-qty' attribute.\n         * @param {*} changed - new qty.\n         * @returns {Boolean}\n         * @private\n         */\n        _isValidQty: function (origin, changed) {\n            return origin != changed && //eslint-disable-line eqeqeq\n                changed.length > 0 &&\n                changed - 0 == changed && //eslint-disable-line eqeqeq\n                changed - 0 > 0;\n        },\n\n        /**\n         * @param {Object} elem\n         * @private\n         */\n        _validateQty: function (elem) {\n            var itemQty = elem.data('item-qty');\n\n            if (!this._isValidQty(itemQty, elem.val())) {\n                elem.val(itemQty);\n            }\n        },\n\n        /**\n         * @param {HTMLElement} elem\n         * @private\n         */\n        _hideItemButton: function (elem) {\n            var itemId = elem.data('cart-item');\n\n            $('#update-cart-item-' + itemId).hide('fade', 300);\n        },\n\n        /**\n         * @param {HTMLElement} elem\n         * @private\n         */\n        _updateItemQty: function (elem) {\n            var itemId = elem.data('cart-item');\n\n            this._ajax(this.options.url.update, {\n                'item_id': itemId,\n                'item_qty': $('#cart-item-' + itemId + '-qty').val()\n            }, elem, this._updateItemQtyAfter);\n        },\n\n        /**\n         * Update content after update qty\n         *\n         * @param {HTMLElement} elem\n         */\n        _updateItemQtyAfter: function (elem) {\n            var productData = this._getProductById(Number(elem.data('cart-item')));\n\n            if (!_.isUndefined(productData)) {\n                $(document).trigger('ajax:updateCartItemQty');\n\n                if (window.location.href === this.shoppingCartUrl) {\n                    window.location.reload(false);\n                }\n            }\n            this._hideItemButton(elem);\n        },\n\n        /**\n         * @param {HTMLElement} elem\n         * @private\n         */\n        _removeItem: function (elem) {\n            var itemId = elem.data('cart-item');\n\n            this._ajax(this.options.url.remove, {\n                'item_id': itemId\n            }, elem, this._removeItemAfter);\n        },\n\n        /**\n         * Update content after item remove\n         *\n         * @param {Object} elem\n         * @private\n         */\n        _removeItemAfter: function (elem) {\n            var productData = this._getProductById(Number(elem.data('cart-item')));\n\n            if (!_.isUndefined(productData)) {\n                $(document).trigger('ajax:removeFromCart', {\n                    productIds: [productData['product_id']],\n                    productInfo: [\n                        {\n                            'id': productData['product_id']\n                        }\n                    ]\n                });\n\n                if (window.location.href.indexOf(this.shoppingCartUrl) === 0) {\n                    window.location.reload();\n                }\n            }\n        },\n\n        /**\n         * Retrieves product data by Id.\n         *\n         * @param {Number} productId - product Id\n         * @returns {Object|undefined}\n         * @private\n         */\n        _getProductById: function (productId) {\n            return _.find(customerData.get('cart')().items, function (item) {\n                return productId === Number(item['item_id']);\n            });\n        },\n\n        /**\n         * @param {String} url - ajax url\n         * @param {Object} data - post data for ajax call\n         * @param {Object} elem - element that initiated the event\n         * @param {Function} callback - callback method to execute after AJAX success\n         */\n        _ajax: function (url, data, elem, callback) {\n            $.extend(data, {\n                'form_key': $.mage.cookies.get('form_key')\n            });\n\n            $.ajax({\n                url: url,\n                data: data,\n                type: 'post',\n                dataType: 'json',\n                context: this,\n\n                /** @inheritdoc */\n                beforeSend: function () {\n                    elem.attr('disabled', 'disabled');\n                },\n\n                /** @inheritdoc */\n                complete: function () {\n                    elem.attr('disabled', null);\n                }\n            })\n                .done(function (response) {\n                    var msg;\n\n                    if (response.success) {\n                        callback.call(this, elem, response);\n                    } else {\n                        msg = response['error_message'];\n\n                        if (msg) {\n                            alert({\n                                content: msg\n                            });\n                        }\n                    }\n                })\n                .fail(function (error) {\n                    console.log(JSON.stringify(error));\n                });\n        },\n\n        /**\n         * Calculate height of minicart list\n         *\n         * @private\n         */\n        _calcHeight: function () {\n            var self = this,\n                height = 0,\n                counter = this.options.minicart.maxItemsVisible,\n                target = $(this.options.minicart.list),\n                outerHeight;\n\n            self.scrollHeight = 0;\n            target.children().each(function () {\n\n                if ($(this).find('.options').length > 0) {\n                    $(this).collapsible();\n                }\n                outerHeight = $(this).outerHeight(true);\n\n                if (counter-- > 0) {\n                    height += outerHeight;\n                }\n                self.scrollHeight += outerHeight;\n            });\n\n            target.parent().height(height);\n        }\n    });\n\n    return $.mage.sidebar;\n});\n","Magento_Checkout/js/action/set-payment-information.js":"/**\n * Copyright \u00a9 Magento, Inc. All rights reserved.\n * See COPYING.txt for license details.\n */\n\n/**\n * @api\n */\ndefine([\n    'Magento_Checkout/js/action/set-payment-information-extended'\n\n], function (setPaymentInformationExtended) {\n    'use strict';\n\n    return function (messageContainer, paymentData) {\n\n        return setPaymentInformationExtended(messageContainer, paymentData, false);\n    };\n});\n","Magento_Checkout/js/action/update-shopping-cart.js":"/**\n * Copyright \u00a9 Magento, Inc. All rights reserved.\n * See COPYING.txt for license details.\n */\n\ndefine([\n    'Magento_Ui/js/modal/alert',\n    'Magento_Ui/js/modal/confirm',\n    'jquery',\n    'mage/translate',\n    'jquery-ui-modules/widget',\n    'mage/validation'\n], function (alert, confirm, $, $t) {\n    'use strict';\n\n    $.widget('mage.updateShoppingCart', {\n        options: {\n            validationURL: '',\n            eventName: 'updateCartItemQty',\n            updateCartActionContainer: '',\n            isCartHasUpdatedContent: false\n        },\n\n        /** @inheritdoc */\n        _create: function () {\n            this._on(this.element, {\n                'submit': this.onSubmit\n            });\n            this._on('[data-role=cart-item-qty]', {\n                'change': function () {\n                    this.isCartHasUpdatedContent = true;\n                }\n            });\n            this._on('ul.pages-items', {\n                'click a': function (event) {\n                    if (this.isCartHasUpdatedContent) {\n                        event.preventDefault();\n                        this.changePageConfirm($(event.currentTarget).attr('href'));\n                    }\n                }\n            });\n        },\n\n        /**\n         * Show the confirmation popup\n         * @param nextPageUrl\n         */\n        changePageConfirm: function (nextPageUrl) {\n            confirm({\n                title: $t('Are you sure you want to leave the page?'),\n                content: $t('Changes you made to the cart will not be saved.'),\n                actions: {\n                    confirm: function () {\n                        window.location.href = nextPageUrl;\n                    }\n                },\n                buttons: [{\n                    text: $t('Cancel'),\n                    class: 'action-secondary action-dismiss',\n                    click: function (event) {\n                        this.closeModal(event);\n                    }\n                }, {\n                    text: $t('Leave'),\n                    class: 'action-primary action-accept',\n                    click: function (event) {\n                        this.closeModal(event, true);\n                    }\n                }]\n            });\n        },\n\n        /**\n         * Prevents default submit action and calls form validator.\n         *\n         * @param {Event} event\n         * @return {Boolean}\n         */\n        onSubmit: function (event) {\n            var action = this.element.find(this.options.updateCartActionContainer).val();\n\n            if (!this.options.validationURL || action === 'empty_cart') {\n                return true;\n            }\n\n            if (this.isValid()) {\n                event.preventDefault();\n                this.validateItems(this.options.validationURL, this.element.serialize());\n            }\n\n            return false;\n        },\n\n        /**\n         * Validates requested form.\n         *\n         * @return {Boolean}\n         */\n        isValid: function () {\n            return this.element.validation() && this.element.validation('isValid');\n        },\n\n        /**\n         * Validates updated shopping cart data.\n         *\n         * @param {String} url - request url\n         * @param {Object} data - post data for ajax call\n         */\n        validateItems: function (url, data) {\n            $.extend(data, {\n                'form_key': $.mage.cookies.get('form_key')\n            });\n\n            $.ajax({\n                url: url,\n                data: data,\n                type: 'post',\n                dataType: 'json',\n                context: this,\n\n                /** @inheritdoc */\n                beforeSend: function () {\n                    $(document.body).trigger('processStart');\n                },\n\n                /** @inheritdoc */\n                complete: function () {\n                    $(document.body).trigger('processStop');\n                }\n            })\n                .done(function (response) {\n                    if (response.success) {\n                        this.onSuccess();\n                    } else {\n                        this.onError(response);\n                    }\n                })\n                .fail(function () {\n                    this.submitForm();\n                });\n        },\n\n        /**\n         * Form validation succeed.\n         */\n        onSuccess: function () {\n            $(document).trigger('ajax:' + this.options.eventName);\n            this.submitForm();\n        },\n\n        /**\n         * Form validation failed.\n         */\n        onError: function (response) {\n            var that = this,\n                elm,\n                responseData = [];\n\n            try {\n                responseData = JSON.parse(response['error_message']);\n            } catch (error) {\n            }\n\n            if (response['error_message']) {\n                try {\n                    $.each(responseData, function (index, data) {\n\n                        if (data.itemId !== undefined) {\n                            elm = $('#cart-' + data.itemId + '-qty');\n                            elm.val(elm.attr('data-item-qty'));\n                        }\n                        response['error_message'] = data.error;\n                    });\n                } catch (e) {}\n                alert({\n                    content: response['error_message'],\n                    actions: {\n                        /** @inheritdoc */\n                        always: function () {\n                            that.submitForm();\n                        }\n                    }\n                });\n            } else {\n                this.submitForm();\n            }\n        },\n\n        /**\n         * Real submit of validated form.\n         */\n        submitForm: function () {\n            this.element\n                .off('submit', this.onSubmit)\n                .on('submit', function () {\n                    $(document.body).trigger('processStart');\n                })\n                .trigger('submit');\n        }\n    });\n\n    return $.mage.updateShoppingCart;\n});\n","Magento_Checkout/js/action/get-payment-information.js":"/**\n * Copyright \u00a9 Magento, Inc. All rights reserved.\n * See COPYING.txt for license details.\n */\n\n/**\n * @api\n */\ndefine([\n    'jquery',\n    'Magento_Checkout/js/model/quote',\n    'Magento_Checkout/js/model/url-builder',\n    'mage/storage',\n    'Magento_Checkout/js/model/error-processor',\n    'Magento_Customer/js/model/customer',\n    'Magento_Checkout/js/model/payment/method-converter',\n    'Magento_Checkout/js/model/payment-service'\n], function ($, quote, urlBuilder, storage, errorProcessor, customer, methodConverter, paymentService) {\n    'use strict';\n\n    return function (deferred, messageContainer) {\n        var serviceUrl;\n\n        deferred = deferred || $.Deferred();\n\n        /**\n         * Checkout for guest and registered customer.\n         */\n        if (!customer.isLoggedIn()) {\n            serviceUrl = urlBuilder.createUrl('/guest-carts/:cartId/payment-information', {\n                cartId: quote.getQuoteId()\n            });\n        } else {\n            serviceUrl = urlBuilder.createUrl('/carts/mine/payment-information', {});\n        }\n\n        return storage.get(\n            serviceUrl, false\n        ).done(function (response) {\n            quote.setTotals(response.totals);\n            paymentService.setPaymentMethods(methodConverter(response['payment_methods']));\n            deferred.resolve();\n        }).fail(function (response) {\n            errorProcessor.process(response, messageContainer);\n            deferred.reject();\n        });\n    };\n});\n","Magento_Checkout/js/action/recollect-shipping-rates.js":"/**\n * Copyright \u00a9 Magento, Inc. All rights reserved.\n * See COPYING.txt for license details.\n */\n\n/**\n * @api\n */\ndefine([\n    'Magento_Checkout/js/model/quote',\n    'Magento_Checkout/js/action/select-shipping-address',\n    'Magento_Checkout/js/model/shipping-rate-registry'\n], function (quote, selectShippingAddress, rateRegistry) {\n    'use strict';\n\n    return function () {\n        var shippingAddress = null;\n\n        if (!quote.isVirtual()) {\n            shippingAddress = quote.shippingAddress();\n\n            rateRegistry.set(shippingAddress.getCacheKey(), null);\n            selectShippingAddress(shippingAddress);\n        }\n    };\n});\n","Magento_Checkout/js/action/select-shipping-method.js":"/**\n * Copyright \u00a9 Magento, Inc. All rights reserved.\n * See COPYING.txt for license details.\n */\n\n/**\n * @api\n */\ndefine([\n    '../model/quote'\n], function (quote) {\n    'use strict';\n\n    return function (shippingMethod) {\n        quote.shippingMethod(shippingMethod);\n    };\n});\n","Magento_Checkout/js/action/set-shipping-information.js":"/**\n * Copyright \u00a9 Magento, Inc. All rights reserved.\n * See COPYING.txt for license details.\n */\n\n/**\n * @api\n */\ndefine([\n    '../model/quote',\n    'Magento_Checkout/js/model/shipping-save-processor'\n], function (quote, shippingSaveProcessor) {\n    'use strict';\n\n    return function () {\n        return shippingSaveProcessor.saveShippingInformation(quote.shippingAddress().getType());\n    };\n});\n","Magento_Checkout/js/action/select-payment-method.js":"/**\n * Copyright \u00a9 Magento, Inc. All rights reserved.\n * See COPYING.txt for license details.\n */\n\n/**\n * @api\n */\ndefine([\n    'Magento_Checkout/js/model/quote'\n], function (quote) {\n    'use strict';\n\n    return function (paymentMethod) {\n        if (paymentMethod) {\n            paymentMethod.__disableTmpl = {\n                title: true\n            };\n        }\n        quote.paymentMethod(paymentMethod);\n    };\n});\n","Magento_Checkout/js/action/create-shipping-address.js":"/**\n * Copyright \u00a9 Magento, Inc. All rights reserved.\n * See COPYING.txt for license details.\n */\n\n/**\n * @api\n */\ndefine([\n    'Magento_Customer/js/model/address-list',\n    'Magento_Checkout/js/model/address-converter'\n], function (addressList, addressConverter) {\n    'use strict';\n\n    return function (addressData) {\n        var address = addressConverter.formAddressDataToQuoteAddress(addressData),\n            isAddressUpdated = addressList().some(function (currentAddress, index, addresses) {\n                if (currentAddress.getKey() == address.getKey()) { //eslint-disable-line eqeqeq\n                    addresses[index] = address;\n\n                    return true;\n                }\n\n                return false;\n            });\n\n        if (!isAddressUpdated) {\n            addressList.push(address);\n        } else {\n            addressList.valueHasMutated();\n        }\n\n        return address;\n    };\n});\n","Magento_Checkout/js/action/redirect-on-success.js":"/**\n * Copyright \u00a9 Magento, Inc. All rights reserved.\n * See COPYING.txt for license details.\n */\n\n/**\n * @api\n */\ndefine(\n    [\n        'mage/url',\n        'Magento_Checkout/js/model/full-screen-loader'\n    ],\n    function (url, fullScreenLoader) {\n        'use strict';\n\n        return {\n            redirectUrl: window.checkoutConfig.defaultSuccessPageUrl,\n\n            /**\n             * Provide redirect to page\n             */\n            execute: function () {\n                fullScreenLoader.startLoader();\n                this.redirectToSuccessPage();\n            },\n\n            /**\n             * Redirect to success page.\n             */\n            redirectToSuccessPage: function () {\n                window.location.replace(url.build(this.redirectUrl));\n            }\n        };\n    }\n);\n","Magento_Checkout/js/action/select-billing-address.js":"/**\n * Copyright \u00a9 Magento, Inc. All rights reserved.\n * See COPYING.txt for license details.\n */\n\n/**\n * @api\n */\ndefine([\n    'jquery',\n    '../model/quote'\n], function ($, quote) {\n    'use strict';\n\n    return function (billingAddress) {\n        var address = null;\n\n        if (quote.shippingAddress() && billingAddress.getCacheKey() == //eslint-disable-line eqeqeq\n            quote.shippingAddress().getCacheKey()\n        ) {\n            address = $.extend(true, {}, billingAddress);\n            address.saveInAddressBook = null;\n        } else {\n            address = billingAddress;\n        }\n        quote.billingAddress(address);\n    };\n});\n","Magento_Checkout/js/action/place-order.js":"/**\n * Copyright \u00a9 Magento, Inc. All rights reserved.\n * See COPYING.txt for license details.\n */\n\n/**\n * @api\n */\ndefine([\n    'Magento_Checkout/js/model/quote',\n    'Magento_Checkout/js/model/url-builder',\n    'Magento_Customer/js/model/customer',\n    'Magento_Checkout/js/model/place-order'\n], function (quote, urlBuilder, customer, placeOrderService) {\n    'use strict';\n\n    return function (paymentData, messageContainer) {\n        var serviceUrl, payload;\n\n        payload = {\n            cartId: quote.getQuoteId(),\n            billingAddress: quote.billingAddress(),\n            paymentMethod: paymentData\n        };\n\n        if (customer.isLoggedIn()) {\n            serviceUrl = urlBuilder.createUrl('/carts/mine/payment-information', {});\n        } else {\n            serviceUrl = urlBuilder.createUrl('/guest-carts/:quoteId/payment-information', {\n                quoteId: quote.getQuoteId()\n            });\n            payload.email = quote.guestEmail;\n        }\n\n        return placeOrderService(serviceUrl, payload, messageContainer);\n    };\n});\n","Magento_Checkout/js/action/set-billing-address.js":"/**\n * Copyright \u00a9 Magento, Inc. All rights reserved.\n * See COPYING.txt for license details.\n */\n\n/**\n * @api\n */\ndefine(\n    [\n        'jquery',\n        'Magento_Checkout/js/model/quote',\n        'Magento_Checkout/js/model/url-builder',\n        'mage/storage',\n        'Magento_Checkout/js/model/error-processor',\n        'Magento_Customer/js/model/customer',\n        'Magento_Checkout/js/model/full-screen-loader',\n        'Magento_Checkout/js/action/get-payment-information'\n    ],\n    function ($,\n              quote,\n              urlBuilder,\n              storage,\n              errorProcessor,\n              customer,\n              fullScreenLoader,\n              getPaymentInformationAction\n    ) {\n        'use strict';\n\n        return function (messageContainer) {\n            var serviceUrl,\n                payload;\n\n            /**\n             * Checkout for guest and registered customer.\n             */\n            if (!customer.isLoggedIn()) {\n                serviceUrl = urlBuilder.createUrl('/guest-carts/:cartId/billing-address', {\n                    cartId: quote.getQuoteId()\n                });\n                payload = {\n                    cartId: quote.getQuoteId(),\n                    address: quote.billingAddress()\n                };\n            } else {\n                serviceUrl = urlBuilder.createUrl('/carts/mine/billing-address', {});\n                payload = {\n                    cartId: quote.getQuoteId(),\n                    address: quote.billingAddress()\n                };\n            }\n\n            fullScreenLoader.startLoader();\n\n            return storage.post(\n                serviceUrl, JSON.stringify(payload)\n            ).done(\n                function () {\n                    var deferred = $.Deferred();\n\n                    getPaymentInformationAction(deferred);\n                    $.when(deferred).done(function () {\n                        fullScreenLoader.stopLoader();\n                    });\n                }\n            ).fail(\n                function (response) {\n                    errorProcessor.process(response, messageContainer);\n                    fullScreenLoader.stopLoader();\n                }\n            );\n        };\n    }\n);\n","Magento_Checkout/js/action/set-payment-information-extended.js":"/**\n * Copyright \u00a9 Magento, Inc. All rights reserved.\n * See COPYING.txt for license details.\n */\n\n/**\n * @api\n */\ndefine([\n    'Magento_Checkout/js/model/quote',\n    'Magento_Checkout/js/model/url-builder',\n    'mage/storage',\n    'Magento_Checkout/js/model/error-processor',\n    'Magento_Customer/js/model/customer',\n    'Magento_Checkout/js/action/get-totals',\n    'Magento_Checkout/js/model/full-screen-loader',\n    'underscore',\n    'Magento_Checkout/js/model/payment/place-order-hooks'\n], function (quote, urlBuilder, storage, errorProcessor, customer, getTotalsAction, fullScreenLoader, _, hooks) {\n    'use strict';\n\n    /**\n     * Filter template data.\n     *\n     * @param {Object|Array} data\n     */\n    var filterTemplateData = function (data) {\n        return _.each(data, function (value, key, list) {\n            if (_.isArray(value) || _.isObject(value)) {\n                list[key] = filterTemplateData(value);\n            }\n\n            if (key === '__disableTmpl' || key === 'title') {\n                delete list[key];\n            }\n        });\n    };\n\n    return function (messageContainer, paymentData, skipBilling) {\n        var serviceUrl,\n            payload,\n            headers = {};\n\n        paymentData = filterTemplateData(paymentData);\n        skipBilling = skipBilling || false;\n        payload = {\n            cartId: quote.getQuoteId(),\n            paymentMethod: paymentData\n        };\n\n        /**\n         * Checkout for guest and registered customer.\n         */\n        if (!customer.isLoggedIn()) {\n            serviceUrl = urlBuilder.createUrl('/guest-carts/:cartId/set-payment-information', {\n                cartId: quote.getQuoteId()\n            });\n            payload.email = quote.guestEmail;\n        } else {\n            serviceUrl = urlBuilder.createUrl('/carts/mine/set-payment-information', {});\n        }\n\n        if (skipBilling === false) {\n            payload.billingAddress = quote.billingAddress();\n        }\n\n        fullScreenLoader.startLoader();\n\n        _.each(hooks.requestModifiers, function (modifier) {\n            modifier(headers, payload);\n        });\n\n        return storage.post(\n            serviceUrl, JSON.stringify(payload), true, 'application/json', headers\n        ).fail(\n            function (response) {\n                errorProcessor.process(response, messageContainer);\n            }\n        ).always(\n            function () {\n                fullScreenLoader.stopLoader();\n                _.each(hooks.afterRequestListeners, function (listener) {\n                    listener();\n                });\n            }\n        );\n    };\n});\n","Magento_Checkout/js/action/select-shipping-address.js":"/**\n * Copyright \u00a9 Magento, Inc. All rights reserved.\n * See COPYING.txt for license details.\n */\n\n/**\n * @api\n */\ndefine([\n    'Magento_Checkout/js/model/quote'\n], function (quote) {\n    'use strict';\n\n    return function (shippingAddress) {\n        quote.shippingAddress(shippingAddress);\n    };\n});\n","Magento_Checkout/js/action/create-billing-address.js":"/**\n * Copyright \u00a9 Magento, Inc. All rights reserved.\n * See COPYING.txt for license details.\n */\n\n/**\n * @api\n */\ndefine([\n    'Magento_Checkout/js/model/address-converter'\n], function (addressConverter) {\n    'use strict';\n\n    return function (addressData) {\n        var address = addressConverter.formAddressDataToQuoteAddress(addressData);\n\n        /**\n         * Returns new customer billing address type.\n         *\n         * @returns {String}\n         */\n        address.getType = function () {\n            return 'new-customer-billing-address';\n        };\n\n        return address;\n    };\n});\n","Magento_Checkout/js/action/get-totals.js":"/**\n * Copyright \u00a9 Magento, Inc. All rights reserved.\n * See COPYING.txt for license details.\n */\n\n/**\n * @api\n */\ndefine([\n    'jquery',\n    '../model/quote',\n    'Magento_Checkout/js/model/resource-url-manager',\n    'Magento_Checkout/js/model/error-processor',\n    'mage/storage',\n    'Magento_Checkout/js/model/totals'\n], function ($, quote, resourceUrlManager, errorProcessor, storage, totals) {\n    'use strict';\n\n    return function (callbacks, deferred) {\n        deferred = deferred || $.Deferred();\n        totals.isLoading(true);\n\n        return storage.get(\n            resourceUrlManager.getUrlForCartTotals(quote),\n            false\n        ).done(function (response) {\n            var proceed = true;\n\n            totals.isLoading(false);\n\n            if (callbacks.length > 0) {\n                $.each(callbacks, function (index, callback) {\n                    proceed = proceed && callback();\n                });\n            }\n\n            if (proceed) {\n                quote.setTotals(response);\n                deferred.resolve();\n            }\n        }).fail(function (response) {\n            totals.isLoading(false);\n            deferred.reject();\n            errorProcessor.process(response);\n        }).always(function () {\n            totals.isLoading(false);\n        });\n    };\n});\n","Magento_Checkout/js/view/cart-item-renderer.js":"/**\n * Copyright \u00a9 Magento, Inc. All rights reserved.\n * See COPYING.txt for license details.\n */\n\ndefine([\n    'uiComponent'\n], function (Component) {\n    'use strict';\n\n    return Component.extend({\n        /**\n         * Prepare the product name value to be rendered as HTML\n         *\n         * @param {String} productName\n         * @return {String}\n         */\n        getProductNameUnsanitizedHtml: function (productName) {\n            // product name has already escaped on backend\n            return productName;\n        },\n\n        /**\n         * Prepare the given option value to be rendered as HTML\n         *\n         * @param {String} optionValue\n         * @return {String}\n         */\n        getOptionValueUnsanitizedHtml: function (optionValue) {\n            // option value has already escaped on backend\n            return optionValue;\n        }\n    });\n});\n","Magento_Checkout/js/view/progress-bar.js":"/**\n * Copyright \u00a9 Magento, Inc. All rights reserved.\n * See COPYING.txt for license details.\n */\n\ndefine([\n    'jquery',\n    'underscore',\n    'ko',\n    'uiComponent',\n    'Magento_Checkout/js/model/step-navigator',\n    'Magento_Checkout/js/view/billing-address'\n], function ($, _, ko, Component, stepNavigator, billingAddress) {\n    'use strict';\n\n    var steps = stepNavigator.steps;\n\n    return Component.extend({\n        defaults: {\n            template: 'Magento_Checkout/progress-bar',\n            visible: true\n        },\n        steps: steps,\n\n        /** @inheritdoc */\n        initialize: function () {\n            var stepsValue;\n\n            this._super();\n            window.addEventListener('hashchange', _.bind(stepNavigator.handleHash, stepNavigator));\n\n            if (!window.location.hash) {\n                stepsValue = stepNavigator.steps();\n\n                if (stepsValue.length) {\n                    stepNavigator.setHash(stepsValue.sort(stepNavigator.sortItems)[0].code);\n                }\n            }\n\n            stepNavigator.handleHash();\n        },\n\n        /**\n         * @param {*} itemOne\n         * @param {*} itemTwo\n         * @return {*|Number}\n         */\n        sortItems: function (itemOne, itemTwo) {\n            return stepNavigator.sortItems(itemOne, itemTwo);\n        },\n\n        /**\n         * @param {Object} step\n         */\n        navigateTo: function (step) {\n            if (step.code === 'shipping') {\n                billingAddress().needCancelBillingAddressChanges();\n            }\n            stepNavigator.navigateTo(step.code);\n        },\n\n        /**\n         * @param {Object} item\n         * @return {*|Boolean}\n         */\n        isProcessed: function (item) {\n            return stepNavigator.isProcessed(item.code);\n        }\n    });\n});\n","Magento_Checkout/js/view/registration.js":"/**\n * Copyright \u00a9 Magento, Inc. All rights reserved.\n * See COPYING.txt for license details.\n */\n\ndefine([\n    'jquery',\n    'uiComponent',\n    'Magento_Ui/js/model/messageList'\n], function ($, Component, messageList) {\n    'use strict';\n\n    return Component.extend({\n        defaults: {\n            template: 'Magento_Checkout/registration',\n            accountCreated: false,\n            creationStarted: false,\n            isFormVisible: true\n        },\n\n        /**\n         * @inheritdoc\n         */\n        initObservable: function () {\n            this._super()\n                .observe('accountCreated')\n                .observe('isFormVisible')\n                .observe('creationStarted');\n\n            return this;\n        },\n\n        /**\n         * @return {*}\n         */\n        getEmailAddress: function () {\n            return this.email;\n        },\n\n        /**\n         * @return String\n         */\n        getUrl: function () {\n            return this.registrationUrl;\n        },\n\n        /**\n         * Create new user account.\n         *\n         * @deprecated\n         */\n        createAccount: function () {\n            this.creationStarted(true);\n            $.post(\n                this.registrationUrl\n            ).done(\n                function (response) {\n\n                    if (response.errors == false) { //eslint-disable-line eqeqeq\n                        this.accountCreated(true);\n                    } else {\n                        messageList.addErrorMessage(response);\n                    }\n                    this.isFormVisible(false);\n                }.bind(this)\n            ).fail(\n                function (response) {\n                    this.accountCreated(false);\n                    this.isFormVisible(false);\n                    messageList.addErrorMessage(response);\n                }.bind(this)\n            );\n        }\n    });\n});\n","Magento_Checkout/js/view/summary.js":"/**\n * Copyright \u00a9 Magento, Inc. All rights reserved.\n * See COPYING.txt for license details.\n */\n\ndefine([\n    'uiComponent',\n    'Magento_Checkout/js/model/totals'\n], function (Component, totals) {\n    'use strict';\n\n    return Component.extend({\n        isLoading: totals.isLoading\n    });\n});\n","Magento_Checkout/js/view/authentication-messages.js":"/**\n * Copyright \u00a9 Magento, Inc. All rights reserved.\n * See COPYING.txt for license details.\n */\n\ndefine([\n    'Magento_Ui/js/view/messages',\n    'Magento_Checkout/js/model/authentication-messages'\n], function (Component, messageContainer) {\n    'use strict';\n\n    return Component.extend({\n        /** @inheritdoc */\n        initialize: function (config) {\n            return this._super(config, messageContainer);\n        }\n    });\n});\n","Magento_Checkout/js/view/authentication.js":"/**\n * Copyright \u00a9 Magento, Inc. All rights reserved.\n * See COPYING.txt for license details.\n */\n\ndefine([\n    'jquery',\n    'Magento_Ui/js/form/form',\n    'Magento_Customer/js/action/login',\n    'Magento_Customer/js/model/customer',\n    'mage/validation',\n    'Magento_Checkout/js/model/authentication-messages',\n    'Magento_Checkout/js/model/full-screen-loader'\n], function ($, Component, loginAction, customer, validation, messageContainer, fullScreenLoader) {\n    'use strict';\n\n    var checkoutConfig = window.checkoutConfig;\n\n    return Component.extend({\n        isGuestCheckoutAllowed: checkoutConfig.isGuestCheckoutAllowed,\n        isCustomerLoginRequired: checkoutConfig.isCustomerLoginRequired,\n        registerUrl: checkoutConfig.registerUrl,\n        forgotPasswordUrl: checkoutConfig.forgotPasswordUrl,\n        autocomplete: checkoutConfig.autocomplete,\n        defaults: {\n            template: 'Magento_Checkout/authentication'\n        },\n\n        /**\n         * Is login form enabled for current customer.\n         *\n         * @return {Boolean}\n         */\n        isActive: function () {\n            return !customer.isLoggedIn();\n        },\n\n        /**\n         * Provide login action.\n         *\n         * @param {HTMLElement} loginForm\n         */\n        login: function (loginForm) {\n            var loginData = {},\n                formDataArray = $(loginForm).serializeArray();\n\n            formDataArray.forEach(function (entry) {\n                loginData[entry.name] = entry.value;\n            });\n\n            if ($(loginForm).validation() &&\n                $(loginForm).validation('isValid')\n            ) {\n                fullScreenLoader.startLoader();\n                loginAction(loginData, checkoutConfig.checkoutUrl, undefined, messageContainer).always(function () {\n                    fullScreenLoader.stopLoader();\n                });\n            }\n        }\n    });\n});\n","Magento_Checkout/js/view/minicart.js":"/**\n * Copyright \u00a9 Magento, Inc. All rights reserved.\n * See COPYING.txt for license details.\n */\n\ndefine([\n    'uiComponent',\n    'Magento_Customer/js/customer-data',\n    'jquery',\n    'ko',\n    'underscore',\n    'sidebar',\n    'mage/translate',\n    'mage/dropdown'\n], function (Component, customerData, $, ko, _) {\n    'use strict';\n\n    var sidebarInitialized = false,\n        addToCartCalls = 0,\n        miniCart;\n\n    miniCart = $('[data-block=\\'minicart\\']');\n\n    /**\n     * @return {Boolean}\n     */\n    function initSidebar() {\n        if (miniCart.data('mageSidebar')) {\n            miniCart.sidebar('update');\n        }\n\n        if (!$('[data-role=product-item]').length) {\n            return false;\n        }\n        miniCart.trigger('contentUpdated');\n\n        if (sidebarInitialized) {\n            return false;\n        }\n        sidebarInitialized = true;\n        miniCart.sidebar({\n            'targetElement': 'div.block.block-minicart',\n            'url': {\n                'checkout': window.checkout.checkoutUrl,\n                'update': window.checkout.updateItemQtyUrl,\n                'remove': window.checkout.removeItemUrl,\n                'loginUrl': window.checkout.customerLoginUrl,\n                'isRedirectRequired': window.checkout.isRedirectRequired\n            },\n            'button': {\n                'checkout': '#top-cart-btn-checkout',\n                'remove': '#mini-cart a.action.delete',\n                'close': '#btn-minicart-close'\n            },\n            'showcart': {\n                'parent': 'span.counter',\n                'qty': 'span.counter-number',\n                'label': 'span.counter-label'\n            },\n            'minicart': {\n                'list': '#mini-cart',\n                'content': '#minicart-content-wrapper',\n                'qty': 'div.items-total',\n                'subtotal': 'div.subtotal span.price',\n                'maxItemsVisible': window.checkout.minicartMaxItemsVisible\n            },\n            'item': {\n                'qty': ':input.cart-item-qty',\n                'button': ':button.update-cart-item'\n            },\n            'confirmMessage': $.mage.__('Are you sure you would like to remove this item from the shopping cart?')\n        });\n    }\n\n    miniCart.on('dropdowndialogopen', function () {\n        initSidebar();\n    });\n\n    return Component.extend({\n        shoppingCartUrl: window.checkout.shoppingCartUrl,\n        maxItemsToDisplay: window.checkout.maxItemsToDisplay,\n        cart: {},\n\n        // jscs:disable requireCamelCaseOrUpperCaseIdentifiers\n        /**\n         * @override\n         */\n        initialize: function () {\n            var self = this,\n                cartData = customerData.get('cart');\n\n            this.update(cartData());\n            cartData.subscribe(function (updatedCart) {\n                addToCartCalls--;\n                this.isLoading(addToCartCalls > 0);\n                sidebarInitialized = false;\n                this.update(updatedCart);\n                initSidebar();\n            }, this);\n            $('[data-block=\"minicart\"]').on('contentLoading', function () {\n                addToCartCalls++;\n                self.isLoading(true);\n            });\n\n            if (\n                cartData().website_id !== window.checkout.websiteId && cartData().website_id !== undefined ||\n                cartData().storeId !== window.checkout.storeId && cartData().storeId !== undefined\n            ) {\n                customerData.reload(['cart'], false);\n            }\n\n            return this._super();\n        },\n        //jscs:enable requireCamelCaseOrUpperCaseIdentifiers\n\n        isLoading: ko.observable(false),\n        initSidebar: initSidebar,\n\n        /**\n         * Close mini shopping cart.\n         */\n        closeMinicart: function () {\n            $('[data-block=\"minicart\"]').find('[data-role=\"dropdownDialog\"]').dropdownDialog('close');\n        },\n\n        /**\n         * @param {String} productType\n         * @return {*|String}\n         */\n        getItemRenderer: function (productType) {\n            return this.itemRenderer[productType] || 'defaultRenderer';\n        },\n\n        /**\n         * Update mini shopping cart content.\n         *\n         * @param {Object} updatedCart\n         * @returns void\n         */\n        update: function (updatedCart) {\n            _.each(updatedCart, function (value, key) {\n                if (!this.cart.hasOwnProperty(key)) {\n                    this.cart[key] = ko.observable();\n                }\n                this.cart[key](value);\n            }, this);\n        },\n\n        /**\n         * Get cart param by name.\n         *\n         * @param {String} name\n         * @returns {*}\n         */\n        getCartParamUnsanitizedHtml: function (name) {\n            if (!_.isUndefined(name)) {\n                if (!this.cart.hasOwnProperty(name)) {\n                    this.cart[name] = ko.observable();\n                }\n            }\n\n            return this.cart[name]();\n        },\n\n        /**\n         * @deprecated please use getCartParamUnsanitizedHtml.\n         * @param {String} name\n         * @returns {*}\n         */\n        getCartParam: function (name) {\n            return this.getCartParamUnsanitizedHtml(name);\n        },\n\n        /**\n         * Returns array of cart items, limited by 'maxItemsToDisplay' setting\n         * @returns []\n         */\n        getCartItems: function () {\n            var items = this.getCartParamUnsanitizedHtml('items') || [];\n\n            items = items.slice(parseInt(-this.maxItemsToDisplay, 10));\n\n            return items;\n        },\n\n        /**\n         * Returns count of cart line items\n         * @returns {Number}\n         */\n        getCartLineItemsCount: function () {\n            var items = this.getCartParamUnsanitizedHtml('items') || [];\n\n            return parseInt(items.length, 10);\n        }\n    });\n});\n","Magento_Checkout/js/view/shipping-information.js":"/**\n * Copyright \u00a9 Magento, Inc. All rights reserved.\n * See COPYING.txt for license details.\n */\n\ndefine([\n    'jquery',\n    'uiComponent',\n    'Magento_Checkout/js/model/quote',\n    'Magento_Checkout/js/model/step-navigator',\n    'Magento_Checkout/js/model/sidebar'\n], function ($, Component, quote, stepNavigator, sidebarModel) {\n    'use strict';\n\n    return Component.extend({\n        defaults: {\n            template: 'Magento_Checkout/shipping-information'\n        },\n\n        /**\n         * @return {Boolean}\n         */\n        isVisible: function () {\n            return !quote.isVirtual() && stepNavigator.isProcessed('shipping');\n        },\n\n        /**\n         * @return {String}\n         */\n        getShippingMethodTitle: function () {\n            var shippingMethod = quote.shippingMethod(),\n                shippingMethodTitle = '';\n\n            if (!shippingMethod) {\n                return '';\n            }\n\n            shippingMethodTitle = shippingMethod['carrier_title'];\n\n            if (typeof shippingMethod['method_title'] !== 'undefined') {\n                shippingMethodTitle += ' - ' + shippingMethod['method_title'];\n            }\n\n            return shippingMethodTitle;\n        },\n\n        /**\n         * Back step.\n         */\n        back: function () {\n            sidebarModel.hide();\n            stepNavigator.navigateTo('shipping');\n        },\n\n        /**\n         * Back to shipping method.\n         */\n        backToShippingMethod: function () {\n            sidebarModel.hide();\n            stepNavigator.navigateTo('shipping', 'opc-shipping_method');\n        }\n    });\n});\n","Magento_Checkout/js/view/billing-address.js":"/**\n * Copyright \u00a9 Magento, Inc. All rights reserved.\n * See COPYING.txt for license details.\n */\n\ndefine([\n    'ko',\n    'underscore',\n    'Magento_Ui/js/form/form',\n    'Magento_Customer/js/model/customer',\n    'Magento_Customer/js/model/address-list',\n    'Magento_Checkout/js/model/quote',\n    'Magento_Checkout/js/action/create-billing-address',\n    'Magento_Checkout/js/action/select-billing-address',\n    'Magento_Checkout/js/checkout-data',\n    'Magento_Checkout/js/model/checkout-data-resolver',\n    'Magento_Customer/js/customer-data',\n    'Magento_Checkout/js/action/set-billing-address',\n    'Magento_Ui/js/model/messageList',\n    'mage/translate',\n    'Magento_Checkout/js/model/billing-address-postcode-validator',\n    'Magento_Checkout/js/model/address-converter'\n],\nfunction (\n    ko,\n    _,\n    Component,\n    customer,\n    addressList,\n    quote,\n    createBillingAddress,\n    selectBillingAddress,\n    checkoutData,\n    checkoutDataResolver,\n    customerData,\n    setBillingAddressAction,\n    globalMessageList,\n    $t,\n    billingAddressPostcodeValidator,\n    addressConverter\n) {\n    'use strict';\n\n    var lastSelectedBillingAddress = null,\n        addressUpdated = false,\n        addressEdited = false,\n        countryData = customerData.get('directory-data'),\n        addressOptions = addressList().filter(function (address) {\n            return address.getType() === 'customer-address';\n        });\n\n    return Component.extend({\n        defaults: {\n            template: 'Magento_Checkout/billing-address',\n            actionsTemplate: 'Magento_Checkout/billing-address/actions',\n            formTemplate: 'Magento_Checkout/billing-address/form',\n            detailsTemplate: 'Magento_Checkout/billing-address/details',\n            links: {\n                isAddressFormVisible: '${$.billingAddressListProvider}:isNewAddressSelected'\n            }\n        },\n        currentBillingAddress: quote.billingAddress,\n        customerHasAddresses: addressOptions.length > 0,\n\n        /**\n         * Init component\n         */\n        initialize: function () {\n            this._super();\n            quote.paymentMethod.subscribe(function () {\n                checkoutDataResolver.resolveBillingAddress();\n            }, this);\n            billingAddressPostcodeValidator.initFields(this.get('name') + '.form-fields');\n        },\n\n        /**\n         * @return {exports.initObservable}\n         */\n        initObservable: function () {\n            this._super()\n                .observe({\n                    selectedAddress: null,\n                    isAddressDetailsVisible: quote.billingAddress() != null,\n                    isAddressFormVisible: !customer.isLoggedIn() || !addressOptions.length,\n                    isAddressSameAsShipping: false,\n                    saveInAddressBook: 1\n                });\n\n            quote.billingAddress.subscribe(function (newAddress) {\n                if (quote.isVirtual()) {\n                    this.isAddressSameAsShipping(false);\n                } else {\n                    this.isAddressSameAsShipping(\n                        newAddress != null &&\n                        newAddress.getCacheKey() == quote.shippingAddress().getCacheKey() //eslint-disable-line eqeqeq\n                    );\n                }\n\n                if (newAddress != null && newAddress.saveInAddressBook !== undefined) {\n                    this.saveInAddressBook(newAddress.saveInAddressBook);\n                } else {\n                    this.saveInAddressBook(1);\n                }\n                this.isAddressDetailsVisible(true);\n            }, this);\n\n            return this;\n        },\n\n        canUseShippingAddress: ko.computed(function () {\n            return !quote.isVirtual() && quote.shippingAddress() && quote.shippingAddress().canUseForBilling();\n        }),\n\n        /**\n         * @param {Object} address\n         * @return {*}\n         */\n        addressOptionsText: function (address) {\n            return address.getAddressInline();\n        },\n\n        /**\n         * @return {Boolean}\n         */\n        useShippingAddress: function () {\n            if (this.isAddressSameAsShipping()) {\n                selectBillingAddress(quote.shippingAddress());\n                this.updateAddresses(true);\n                this.isAddressDetailsVisible(true);\n            } else {\n                lastSelectedBillingAddress = quote.billingAddress();\n                quote.billingAddress(null);\n                this.isAddressDetailsVisible(false);\n            }\n            checkoutData.setSelectedBillingAddress(null);\n\n            return true;\n        },\n\n        /**\n         * Update address action\n         */\n        updateAddress: function () {\n            var addressData, newBillingAddress;\n\n            addressUpdated = true;\n\n            if (this.selectedAddress() && !this.isAddressFormVisible()) {\n                selectBillingAddress(this.selectedAddress());\n                checkoutData.setSelectedBillingAddress(this.selectedAddress().getKey());\n            } else {\n                this.source.set('params.invalid', false);\n                this.source.trigger(this.dataScopePrefix + '.data.validate');\n\n                if (this.source.get(this.dataScopePrefix + '.custom_attributes')) {\n                    this.source.trigger(this.dataScopePrefix + '.custom_attributes.data.validate');\n                }\n\n                if (!this.source.get('params.invalid')) {\n                    addressData = this.source.get(this.dataScopePrefix);\n\n                    if (customer.isLoggedIn() && !this.customerHasAddresses) { //eslint-disable-line max-depth\n                        this.saveInAddressBook(1);\n                    }\n                    addressData['save_in_address_book'] = this.saveInAddressBook() ? 1 : 0;\n                    newBillingAddress = createBillingAddress(addressData);\n                    // New address must be selected as a billing address\n                    selectBillingAddress(newBillingAddress);\n                    checkoutData.setSelectedBillingAddress(newBillingAddress.getKey());\n                    checkoutData.setNewCustomerBillingAddress(addressData);\n                }\n            }\n            this.updateAddresses(true);\n        },\n\n        /**\n         * Edit address action\n         */\n        editAddress: function () {\n            addressUpdated = false;\n            addressEdited = true;\n            lastSelectedBillingAddress = quote.billingAddress();\n            quote.billingAddress(null);\n            this.isAddressDetailsVisible(false);\n        },\n\n        /**\n         * Cancel address edit action\n         */\n        cancelAddressEdit: function () {\n            addressUpdated = true;\n            this.restoreBillingAddress();\n\n            if (quote.billingAddress()) {\n                // restore 'Same As Shipping' checkbox state\n                this.isAddressSameAsShipping(\n                    quote.billingAddress() != null &&\n                        quote.billingAddress().getCacheKey() == quote.shippingAddress().getCacheKey() && //eslint-disable-line\n                        !quote.isVirtual()\n                );\n                this.isAddressDetailsVisible(true);\n            }\n        },\n\n        /**\n         * Manage cancel button visibility\n         */\n        canUseCancelBillingAddress: ko.computed(function () {\n            return quote.billingAddress() || lastSelectedBillingAddress;\n        }),\n\n        /**\n         * Check if Billing Address Changes should be canceled\n         */\n        needCancelBillingAddressChanges: function () {\n            if (addressEdited && !addressUpdated) {\n                this.cancelAddressEdit();\n            }\n        },\n\n        /**\n         * Restore billing address\n         */\n        restoreBillingAddress: function () {\n            var lastBillingAddress;\n\n            if (lastSelectedBillingAddress != null) {\n                selectBillingAddress(lastSelectedBillingAddress);\n                lastBillingAddress = addressConverter.quoteAddressToFormAddressData(lastSelectedBillingAddress);\n\n                checkoutData.setNewCustomerBillingAddress(lastBillingAddress);\n            }\n        },\n\n        /**\n         * @param {Number} countryId\n         * @return {*}\n         */\n        getCountryName: function (countryId) {\n            return countryData()[countryId] != undefined ? countryData()[countryId].name : ''; //eslint-disable-line\n        },\n\n        /**\n         * Trigger action to update shipping and billing addresses\n         *\n         * @param {Boolean} force\n         */\n        updateAddresses: function (force) {\n            force = !(typeof force === 'undefined' || force !== true);\n\n            if (force\n                || window.checkoutConfig.reloadOnBillingAddress\n                || !window.checkoutConfig.displayBillingOnPaymentMethod) {\n                setBillingAddressAction(globalMessageList);\n            }\n        },\n\n        /**\n         * Get code\n         * @param {Object} parent\n         * @returns {String}\n         */\n        getCode: function (parent) {\n            return _.isFunction(parent.getCode) ? parent.getCode() : 'shared';\n        },\n\n        /**\n         * Get customer attribute label\n         *\n         * @param {*} attribute\n         * @returns {*}\n         */\n        getCustomAttributeLabel: function (attribute) {\n            var label;\n\n            if (typeof attribute === 'string') {\n                return attribute;\n            }\n\n            if (attribute.label) {\n                return attribute.label;\n            }\n\n            if (_.isArray(attribute.value)) {\n                label = _.map(attribute.value, function (value) {\n                    return this.getCustomAttributeOptionLabel(attribute['attribute_code'], value) || value;\n                }, this).join(', ');\n            } else if (typeof attribute.value === 'object') {\n                label = _.map(Object.values(attribute.value)).join(', ');\n            } else {\n                label = this.getCustomAttributeOptionLabel(attribute['attribute_code'], attribute.value);\n            }\n\n            return label || attribute.value;\n        },\n\n        /**\n         * Get option label for given attribute code and option ID\n         *\n         * @param {String} attributeCode\n         * @param {String} value\n         * @returns {String|null}\n         */\n        getCustomAttributeOptionLabel: function (attributeCode, value) {\n            var option,\n                label,\n                options = this.source.get('customAttributes') || {};\n\n            if (options[attributeCode]) {\n                option = _.findWhere(options[attributeCode], {\n                    value: value\n                });\n\n                if (option) {\n                    label = option.label;\n                }\n            } else if (value.file !== null) {\n                label = value.file;\n            }\n\n            return label;\n        }\n    });\n});\n","Magento_Checkout/js/view/payment.js":"/**\n * Copyright \u00a9 Magento, Inc. All rights reserved.\n * See COPYING.txt for license details.\n */\n\ndefine([\n    'jquery',\n    'underscore',\n    'uiComponent',\n    'ko',\n    'Magento_Checkout/js/model/quote',\n    'Magento_Checkout/js/model/step-navigator',\n    'Magento_Checkout/js/model/payment-service',\n    'Magento_Checkout/js/model/payment/method-converter',\n    'Magento_Checkout/js/action/get-payment-information',\n    'Magento_Checkout/js/model/checkout-data-resolver',\n    'mage/translate'\n], function (\n    $,\n    _,\n    Component,\n    ko,\n    quote,\n    stepNavigator,\n    paymentService,\n    methodConverter,\n    getPaymentInformation,\n    checkoutDataResolver,\n    $t\n) {\n    'use strict';\n\n    /** Set payment methods to collection */\n    paymentService.setPaymentMethods(methodConverter(window.checkoutConfig.paymentMethods));\n\n    return Component.extend({\n        defaults: {\n            template: 'Magento_Checkout/payment',\n            activeMethod: ''\n        },\n        isVisible: ko.observable(quote.isVirtual()),\n        quoteIsVirtual: quote.isVirtual(),\n        isPaymentMethodsAvailable: ko.computed(function () {\n            return paymentService.getAvailablePaymentMethods().length > 0;\n        }),\n\n        /** @inheritdoc */\n        initialize: function () {\n            this._super();\n            checkoutDataResolver.resolvePaymentMethod();\n            stepNavigator.registerStep(\n                'payment',\n                null,\n                $t('Review & Payments'),\n                this.isVisible,\n                _.bind(this.navigate, this),\n                this.sortOrder\n            );\n\n            return this;\n        },\n\n        /**\n         * Navigate method.\n         */\n        navigate: function () {\n            var self = this;\n\n            if (!self.hasShippingMethod()) {\n                this.isVisible(false);\n                stepNavigator.setHash('shipping');\n            } else {\n                getPaymentInformation().done(function () {\n                    self.isVisible(true);\n                });\n            }\n        },\n\n        /**\n         * @return {Boolean}\n         */\n        hasShippingMethod: function () {\n            return window.checkoutConfig.selectedShippingMethod !== null;\n        },\n\n        /**\n         * @return {*}\n         */\n        getFormKey: function () {\n            return window.checkoutConfig.formKey;\n        }\n    });\n});\n","Magento_Checkout/js/view/shipping.js":"/**\n * Copyright \u00a9 Magento, Inc. All rights reserved.\n * See COPYING.txt for license details.\n */\n\ndefine([\n    'jquery',\n    'underscore',\n    'Magento_Ui/js/form/form',\n    'ko',\n    'Magento_Customer/js/model/customer',\n    'Magento_Customer/js/model/address-list',\n    'Magento_Checkout/js/model/address-converter',\n    'Magento_Checkout/js/model/quote',\n    'Magento_Checkout/js/action/create-shipping-address',\n    'Magento_Checkout/js/action/select-shipping-address',\n    'Magento_Checkout/js/model/shipping-rates-validator',\n    'Magento_Checkout/js/model/shipping-address/form-popup-state',\n    'Magento_Checkout/js/model/shipping-service',\n    'Magento_Checkout/js/action/select-shipping-method',\n    'Magento_Checkout/js/model/shipping-rate-registry',\n    'Magento_Checkout/js/action/set-shipping-information',\n    'Magento_Checkout/js/model/step-navigator',\n    'Magento_Ui/js/modal/modal',\n    'Magento_Checkout/js/model/checkout-data-resolver',\n    'Magento_Checkout/js/checkout-data',\n    'uiRegistry',\n    'mage/translate',\n    'Magento_Checkout/js/model/shipping-rate-service'\n], function (\n    $,\n    _,\n    Component,\n    ko,\n    customer,\n    addressList,\n    addressConverter,\n    quote,\n    createShippingAddress,\n    selectShippingAddress,\n    shippingRatesValidator,\n    formPopUpState,\n    shippingService,\n    selectShippingMethodAction,\n    rateRegistry,\n    setShippingInformationAction,\n    stepNavigator,\n    modal,\n    checkoutDataResolver,\n    checkoutData,\n    registry,\n    $t\n) {\n    'use strict';\n\n    var popUp = null;\n\n    return Component.extend({\n        defaults: {\n            template: 'Magento_Checkout/shipping',\n            shippingFormTemplate: 'Magento_Checkout/shipping-address/form',\n            shippingMethodListTemplate: 'Magento_Checkout/shipping-address/shipping-method-list',\n            shippingMethodItemTemplate: 'Magento_Checkout/shipping-address/shipping-method-item',\n            imports: {\n                countryOptions: '${ $.parentName }.shippingAddress.shipping-address-fieldset.country_id:indexedOptions'\n            }\n        },\n        visible: ko.observable(!quote.isVirtual()),\n        errorValidationMessage: ko.observable(false),\n        isCustomerLoggedIn: customer.isLoggedIn,\n        isFormPopUpVisible: formPopUpState.isVisible,\n        isFormInline: addressList().length === 0,\n        isNewAddressAdded: ko.observable(false),\n        saveInAddressBook: 1,\n        quoteIsVirtual: quote.isVirtual(),\n\n        /**\n         * @return {exports}\n         */\n        initialize: function () {\n            var self = this,\n                hasNewAddress,\n                fieldsetName = 'checkout.steps.shipping-step.shippingAddress.shipping-address-fieldset';\n\n            this._super();\n\n            if (!quote.isVirtual()) {\n                stepNavigator.registerStep(\n                    'shipping',\n                    '',\n                    $t('Shipping'),\n                    this.visible, _.bind(this.navigate, this),\n                    this.sortOrder\n                );\n            }\n            checkoutDataResolver.resolveShippingAddress();\n\n            hasNewAddress = addressList.some(function (address) {\n                return address.getType() == 'new-customer-address'; //eslint-disable-line eqeqeq\n            });\n\n            this.isNewAddressAdded(hasNewAddress);\n\n            this.isFormPopUpVisible.subscribe(function (value) {\n                if (value) {\n                    self.getPopUp().openModal();\n                }\n            });\n\n            quote.shippingMethod.subscribe(function () {\n                self.errorValidationMessage(false);\n            });\n\n            registry.async('checkoutProvider')(function (checkoutProvider) {\n                var shippingAddressData = checkoutData.getShippingAddressFromData();\n\n                if (shippingAddressData) {\n                    checkoutProvider.set(\n                        'shippingAddress',\n                        $.extend(true, {}, checkoutProvider.get('shippingAddress'), shippingAddressData)\n                    );\n                }\n                checkoutProvider.on('shippingAddress', function (shippingAddrsData, changes) {\n                    var isStreetAddressDeleted, isStreetAddressNotEmpty;\n\n                    /**\n                     * In last modifying operation street address was deleted.\n                     * @return {Boolean}\n                     */\n                    isStreetAddressDeleted = function () {\n                        var change;\n\n                        if (!changes || changes.length === 0) {\n                            return false;\n                        }\n\n                        change = changes.pop();\n\n                        if (_.isUndefined(change.value) || _.isUndefined(change.oldValue)) {\n                            return false;\n                        }\n\n                        if (!change.path.startsWith('shippingAddress.street')) {\n                            return false;\n                        }\n\n                        return change.value.length === 0 && change.oldValue.length > 0;\n                    };\n\n                    isStreetAddressNotEmpty = shippingAddrsData.street && !_.isEmpty(shippingAddrsData.street[0]);\n\n                    if (isStreetAddressNotEmpty || isStreetAddressDeleted()) {\n                        checkoutData.setShippingAddressFromData(shippingAddrsData);\n                    }\n                });\n                shippingRatesValidator.initFields(fieldsetName);\n            });\n\n            return this;\n        },\n\n        /**\n         * Navigator change hash handler.\n         *\n         * @param {Object} step - navigation step\n         */\n        navigate: function (step) {\n            step && step.isVisible(true);\n        },\n\n        /**\n         * @return {*}\n         */\n        getPopUp: function () {\n            var self = this,\n                buttons;\n\n            if (!popUp) {\n                buttons = this.popUpForm.options.buttons;\n                this.popUpForm.options.buttons = [\n                    {\n                        text: buttons.save.text ? buttons.save.text : $t('Save Address'),\n                        class: buttons.save.class ? buttons.save.class : 'action primary action-save-address',\n                        click: self.saveNewAddress.bind(self)\n                    },\n                    {\n                        text: buttons.cancel.text ? buttons.cancel.text : $t('Cancel'),\n                        class: buttons.cancel.class ? buttons.cancel.class : 'action secondary action-hide-popup',\n\n                        /** @inheritdoc */\n                        click: this.onClosePopUp.bind(this)\n                    }\n                ];\n\n                /** @inheritdoc */\n                this.popUpForm.options.closed = function () {\n                    self.isFormPopUpVisible(false);\n                };\n\n                this.popUpForm.options.modalCloseBtnHandler = this.onClosePopUp.bind(this);\n                this.popUpForm.options.keyEventHandlers = {\n                    escapeKey: this.onClosePopUp.bind(this)\n                };\n\n                /** @inheritdoc */\n                this.popUpForm.options.opened = function () {\n                    // Store temporary address for revert action in case when user click cancel action\n                    self.temporaryAddress = $.extend(true, {}, checkoutData.getShippingAddressFromData());\n                };\n                popUp = modal(this.popUpForm.options, $(this.popUpForm.element));\n            }\n\n            return popUp;\n        },\n\n        /**\n         * Revert address and close modal.\n         */\n        onClosePopUp: function () {\n            checkoutData.setShippingAddressFromData($.extend(true, {}, this.temporaryAddress));\n            this.getPopUp().closeModal();\n        },\n\n        /**\n         * Show address form popup\n         */\n        showFormPopUp: function () {\n            this.isFormPopUpVisible(true);\n        },\n\n        /**\n         * Save new shipping address\n         */\n        saveNewAddress: function () {\n            var addressData,\n                newShippingAddress;\n\n            this.source.set('params.invalid', false);\n            this.triggerShippingDataValidateEvent();\n\n            if (!this.source.get('params.invalid')) {\n                addressData = this.source.get('shippingAddress');\n                // if user clicked the checkbox, its value is true or false. Need to convert.\n                addressData['save_in_address_book'] = this.saveInAddressBook ? 1 : 0;\n\n                // New address must be selected as a shipping address\n                newShippingAddress = createShippingAddress(addressData);\n                selectShippingAddress(newShippingAddress);\n                checkoutData.setSelectedShippingAddress(newShippingAddress.getKey());\n                checkoutData.setNewCustomerShippingAddress($.extend(true, {}, addressData));\n                this.getPopUp().closeModal();\n                this.isNewAddressAdded(true);\n            }\n        },\n\n        /**\n         * Shipping Method View\n         */\n        rates: shippingService.getShippingRates(),\n        isLoading: shippingService.isLoading,\n        isSelected: ko.computed(function () {\n            return checkoutData.getSelectedShippingRate() ? checkoutData.getSelectedShippingRate() :\n                quote.shippingMethod() ?\n                quote.shippingMethod()['carrier_code'] + '_' + quote.shippingMethod()['method_code'] :\n                null;\n        }),\n\n        /**\n         * @param {Object} shippingMethod\n         * @return {Boolean}\n         */\n        selectShippingMethod: function (shippingMethod) {\n            selectShippingMethodAction(shippingMethod);\n            checkoutData.setSelectedShippingRate(shippingMethod['carrier_code'] + '_' + shippingMethod['method_code']);\n\n            return true;\n        },\n\n        /**\n         * Set shipping information handler\n         */\n        setShippingInformation: function () {\n            if (this.validateShippingInformation()) {\n                quote.billingAddress(null);\n                checkoutDataResolver.resolveBillingAddress();\n                registry.async('checkoutProvider')(function (checkoutProvider) {\n                    var shippingAddressData = checkoutData.getShippingAddressFromData();\n\n                    if (shippingAddressData) {\n                        checkoutProvider.set(\n                            'shippingAddress',\n                            $.extend(true, {}, checkoutProvider.get('shippingAddress'), shippingAddressData)\n                        );\n                    }\n                });\n                setShippingInformationAction().done(\n                    function () {\n                        stepNavigator.next();\n                    }\n                );\n            }\n        },\n\n        /**\n         * @return {Boolean}\n         */\n        validateShippingInformation: function () {\n            var shippingAddress,\n                addressData,\n                loginFormSelector = 'form[data-role=email-with-possible-login]',\n                emailValidationResult = customer.isLoggedIn(),\n                field,\n                option = _.isObject(this.countryOptions) && this.countryOptions[quote.shippingAddress().countryId],\n                messageContainer = registry.get('checkout.errors').messageContainer;\n\n            if (!quote.shippingMethod()) {\n                this.errorValidationMessage(\n                    $t('The shipping method is missing. Select the shipping method and try again.')\n                );\n\n                return false;\n            }\n\n            if (!customer.isLoggedIn()) {\n                $(loginFormSelector).validation();\n                emailValidationResult = Boolean($(loginFormSelector + ' input[name=username]').valid());\n            }\n\n            if (this.isFormInline) {\n                this.source.set('params.invalid', false);\n                this.triggerShippingDataValidateEvent();\n\n                if (!quote.shippingMethod()['method_code']) {\n                    this.errorValidationMessage(\n                        $t('The shipping method is missing. Select the shipping method and try again.')\n                    );\n                }\n\n                if (emailValidationResult &&\n                    this.source.get('params.invalid') ||\n                    !quote.shippingMethod()['method_code'] ||\n                    !quote.shippingMethod()['carrier_code']\n                ) {\n                    this.focusInvalid();\n\n                    return false;\n                }\n\n                shippingAddress = quote.shippingAddress();\n                addressData = addressConverter.formAddressDataToQuoteAddress(\n                    this.source.get('shippingAddress')\n                );\n\n                //Copy form data to quote shipping address object\n                for (field in addressData) {\n                    if (addressData.hasOwnProperty(field) &&  //eslint-disable-line max-depth\n                        shippingAddress.hasOwnProperty(field) &&\n                        typeof addressData[field] != 'function' &&\n                        _.isEqual(shippingAddress[field], addressData[field])\n                    ) {\n                        shippingAddress[field] = addressData[field];\n                    } else if (typeof addressData[field] != 'function' &&\n                        !_.isEqual(shippingAddress[field], addressData[field])) {\n                        shippingAddress = addressData;\n                        break;\n                    }\n                }\n\n                if (customer.isLoggedIn()) {\n                    shippingAddress['save_in_address_book'] = 1;\n                }\n                selectShippingAddress(shippingAddress);\n            } else if (customer.isLoggedIn() &&\n                option &&\n                option['is_region_required'] &&\n                !quote.shippingAddress().region\n            ) {\n                messageContainer.addErrorMessage({\n                    message: $t('Please specify a regionId in shipping address.')\n                });\n\n                return false;\n            }\n\n            if (!emailValidationResult) {\n                $(loginFormSelector + ' input[name=username]').trigger('focus');\n\n                return false;\n            }\n\n            return true;\n        },\n\n        /**\n         * Trigger Shipping data Validate Event.\n         */\n        triggerShippingDataValidateEvent: function () {\n            this.source.trigger('shippingAddress.data.validate');\n\n            if (this.source.get('shippingAddress.custom_attributes')) {\n                this.source.trigger('shippingAddress.custom_attributes.data.validate');\n            }\n        }\n    });\n});\n","Magento_Checkout/js/view/estimation.js":"/**\n * Copyright \u00a9 Magento, Inc. All rights reserved.\n * See COPYING.txt for license details.\n */\n\ndefine([\n    'uiComponent',\n    'Magento_Checkout/js/model/quote',\n    'Magento_Catalog/js/price-utils',\n    'Magento_Checkout/js/model/totals',\n    'Magento_Checkout/js/model/sidebar'\n], function (Component, quote, priceUtils, totals, sidebarModel) {\n    'use strict';\n\n    return Component.extend({\n        isLoading: totals.isLoading,\n\n        /**\n         * @return {Number}\n         */\n        getQuantity: function () {\n            if (totals.totals()) {\n                return parseFloat(totals.totals()['items_qty']);\n            }\n\n            return 0;\n        },\n\n        /**\n         * @return {Number}\n         */\n        getPureValue: function () {\n            if (totals.totals()) {\n                return parseFloat(totals.getSegment('grand_total').value);\n            }\n\n            return 0;\n        },\n\n        /**\n         * Show sidebar.\n         */\n        showSidebar: function () {\n            sidebarModel.show();\n        },\n\n        /**\n         * @param {*} price\n         * @return {*|String}\n         */\n        getFormattedPrice: function (price) {\n            return priceUtils.formatPriceLocale(price, quote.getPriceFormat());\n        },\n\n        /**\n         * @return {*|String}\n         */\n        getValue: function () {\n            return this.getFormattedPrice(this.getPureValue());\n        }\n    });\n});\n","Magento_Checkout/js/view/sidebar.js":"/**\n * Copyright \u00a9 Magento, Inc. All rights reserved.\n * See COPYING.txt for license details.\n */\n\ndefine([\n    'uiComponent',\n    'ko',\n    'jquery',\n    'Magento_Checkout/js/model/sidebar'\n], function (Component, ko, $, sidebarModel) {\n    'use strict';\n\n    return Component.extend({\n        /**\n         * @param {HTMLElement} element\n         */\n        setModalElement: function (element) {\n            sidebarModel.setPopup($(element));\n        }\n    });\n});\n","Magento_Checkout/js/view/form/element/email.js":"/**\n * Copyright \u00a9 Magento, Inc. All rights reserved.\n * See COPYING.txt for license details.\n */\n\ndefine([\n    'jquery',\n    'uiComponent',\n    'ko',\n    'Magento_Customer/js/model/customer',\n    'Magento_Customer/js/action/check-email-availability',\n    'Magento_Customer/js/action/login',\n    'Magento_Checkout/js/model/quote',\n    'Magento_Checkout/js/checkout-data',\n    'Magento_Checkout/js/model/full-screen-loader',\n    'mage/validation'\n], function ($, Component, ko, customer, checkEmailAvailability, loginAction, quote, checkoutData, fullScreenLoader) {\n    'use strict';\n\n    var validatedEmail;\n\n    if (!checkoutData.getValidatedEmailValue() &&\n        window.checkoutConfig.validatedEmailValue\n    ) {\n        checkoutData.setInputFieldEmailValue(window.checkoutConfig.validatedEmailValue);\n        checkoutData.setValidatedEmailValue(window.checkoutConfig.validatedEmailValue);\n    }\n\n    validatedEmail = checkoutData.getValidatedEmailValue();\n\n    if (validatedEmail && !customer.isLoggedIn()) {\n        quote.guestEmail = validatedEmail;\n    }\n\n    return Component.extend({\n        defaults: {\n            template: 'Magento_Checkout/form/element/email',\n            email: checkoutData.getInputFieldEmailValue(),\n            emailFocused: false,\n            isLoading: false,\n            isPasswordVisible: false,\n            listens: {\n                email: 'emailHasChanged',\n                emailFocused: 'validateEmail'\n            },\n            ignoreTmpls: {\n                email: true\n            }\n        },\n        checkDelay: 2000,\n        checkRequest: null,\n        isEmailCheckComplete: null,\n        isCustomerLoggedIn: customer.isLoggedIn,\n        forgotPasswordUrl: window.checkoutConfig.forgotPasswordUrl,\n        emailCheckTimeout: 0,\n        emailInputId: '#customer-email',\n\n        /**\n         * Initializes regular properties of instance.\n         *\n         * @returns {Object} Chainable.\n         */\n        initConfig: function () {\n            this._super();\n\n            this.isPasswordVisible = this.resolveInitialPasswordVisibility();\n\n            return this;\n        },\n\n        /**\n         * Initializes observable properties of instance\n         *\n         * @returns {Object} Chainable.\n         */\n        initObservable: function () {\n            this._super()\n                .observe(['email', 'emailFocused', 'isLoading', 'isPasswordVisible']);\n\n            return this;\n        },\n\n        /**\n         * Callback on changing email property\n         */\n        emailHasChanged: function () {\n            var self = this;\n\n            clearTimeout(this.emailCheckTimeout);\n\n            if (self.validateEmail()) {\n                quote.guestEmail = self.email();\n                checkoutData.setValidatedEmailValue(self.email());\n            }\n            this.emailCheckTimeout = setTimeout(function () {\n                if (self.validateEmail()) {\n                    self.checkEmailAvailability();\n                } else {\n                    self.isPasswordVisible(false);\n                }\n            }, self.checkDelay);\n\n            checkoutData.setInputFieldEmailValue(self.email());\n        },\n\n        /**\n         * Check email existing.\n         */\n        checkEmailAvailability: function () {\n            this.validateRequest();\n            this.isEmailCheckComplete = $.Deferred();\n            // Clean up errors on email\n            $(this.emailInputId).removeClass('mage-error').parent().find('.mage-error').remove();\n            this.isLoading(true);\n            this.checkRequest = checkEmailAvailability(this.isEmailCheckComplete, this.email());\n\n            $.when(this.isEmailCheckComplete).done(function () {\n                this.isPasswordVisible(false);\n                checkoutData.setCheckedEmailValue('');\n            }.bind(this)).fail(function () {\n                this.isPasswordVisible(true);\n                checkoutData.setCheckedEmailValue(this.email());\n            }.bind(this)).always(function () {\n                this.isLoading(false);\n            }.bind(this));\n        },\n\n        /**\n         * If request has been sent -> abort it.\n         * ReadyStates for request aborting:\n         * 1 - The request has been set up\n         * 2 - The request has been sent\n         * 3 - The request is in process\n         */\n        validateRequest: function () {\n            if (this.checkRequest != null && $.inArray(this.checkRequest.readyState, [1, 2, 3])) {\n                this.checkRequest.abort();\n                this.checkRequest = null;\n            }\n        },\n\n        /**\n         * Local email validation.\n         *\n         * @param {Boolean} focused - input focus.\n         * @returns {Boolean} - validation result.\n         */\n        validateEmail: function (focused) {\n            var loginFormSelector = 'form[data-role=email-with-possible-login]',\n                usernameSelector = loginFormSelector + ' input[name=username]',\n                loginForm = $(loginFormSelector),\n                validator,\n                valid;\n\n            loginForm.validation();\n\n            if (focused === false && !!this.email()) {\n                valid = !!$(usernameSelector).valid();\n\n                if (valid) {\n                    $(usernameSelector).removeAttr('aria-invalid aria-describedby');\n                }\n\n                return valid;\n            }\n\n            if (loginForm.is(':visible')) {\n                validator = loginForm.validate();\n\n                return validator.check(usernameSelector);\n            }\n\n            return true;\n        },\n\n        /**\n         * Log in form submitting callback.\n         *\n         * @param {HTMLElement} loginForm - form element.\n         */\n        login: function (loginForm) {\n            var loginData = {},\n                formDataArray = $(loginForm).serializeArray();\n\n            formDataArray.forEach(function (entry) {\n                loginData[entry.name] = entry.value;\n            });\n\n            if (this.isPasswordVisible() && $(loginForm).validation() && $(loginForm).validation('isValid')) {\n                fullScreenLoader.startLoader();\n                loginAction(loginData).always(function () {\n                    fullScreenLoader.stopLoader();\n                });\n            }\n        },\n\n        /**\n         * Resolves an initial state of a login form.\n         *\n         * @returns {Boolean} - initial visibility state.\n         */\n        resolveInitialPasswordVisibility: function () {\n            if (checkoutData.getInputFieldEmailValue() !== '' && checkoutData.getCheckedEmailValue() !== '') {\n                return true;\n            }\n\n            if (checkoutData.getInputFieldEmailValue() !== '') {\n                return checkoutData.getInputFieldEmailValue() === checkoutData.getCheckedEmailValue();\n            }\n\n            return false;\n        }\n    });\n});\n","Magento_Checkout/js/view/cart/shipping-estimation.js":"/**\n * Copyright \u00a9 Magento, Inc. All rights reserved.\n * See COPYING.txt for license details.\n */\ndefine(\n    [\n        'jquery',\n        'Magento_Ui/js/form/form',\n        'Magento_Checkout/js/action/select-shipping-address',\n        'Magento_Checkout/js/model/address-converter',\n        'Magento_Checkout/js/model/cart/estimate-service',\n        'Magento_Checkout/js/checkout-data',\n        'Magento_Checkout/js/model/shipping-rates-validator',\n        'uiRegistry',\n        'Magento_Checkout/js/model/quote',\n        'Magento_Checkout/js/model/checkout-data-resolver',\n        'Magento_Checkout/js/model/shipping-service',\n        'mage/validation'\n    ],\n    function (\n        $,\n        Component,\n        selectShippingAddress,\n        addressConverter,\n        estimateService,\n        checkoutData,\n        shippingRatesValidator,\n        registry,\n        quote,\n        checkoutDataResolver,\n        shippingService\n    ) {\n        'use strict';\n\n        return Component.extend({\n            defaults: {\n                template: 'Magento_Checkout/cart/shipping-estimation'\n            },\n            isVirtual: quote.isVirtual(),\n\n            /**\n             * @override\n             */\n            initialize: function () {\n                this._super();\n\n                // Prevent shipping methods showing none available whilst we resolve\n                shippingService.isLoading(true);\n\n                registry.async('checkoutProvider')(function (checkoutProvider) {\n                    var address, estimatedAddress;\n\n                    shippingService.isLoading(false);\n\n                    checkoutDataResolver.resolveEstimationAddress();\n                    address = quote.isVirtual() ? quote.billingAddress() : quote.shippingAddress();\n\n                    if (!address && quote.isVirtual()) {\n                        address = addressConverter.formAddressDataToQuoteAddress(\n                            checkoutData.getSelectedBillingAddress()\n                        );\n                    }\n\n                    if (address) {\n                        estimatedAddress = address.isEditable() ?\n                            addressConverter.quoteAddressToFormAddressData(address) :\n                            {\n                                // only the following fields must be used by estimation form data provider\n                                'country_id': address.countryId,\n                                region: address.region,\n                                'region_id': address.regionId,\n                                postcode: address.postcode\n                            };\n                        checkoutProvider.set(\n                            'shippingAddress',\n                            $.extend({}, checkoutProvider.get('shippingAddress'), estimatedAddress)\n                        );\n                    }\n\n                    if (!quote.isVirtual()) {\n                        checkoutProvider.on('shippingAddress', function (shippingAddressData) {\n                            //jscs:disable requireCamelCaseOrUpperCaseIdentifiers\n                            if (quote.shippingAddress().countryId !== shippingAddressData.country_id ||\n                                (shippingAddressData.postcode || shippingAddressData.region_id)\n                            ) {\n                                checkoutData.setShippingAddressFromData(shippingAddressData);\n                            }\n                            //jscs:enable requireCamelCaseOrUpperCaseIdentifiers\n                        });\n                    } else {\n                        checkoutProvider.on('shippingAddress', function (shippingAddressData) {\n                            checkoutData.setBillingAddressFromData(shippingAddressData);\n                        });\n                    }\n                });\n\n                return this;\n            },\n\n            /**\n             * @override\n             */\n            initElement: function (element) {\n                this._super();\n\n                if (element.index === 'address-fieldsets') {\n                    shippingRatesValidator.bindChangeHandlers(element.elems(), true, 500);\n                    element.elems.subscribe(function (elems) {\n                        shippingRatesValidator.doElementBinding(elems[elems.length - 1], true, 500);\n                    });\n                }\n\n                return this;\n            },\n\n            /**\n             * Returns shipping rates for address\n             * @returns void\n             */\n            getEstimationInfo: function () {\n                var addressData = null;\n\n                this.source.set('params.invalid', false);\n                this.source.trigger('shippingAddress.data.validate');\n\n                if (!this.source.get('params.invalid')) {\n                    addressData = this.source.get('shippingAddress');\n                    selectShippingAddress(addressConverter.formAddressDataToQuoteAddress(addressData));\n                }\n            }\n        });\n    }\n);\n","Magento_Checkout/js/view/cart/shipping-rates.js":"/**\n * Copyright \u00a9 Magento, Inc. All rights reserved.\n * See COPYING.txt for license details.\n */\n\ndefine([\n    'ko',\n    'underscore',\n    'uiComponent',\n    'Magento_Checkout/js/model/shipping-service',\n    'Magento_Catalog/js/price-utils',\n    'Magento_Checkout/js/model/quote',\n    'Magento_Checkout/js/action/select-shipping-method',\n    'Magento_Checkout/js/checkout-data'\n], function (ko, _, Component, shippingService, priceUtils, quote, selectShippingMethodAction, checkoutData) {\n    'use strict';\n\n    return Component.extend({\n        defaults: {\n            template: 'Magento_Checkout/cart/shipping-rates'\n        },\n        isVisible: ko.observable(!quote.isVirtual()),\n        isLoading: shippingService.isLoading,\n        shippingRates: shippingService.getShippingRates(),\n        shippingRateGroups: ko.observableArray([]),\n        selectedShippingMethod: ko.computed(function () {\n            return quote.shippingMethod() ?\n                quote.shippingMethod()['carrier_code'] + '_' + quote.shippingMethod()['method_code'] :\n                null;\n        }),\n\n        /**\n         * @override\n         */\n        initObservable: function () {\n            var self = this;\n\n            this._super();\n\n            this.shippingRates.subscribe(function (rates) {\n                self.shippingRateGroups([]);\n                _.each(rates, function (rate) {\n                    var carrierTitle = rate['carrier_title'];\n\n                    if (self.shippingRateGroups.indexOf(carrierTitle) === -1) {\n                        self.shippingRateGroups.push(carrierTitle);\n                    }\n                });\n            });\n\n            return this;\n        },\n\n        /**\n         * Get shipping rates for specific group based on title.\n         * @returns Array\n         */\n        getRatesForGroup: function (shippingRateGroupTitle) {\n            return _.filter(this.shippingRates(), function (rate) {\n                return shippingRateGroupTitle === rate['carrier_title'];\n            });\n        },\n\n        /**\n         * Format shipping price.\n         * @returns {String}\n         */\n        getFormattedPrice: function (price) {\n            return priceUtils.formatPriceLocale(price, quote.getPriceFormat());\n        },\n\n        /**\n         * Set shipping method.\n         * @param {String} methodData\n         * @returns bool\n         */\n        selectShippingMethod: function (methodData) {\n            selectShippingMethodAction(methodData);\n            checkoutData.setSelectedShippingRate(methodData['carrier_code'] + '_' + methodData['method_code']);\n\n            return true;\n        }\n    });\n});\n","Magento_Checkout/js/view/cart/totals.js":"/**\n * Copyright \u00a9 Magento, Inc. All rights reserved.\n * See COPYING.txt for license details.\n */\ndefine([\n    'jquery',\n    'uiComponent',\n    'Magento_Checkout/js/model/totals',\n    'Magento_Checkout/js/model/shipping-service'\n], function ($, Component, totalsService, shippingService) {\n    'use strict';\n\n    return Component.extend({\n        isLoading: totalsService.isLoading,\n\n        /**\n         * @override\n         */\n        initialize: function () {\n            this._super();\n            totalsService.totals.subscribe(function () {\n                $(window).trigger('resize');\n            });\n            shippingService.getShippingRates().subscribe(function () {\n                $(window).trigger('resize');\n            });\n        }\n    });\n});\n","Magento_Checkout/js/view/cart/totals/shipping.js":"/**\n * Copyright \u00a9 Magento, Inc. All rights reserved.\n * See COPYING.txt for license details.\n */\n\ndefine([\n    'Magento_Checkout/js/view/summary/shipping',\n    'Magento_Checkout/js/model/quote'\n], function (Component, quote) {\n    'use strict';\n\n    return Component.extend({\n\n        /**\n         * @override\n         */\n        isCalculated: function () {\n            return !!quote.shippingMethod();\n        }\n    });\n});\n","Magento_Checkout/js/view/payment/default.js":"/**\n * Copyright \u00a9 Magento, Inc. All rights reserved.\n * See COPYING.txt for license details.\n */\n\ndefine([\n    'ko',\n    'jquery',\n    'uiComponent',\n    'Magento_Checkout/js/action/place-order',\n    'Magento_Checkout/js/action/select-payment-method',\n    'Magento_Checkout/js/model/quote',\n    'Magento_Customer/js/model/customer',\n    'Magento_Checkout/js/model/payment-service',\n    'Magento_Checkout/js/checkout-data',\n    'Magento_Checkout/js/model/checkout-data-resolver',\n    'uiRegistry',\n    'Magento_Checkout/js/model/payment/additional-validators',\n    'Magento_Ui/js/model/messages',\n    'uiLayout',\n    'Magento_Checkout/js/action/redirect-on-success'\n], function (\n    ko,\n    $,\n    Component,\n    placeOrderAction,\n    selectPaymentMethodAction,\n    quote,\n    customer,\n    paymentService,\n    checkoutData,\n    checkoutDataResolver,\n    registry,\n    additionalValidators,\n    Messages,\n    layout,\n    redirectOnSuccessAction\n) {\n    'use strict';\n\n    return Component.extend({\n        redirectAfterPlaceOrder: true,\n        isPlaceOrderActionAllowed: ko.observable(quote.billingAddress() != null),\n\n        /**\n         * After place order callback\n         */\n        afterPlaceOrder: function () {\n            // Override this function and put after place order logic here\n        },\n\n        /**\n         * Initialize view.\n         *\n         * @return {exports}\n         */\n        initialize: function () {\n            var billingAddressCode,\n                billingAddressData,\n                defaultAddressData;\n\n            this._super().initChildren();\n            quote.billingAddress.subscribe(function (address) {\n                this.isPlaceOrderActionAllowed(address !== null);\n            }, this);\n            checkoutDataResolver.resolveBillingAddress();\n\n            billingAddressCode = 'billingAddress' + this.getCode();\n            registry.async('checkoutProvider')(function (checkoutProvider) {\n                defaultAddressData = checkoutProvider.get(billingAddressCode);\n\n                if (defaultAddressData === undefined) {\n                    // Skip if payment does not have a billing address form\n                    return;\n                }\n                billingAddressData = checkoutData.getBillingAddressFromData();\n\n                if (billingAddressData) {\n                    checkoutProvider.set(\n                        billingAddressCode,\n                        $.extend(true, {}, defaultAddressData, billingAddressData)\n                    );\n                }\n                checkoutProvider.on(billingAddressCode, function (providerBillingAddressData) {\n                    checkoutData.setBillingAddressFromData(providerBillingAddressData);\n                }, billingAddressCode);\n            });\n\n            return this;\n        },\n\n        /**\n         * Initialize child elements\n         *\n         * @returns {Component} Chainable.\n         */\n        initChildren: function () {\n            this.messageContainer = new Messages();\n            this.createMessagesComponent();\n\n            return this;\n        },\n\n        /**\n         * Create child message renderer component\n         *\n         * @returns {Component} Chainable.\n         */\n        createMessagesComponent: function () {\n\n            var messagesComponent = {\n                parent: this.name,\n                name: this.name + '.messages',\n                displayArea: 'messages',\n                component: 'Magento_Ui/js/view/messages',\n                config: {\n                    messageContainer: this.messageContainer\n                }\n            };\n\n            layout([messagesComponent]);\n\n            return this;\n        },\n\n        /**\n         * Place order.\n         */\n        placeOrder: function (data, event) {\n            var self = this;\n\n            if (event) {\n                event.preventDefault();\n            }\n\n            if (this.validate() &&\n                additionalValidators.validate() &&\n                this.isPlaceOrderActionAllowed() === true\n            ) {\n                this.isPlaceOrderActionAllowed(false);\n\n                this.getPlaceOrderDeferredObject()\n                    .done(\n                        function () {\n                            self.afterPlaceOrder();\n\n                            if (self.redirectAfterPlaceOrder) {\n                                redirectOnSuccessAction.execute();\n                            }\n                        }\n                    ).always(\n                        function () {\n                            self.isPlaceOrderActionAllowed(true);\n                        }\n                    );\n\n                return true;\n            }\n\n            return false;\n        },\n\n        /**\n         * @return {*}\n         */\n        getPlaceOrderDeferredObject: function () {\n            return $.when(\n                placeOrderAction(this.getData(), this.messageContainer)\n            );\n        },\n\n        /**\n         * @return {Boolean}\n         */\n        selectPaymentMethod: function () {\n            selectPaymentMethodAction(this.getData());\n            checkoutData.setSelectedPaymentMethod(this.item.method);\n\n            return true;\n        },\n\n        isChecked: ko.computed(function () {\n            return quote.paymentMethod() ? quote.paymentMethod().method : null;\n        }),\n\n        isRadioButtonVisible: ko.computed(function () {\n            return paymentService.getAvailablePaymentMethods().length !== 1;\n        }),\n\n        /**\n         * Get payment method data\n         */\n        getData: function () {\n            return {\n                'method': this.item.method,\n                'po_number': null,\n                'additional_data': null\n            };\n        },\n\n        /**\n         * Get payment method type.\n         */\n        getTitle: function () {\n            return this.item.title;\n        },\n\n        /**\n         * Get payment method code.\n         */\n        getCode: function () {\n            return this.item.method;\n        },\n\n        /**\n         * @return {Boolean}\n         */\n        validate: function () {\n            return true;\n        },\n\n        /**\n         * @return {String}\n         */\n        getBillingAddressFormName: function () {\n            return 'billing-address-form-' + this.item.method;\n        },\n\n        /**\n         * Dispose billing address subscriptions\n         */\n        disposeSubscriptions: function () {\n            // dispose all active subscriptions\n            var billingAddressCode = 'billingAddress' + this.getCode();\n\n            registry.async('checkoutProvider')(function (checkoutProvider) {\n                checkoutProvider.off(billingAddressCode);\n            });\n        }\n    });\n});\n","Magento_Checkout/js/view/payment/email-validator.js":"/**\n * Copyright \u00a9 Magento, Inc. All rights reserved.\n * See COPYING.txt for license details.\n */\ndefine(\n    [\n        'uiComponent',\n        'Magento_Checkout/js/model/payment/additional-validators',\n        'Magento_Checkout/js/model/customer-email-validator'\n    ],\n    function (Component, additionalValidators, agreementValidator) {\n        'use strict';\n\n        additionalValidators.registerValidator(agreementValidator);\n\n        return Component.extend({});\n    }\n);\n","Magento_Checkout/js/view/payment/list.js":"/**\n * Copyright \u00a9 Magento, Inc. All rights reserved.\n * See COPYING.txt for license details.\n */\n\ndefine([\n    'underscore',\n    'ko',\n    'mageUtils',\n    'uiComponent',\n    'Magento_Checkout/js/model/payment/method-list',\n    'Magento_Checkout/js/model/payment/renderer-list',\n    'uiLayout',\n    'Magento_Checkout/js/model/checkout-data-resolver',\n    'mage/translate',\n    'uiRegistry'\n], function (_, ko, utils, Component, paymentMethods, rendererList, layout, checkoutDataResolver, $t, registry) {\n    'use strict';\n\n    return Component.extend({\n        defaults: {\n            template: 'Magento_Checkout/payment-methods/list',\n            visible: paymentMethods().length > 0,\n            configDefaultGroup: {\n                name: 'methodGroup',\n                component: 'Magento_Checkout/js/model/payment/method-group'\n            },\n            paymentGroupsList: [],\n            defaultGroupTitle: $t('Select a new payment method')\n        },\n\n        /**\n         * Initialize view.\n         *\n         * @returns {Component} Chainable.\n         */\n        initialize: function () {\n            this._super().initDefaulGroup().initChildren();\n            paymentMethods.subscribe(\n                function (changes) {\n                    checkoutDataResolver.resolvePaymentMethod();\n                    //remove renderer for \"deleted\" payment methods\n                    _.each(changes, function (change) {\n                        if (change.status === 'deleted') {\n                            this.removeRenderer(change.value.method);\n                        }\n                    }, this);\n                    //add renderer for \"added\" payment methods\n                    _.each(changes, function (change) {\n                        if (change.status === 'added') {\n                            this.createRenderer(change.value);\n                        }\n                    }, this);\n                }, this, 'arrayChange');\n\n            return this;\n        },\n\n        /** @inheritdoc */\n        initObservable: function () {\n            this._super().\n                observe(['paymentGroupsList']);\n\n            return this;\n        },\n\n        /**\n         * Creates default group\n         *\n         * @returns {Component} Chainable.\n         */\n        initDefaulGroup: function () {\n            layout([\n                this.configDefaultGroup\n            ]);\n\n            return this;\n        },\n\n        /**\n         * Create renders for child payment methods.\n         *\n         * @returns {Component} Chainable.\n         */\n        initChildren: function () {\n            var self = this;\n\n            _.each(paymentMethods(), function (paymentMethodData) {\n                self.createRenderer(paymentMethodData);\n            });\n\n            return this;\n        },\n\n        /**\n         * @returns\n         */\n        createComponent: function (payment) {\n            var rendererTemplate,\n                rendererComponent,\n                templateData;\n\n            templateData = {\n                parentName: this.name,\n                name: payment.name\n            };\n            rendererTemplate = {\n                parent: '${ $.$data.parentName }',\n                name: '${ $.$data.name }',\n                displayArea: payment.displayArea,\n                component: payment.component\n            };\n            rendererComponent = utils.template(rendererTemplate, templateData);\n            utils.extend(rendererComponent, {\n                item: payment.item,\n                config: payment.config\n            });\n\n            return rendererComponent;\n        },\n\n        /**\n         * Create renderer.\n         *\n         * @param {Object} paymentMethodData\n         */\n        createRenderer: function (paymentMethodData) {\n            var isRendererForMethod = false,\n                currentGroup;\n\n            registry.get(this.configDefaultGroup.name, function (defaultGroup) {\n                _.each(rendererList(), function (renderer) {\n\n                    if (renderer.hasOwnProperty('typeComparatorCallback') &&\n                        typeof renderer.typeComparatorCallback == 'function'\n                    ) {\n                        isRendererForMethod = renderer.typeComparatorCallback(renderer.type, paymentMethodData.method);\n                    } else {\n                        isRendererForMethod = renderer.type === paymentMethodData.method;\n                    }\n\n                    if (isRendererForMethod) {\n                        currentGroup = renderer.group ? renderer.group : defaultGroup;\n\n                        this.collectPaymentGroups(currentGroup);\n\n                        layout([\n                            this.createComponent(\n                                {\n                                    config: renderer.config,\n                                    component: renderer.component,\n                                    name: renderer.type,\n                                    method: paymentMethodData.method,\n                                    item: paymentMethodData,\n                                    displayArea: currentGroup.displayArea\n                                }\n                            )]);\n                    }\n                }.bind(this));\n            }.bind(this));\n        },\n\n        /**\n         * Collects unique groups of available payment methods\n         *\n         * @param {Object} group\n         */\n        collectPaymentGroups: function (group) {\n            var groupsList = this.paymentGroupsList(),\n                isGroupExists = _.some(groupsList, function (existsGroup) {\n                    return existsGroup.alias === group.alias;\n                });\n\n            if (!isGroupExists) {\n                groupsList.push(group);\n                groupsList = _.sortBy(groupsList, function (existsGroup) {\n                    return existsGroup.sortOrder;\n                });\n                this.paymentGroupsList(groupsList);\n            }\n        },\n\n        /**\n         * Returns payment group title\n         *\n         * @param {Object} group\n         * @returns {String}\n         */\n        getGroupTitle: function (group) {\n            var title = group().title;\n\n            if (group().isDefault() && this.paymentGroupsList().length > 1) {\n                title = this.defaultGroupTitle;\n            }\n\n            return title;\n        },\n\n        /**\n         * Checks if at least one payment method available\n         *\n         * @returns {String}\n         */\n        isPaymentMethodsAvailable: function () {\n            return _.some(this.paymentGroupsList(), function (group) {\n                return this.regionHasElements(group.displayArea);\n            }, this);\n        },\n\n        /**\n         * Remove view renderer.\n         *\n         * @param {String} paymentMethodCode\n         */\n        removeRenderer: function (paymentMethodCode) {\n            var items;\n\n            _.each(this.paymentGroupsList(), function (group) {\n                items = this.getRegion(group.displayArea);\n\n                _.find(items(), function (value) {\n                    if (value.item.method.indexOf(paymentMethodCode) === 0) {\n                        value.disposeSubscriptions();\n                        value.destroy();\n                    }\n                });\n            }, this);\n        }\n    });\n});\n","Magento_Checkout/js/view/configure/product-customer-data.js":"require([\n    'jquery',\n    'Magento_Customer/js/customer-data',\n    'underscore',\n    'domReady!'\n], function ($, customerData, _) {\n    'use strict';\n\n    var selectors = {\n        qtySelector: '#product_addtocart_form [name=\"qty\"]',\n        productIdSelector: '#product_addtocart_form [name=\"product\"]',\n        itemIdSelector: '#product_addtocart_form [name=\"item\"]'\n    },\n    cartData = customerData.get('cart'),\n    productId = $(selectors.productIdSelector).val(),\n    itemId = $(selectors.itemIdSelector).val(),\n    productQty,\n    productQtyInput,\n\n    /**\n    * Updates product's qty input value according to actual data\n    */\n    updateQty = function () {\n\n        if (productQty || productQty === 0) {\n            productQtyInput = productQtyInput || $(selectors.qtySelector);\n\n            if (productQtyInput && productQty.toString() !== productQtyInput.val()) {\n                productQtyInput.val(productQty);\n            }\n        }\n    },\n\n    /**\n    * Sets productQty according to cart data from customer-data\n    *\n    * @param {Object} data - cart data from customer-data\n    */\n    setProductQty = function (data) {\n        var product;\n\n        if (!(data && data.items && data.items.length && productId)) {\n            return;\n        }\n        product = _.find(data.items, function (item) {\n            if (item['item_id'] === itemId) {\n                return item['product_id'] === productId ||\n                    item['item_id'] === productId;\n            }\n        });\n\n        if (!product) {\n            return;\n        }\n        productQty = product.qty;\n    };\n\n    cartData.subscribe(function (updateCartData) {\n        setProductQty(updateCartData);\n        updateQty();\n    });\n\n    setProductQty(cartData());\n    updateQty();\n});\n","Magento_Checkout/js/view/shipping-address/list.js":"/**\n * Copyright \u00a9 Magento, Inc. All rights reserved.\n * See COPYING.txt for license details.\n */\n\ndefine([\n    'underscore',\n    'ko',\n    'mageUtils',\n    'uiComponent',\n    'uiLayout',\n    'Magento_Customer/js/model/address-list'\n], function (_, ko, utils, Component, layout, addressList) {\n    'use strict';\n\n    var defaultRendererTemplate = {\n        parent: '${ $.$data.parentName }',\n        name: '${ $.$data.name }',\n        component: 'Magento_Checkout/js/view/shipping-address/address-renderer/default',\n        provider: 'checkoutProvider'\n    };\n\n    return Component.extend({\n        defaults: {\n            template: 'Magento_Checkout/shipping-address/list',\n            visible: addressList().length > 0,\n            rendererTemplates: []\n        },\n\n        /** @inheritdoc */\n        initialize: function () {\n            this._super()\n                .initChildren();\n\n            addressList.subscribe(function (changes) {\n                    var self = this;\n\n                    changes.forEach(function (change) {\n                        if (change.status === 'added') {\n                            self.createRendererComponent(change.value, change.index);\n                        }\n                    });\n                },\n                this,\n                'arrayChange'\n            );\n\n            return this;\n        },\n\n        /** @inheritdoc */\n        initConfig: function () {\n            this._super();\n            // the list of child components that are responsible for address rendering\n            this.rendererComponents = [];\n\n            return this;\n        },\n\n        /** @inheritdoc */\n        initChildren: function () {\n            _.each(addressList(), this.createRendererComponent, this);\n\n            return this;\n        },\n\n        /**\n         * Create new component that will render given address in the address list\n         *\n         * @param {Object} address\n         * @param {*} index\n         */\n        createRendererComponent: function (address, index) {\n            var rendererTemplate, templateData, rendererComponent;\n\n            if (index in this.rendererComponents) {\n                this.rendererComponents[index].address(address);\n            } else {\n                // rendererTemplates are provided via layout\n                rendererTemplate = address.getType() != undefined && this.rendererTemplates[address.getType()] != undefined ? //eslint-disable-line\n                    utils.extend({}, defaultRendererTemplate, this.rendererTemplates[address.getType()]) :\n                    defaultRendererTemplate;\n                templateData = {\n                    parentName: this.name,\n                    name: index\n                };\n                rendererComponent = utils.template(rendererTemplate, templateData);\n                utils.extend(rendererComponent, {\n                    address: ko.observable(address)\n                });\n                layout([rendererComponent]);\n                this.rendererComponents[index] = rendererComponent;\n            }\n        }\n    });\n});\n","Magento_Checkout/js/view/shipping-address/address-renderer/default.js":"/**\n * Copyright \u00a9 Magento, Inc. All rights reserved.\n * See COPYING.txt for license details.\n */\n\ndefine([\n    'jquery',\n    'ko',\n    'uiComponent',\n    'underscore',\n    'Magento_Checkout/js/action/select-shipping-address',\n    'Magento_Checkout/js/model/quote',\n    'Magento_Checkout/js/model/shipping-address/form-popup-state',\n    'Magento_Checkout/js/checkout-data',\n    'Magento_Customer/js/customer-data'\n], function ($, ko, Component, _, selectShippingAddressAction, quote, formPopUpState, checkoutData, customerData) {\n    'use strict';\n\n    var countryData = customerData.get('directory-data');\n\n    return Component.extend({\n        defaults: {\n            template: 'Magento_Checkout/shipping-address/address-renderer/default'\n        },\n\n        /** @inheritdoc */\n        initObservable: function () {\n            this._super();\n            this.isSelected = ko.computed(function () {\n                var isSelected = false,\n                    shippingAddress = quote.shippingAddress();\n\n                if (shippingAddress) {\n                    isSelected = shippingAddress.getKey() == this.address().getKey(); //eslint-disable-line eqeqeq\n                }\n\n                return isSelected;\n            }, this);\n\n            return this;\n        },\n\n        /**\n         * @param {String} countryId\n         * @return {String}\n         */\n        getCountryName: function (countryId) {\n            return countryData()[countryId] != undefined ? countryData()[countryId].name : ''; //eslint-disable-line\n        },\n\n        /**\n         * Get customer attribute label\n         *\n         * @param {*} attribute\n         * @returns {*}\n         */\n        getCustomAttributeLabel: function (attribute) {\n            var label;\n\n            if (typeof attribute === 'string') {\n                return attribute;\n            }\n\n            if (attribute.label) {\n                return attribute.label;\n            }\n\n            if (_.isArray(attribute.value)) {\n                label = _.map(attribute.value, function (value) {\n                    return this.getCustomAttributeOptionLabel(attribute['attribute_code'], value) || value;\n                }, this).join(', ');\n            } else if (typeof attribute.value === 'object') {\n                label = _.map(Object.values(attribute.value)).join(', ');\n            } else {\n                label = this.getCustomAttributeOptionLabel(attribute['attribute_code'], attribute.value);\n            }\n\n            return label || attribute.value;\n        },\n\n        /**\n         * Get option label for given attribute code and option ID\n         *\n         * @param {String} attributeCode\n         * @param {String} value\n         * @returns {String|null}\n         */\n        getCustomAttributeOptionLabel: function (attributeCode, value) {\n            var option,\n                label,\n                options = this.source.get('customAttributes') || {};\n\n            if (options[attributeCode]) {\n                option = _.findWhere(options[attributeCode], {\n                    value: value\n                });\n\n                if (option) {\n                    label = option.label;\n                }\n            } else if (value.file !== null) {\n                label = value.file;\n            }\n\n            return label;\n        },\n\n        /** Set selected customer shipping address  */\n        selectAddress: function () {\n            selectShippingAddressAction(this.address());\n            checkoutData.setSelectedShippingAddress(this.address().getKey());\n        },\n\n        /**\n         * Edit address.\n         */\n        editAddress: function () {\n            formPopUpState.isVisible(true);\n            this.showPopup();\n\n        },\n\n        /**\n         * Show popup.\n         */\n        showPopup: function () {\n            $('[data-open-modal=\"opc-new-shipping-address\"]').trigger('click');\n        }\n    });\n});\n","Magento_Checkout/js/view/shipping-information/list.js":"/**\n * Copyright \u00a9 Magento, Inc. All rights reserved.\n * See COPYING.txt for license details.\n */\n\ndefine([\n    'jquery',\n    'ko',\n    'mageUtils',\n    'uiComponent',\n    'uiLayout',\n    'Magento_Checkout/js/model/quote'\n], function ($, ko, utils, Component, layout, quote) {\n    'use strict';\n\n    var defaultRendererTemplate = {\n        parent: '${ $.$data.parentName }',\n        name: '${ $.$data.name }',\n        component: 'Magento_Checkout/js/view/shipping-information/address-renderer/default',\n        provider: 'checkoutProvider'\n    };\n\n    return Component.extend({\n        defaults: {\n            template: 'Magento_Checkout/shipping-information/list',\n            rendererTemplates: {}\n        },\n\n        /** @inheritdoc */\n        initialize: function () {\n            var self = this;\n\n            this._super()\n                .initChildren();\n\n            quote.shippingAddress.subscribe(function (address) {\n                self.createRendererComponent(address);\n            });\n\n            return this;\n        },\n\n        /** @inheritdoc */\n        initConfig: function () {\n            this._super();\n            // the list of child components that are responsible for address rendering\n            this.rendererComponents = {};\n\n            return this;\n        },\n\n        /** @inheritdoc */\n        initChildren: function () {\n            return this;\n        },\n\n        /**\n         * Create new component that will render given address in the address list\n         *\n         * @param {Object} address\n         */\n        createRendererComponent: function (address) {\n            var rendererTemplate, templateData, rendererComponent;\n\n            $.each(this.rendererComponents, function (index, component) {\n                component.visible(false);\n            });\n\n            if (this.rendererComponents[address.getType()]) {\n                this.rendererComponents[address.getType()].address(address);\n                this.rendererComponents[address.getType()].visible(true);\n            } else {\n                // rendererTemplates are provided via layout\n                rendererTemplate = address.getType() != undefined && this.rendererTemplates[address.getType()] != undefined ? //eslint-disable-line\n                    utils.extend({}, defaultRendererTemplate, this.rendererTemplates[address.getType()]) :\n                    defaultRendererTemplate;\n                templateData = {\n                    parentName: this.name,\n                    name: address.getType()\n                };\n\n                rendererComponent = utils.template(rendererTemplate, templateData);\n                utils.extend(\n                    rendererComponent,\n                    {\n                        address: ko.observable(address),\n                        visible: ko.observable(true)\n                    }\n                );\n                layout([rendererComponent]);\n                this.rendererComponents[address.getType()] = rendererComponent;\n            }\n        }\n    });\n});\n","Magento_Checkout/js/view/shipping-information/address-renderer/default.js":"/**\n * Copyright \u00a9 Magento, Inc. All rights reserved.\n * See COPYING.txt for license details.\n */\n\ndefine([\n    'uiComponent',\n    'underscore',\n    'Magento_Customer/js/customer-data'\n], function (Component, _, customerData) {\n    'use strict';\n\n    var countryData = customerData.get('directory-data');\n\n    return Component.extend({\n        defaults: {\n            template: 'Magento_Checkout/shipping-information/address-renderer/default'\n        },\n\n        /**\n         * @param {*} countryId\n         * @return {String}\n         */\n        getCountryName: function (countryId) {\n            return countryData()[countryId] != undefined ? countryData()[countryId].name : ''; //eslint-disable-line\n        },\n\n        /**\n         * Get customer attribute label\n         *\n         * @param {*} attribute\n         * @returns {*}\n         */\n        getCustomAttributeLabel: function (attribute) {\n            var label;\n\n            if (typeof attribute === 'string') {\n                return attribute;\n            }\n\n            if (attribute.label) {\n                return attribute.label;\n            }\n\n            if (_.isArray(attribute.value)) {\n                label = _.map(attribute.value, function (value) {\n                    return this.getCustomAttributeOptionLabel(attribute['attribute_code'], value) || value;\n                }, this).join(', ');\n            } else if (typeof attribute.value === 'object') {\n                label = _.map(Object.values(attribute.value)).join(', ');\n            } else {\n                label = this.getCustomAttributeOptionLabel(attribute['attribute_code'], attribute.value);\n            }\n\n            return label || attribute.value;\n        },\n\n        /**\n         * Get option label for given attribute code and option ID\n         *\n         * @param {String} attributeCode\n         * @param {String} value\n         * @returns {String|null}\n         */\n        getCustomAttributeOptionLabel: function (attributeCode, value) {\n            var option,\n                label,\n                options = this.source.get('customAttributes') || {};\n\n            if (options[attributeCode]) {\n                option = _.findWhere(options[attributeCode], {\n                    value: value\n                });\n\n                if (option) {\n                    label = option.label;\n                }\n            } else if (value.file !== null) {\n                label = value.file;\n            }\n\n            return label;\n        }\n    });\n});\n","Magento_Checkout/js/view/summary/cart-items.js":"/**\n * Copyright \u00a9 Magento, Inc. All rights reserved.\n * See COPYING.txt for license details.\n */\n\ndefine([\n    'ko',\n    'Magento_Checkout/js/model/totals',\n    'uiComponent',\n    'Magento_Checkout/js/model/step-navigator',\n    'Magento_Checkout/js/model/quote'\n], function (ko, totals, Component, stepNavigator, quote) {\n    'use strict';\n\n    var useQty = window.checkoutConfig.useQty;\n\n    return Component.extend({\n        defaults: {\n            template: 'Magento_Checkout/summary/cart-items'\n        },\n        totals: totals.totals(),\n        items: ko.observable([]),\n        maxCartItemsToDisplay: window.checkoutConfig.maxCartItemsToDisplay,\n        cartUrl: window.checkoutConfig.cartUrl,\n\n        /**\n         * @deprecated Please use observable property (this.items())\n         */\n        getItems: totals.getItems(),\n\n        /**\n         * Returns cart items qty\n         *\n         * @returns {Number}\n         */\n        getItemsQty: function () {\n            return parseFloat(this.totals['items_qty']);\n        },\n\n        /**\n         * Returns count of cart line items\n         *\n         * @returns {Number}\n         */\n        getCartLineItemsCount: function () {\n            return parseInt(totals.getItems()().length, 10);\n        },\n\n        /**\n         * Returns shopping cart items summary (includes config settings)\n         *\n         * @returns {Number}\n         */\n        getCartSummaryItemsCount: function () {\n            return useQty ? this.getItemsQty() : this.getCartLineItemsCount();\n        },\n\n        /**\n         * @inheritdoc\n         */\n        initialize: function () {\n            this._super();\n            // Set initial items to observable field\n            this.setItems(totals.getItems()());\n            // Subscribe for items data changes and refresh items in view\n            totals.getItems().subscribe(function (items) {\n                this.setItems(items);\n            }.bind(this));\n        },\n\n        /**\n         * Set items to observable field\n         *\n         * @param {Object} items\n         */\n        setItems: function (items) {\n            if (items && items.length > 0) {\n                items = items.slice(parseInt(-this.maxCartItemsToDisplay, 10));\n            }\n            this.items(items);\n        },\n\n        /**\n         * Returns bool value for items block state (expanded or not)\n         *\n         * @returns {*|Boolean}\n         */\n        isItemsBlockExpanded: function () {\n            return quote.isVirtual() || stepNavigator.isProcessed('shipping');\n        }\n    });\n});\n","Magento_Checkout/js/view/summary/abstract-total.js":"/**\n * Copyright \u00a9 Magento, Inc. All rights reserved.\n * See COPYING.txt for license details.\n */\n\ndefine([\n    'uiComponent',\n    'Magento_Checkout/js/model/quote',\n    'Magento_Catalog/js/price-utils',\n    'Magento_Checkout/js/model/totals',\n    'Magento_Checkout/js/model/step-navigator'\n], function (Component, quote, priceUtils, totals, stepNavigator) {\n    'use strict';\n\n    return Component.extend({\n        /**\n         * @param {*} price\n         * @return {*|String}\n         */\n        getFormattedPrice: function (price) {\n            return priceUtils.formatPriceLocale(price, quote.getPriceFormat());\n        },\n\n        /**\n         * @return {*}\n         */\n        getTotals: function () {\n            return totals.totals();\n        },\n\n        /**\n         * @return {*}\n         */\n        isFullMode: function () {\n            if (!this.getTotals()) {\n                return false;\n            }\n\n            return stepNavigator.isProcessed('shipping');\n        }\n    });\n});\n","Magento_Checkout/js/view/summary/subtotal.js":"/**\n * Copyright \u00a9 Magento, Inc. All rights reserved.\n * See COPYING.txt for license details.\n */\n\ndefine([\n    'Magento_Checkout/js/view/summary/abstract-total',\n    'Magento_Checkout/js/model/quote'\n], function (Component, quote) {\n    'use strict';\n\n    return Component.extend({\n        defaults: {\n            template: 'Magento_Checkout/summary/subtotal'\n        },\n\n        /**\n         * Get pure value.\n         *\n         * @return {*}\n         */\n        getPureValue: function () {\n            var totals = quote.getTotals()();\n\n            if (totals) {\n                return totals.subtotal;\n            }\n\n            return quote.subtotal;\n        },\n\n        /**\n         * @return {*|String}\n         */\n        getValue: function () {\n            return this.getFormattedPrice(this.getPureValue());\n        }\n\n    });\n});\n","Magento_Checkout/js/view/summary/totals.js":"/**\n * Copyright \u00a9 Magento, Inc. All rights reserved.\n * See COPYING.txt for license details.\n */\n\ndefine([\n    'Magento_Checkout/js/view/summary/abstract-total'\n], function (Component) {\n    'use strict';\n\n    return Component.extend({\n        /**\n         * @return {*}\n         */\n        isDisplayed: function () {\n            return this.isFullMode();\n        }\n    });\n});\n","Magento_Checkout/js/view/summary/shipping.js":"/**\n * Copyright \u00a9 Magento, Inc. All rights reserved.\n * See COPYING.txt for license details.\n */\n\ndefine([\n    'jquery',\n    'underscore',\n    'Magento_Checkout/js/view/summary/abstract-total',\n    'Magento_Checkout/js/model/quote',\n    'Magento_SalesRule/js/view/summary/discount'\n], function ($, _, Component, quote, discountView) {\n    'use strict';\n\n    return Component.extend({\n        defaults: {\n            template: 'Magento_Checkout/summary/shipping'\n        },\n        quoteIsVirtual: quote.isVirtual(),\n        totals: quote.getTotals(),\n\n        /**\n         * @return {*}\n         */\n        getShippingMethodTitle: function () {\n            var shippingMethod,\n                shippingMethodTitle = '';\n\n            if (!this.isCalculated()) {\n                return '';\n            }\n            shippingMethod = quote.shippingMethod();\n\n            if (!_.isArray(shippingMethod) && !_.isObject(shippingMethod)) {\n                return '';\n            }\n\n            if (typeof shippingMethod['method_title'] !== 'undefined') {\n                shippingMethodTitle = ' - ' + shippingMethod['method_title'];\n            }\n\n            return shippingMethodTitle ?\n                shippingMethod['carrier_title'] + shippingMethodTitle :\n                shippingMethod['carrier_title'];\n        },\n\n        /**\n         * @return {*|Boolean}\n         */\n        isCalculated: function () {\n            return this.totals() && this.isFullMode() && quote.shippingMethod() != null; //eslint-disable-line eqeqeq\n        },\n\n        /**\n         * @return {*}\n         */\n        getValue: function () {\n            var price;\n\n            if (!this.isCalculated()) {\n                return this.notCalculatedMessage;\n            }\n            price =  this.totals()['shipping_amount'];\n\n            return this.getFormattedPrice(price);\n        },\n\n        /**\n         * If is set coupon code, but there wasn't displayed discount view.\n         *\n         * @return {Boolean}\n         */\n        haveToShowCoupon: function () {\n            var couponCode = this.totals()['coupon_code'];\n\n            if (typeof couponCode === 'undefined') {\n                couponCode = false;\n            }\n\n            return couponCode && !discountView().isDisplayed();\n        },\n\n        /**\n         * Returns coupon code description.\n         *\n         * @return {String}\n         */\n        getCouponDescription: function () {\n            if (!this.haveToShowCoupon()) {\n                return '';\n            }\n\n            return '(' + this.totals()['coupon_code'] + ')';\n        }\n    });\n});\n","Magento_Checkout/js/view/summary/grand-total.js":"/**\n * Copyright \u00a9 Magento, Inc. All rights reserved.\n * See COPYING.txt for license details.\n */\n\ndefine([\n    'Magento_Checkout/js/view/summary/abstract-total',\n    'Magento_Checkout/js/model/quote'\n], function (Component, quote) {\n    'use strict';\n\n    return Component.extend({\n        defaults: {\n            template: 'Magento_Checkout/summary/grand-total'\n        },\n\n        /**\n         * @return {*}\n         */\n        isDisplayed: function () {\n            return this.isFullMode();\n        },\n\n        /**\n         * Get pure value.\n         */\n        getPureValue: function () {\n            var totals = quote.getTotals()();\n\n            if (totals) {\n                return totals['grand_total'];\n            }\n\n            return quote['grand_total'];\n        },\n\n        /**\n         * @return {*|String}\n         */\n        getValue: function () {\n            return this.getFormattedPrice(this.getPureValue());\n        }\n    });\n});\n","Magento_Checkout/js/view/summary/item/details.js":"/**\n * Copyright \u00a9 Magento, Inc. All rights reserved.\n * See COPYING.txt for license details.\n */\n\ndefine([\n    'uiComponent',\n    'escaper'\n], function (Component, escaper) {\n    'use strict';\n\n    return Component.extend({\n        defaults: {\n            template: 'Magento_Checkout/summary/item/details',\n            allowedTags: ['b', 'strong', 'i', 'em', 'u']\n        },\n\n        /**\n         * @param {Object} quoteItem\n         * @return {String}\n         */\n        getNameUnsanitizedHtml: function (quoteItem) {\n            var txt = document.createElement('textarea');\n\n            txt.innerHTML = quoteItem.name;\n\n            return escaper.escapeHtml(txt.value, this.allowedTags);\n        },\n\n        /**\n         * @param {Object} quoteItem\n         * @return {String}Magento_Checkout/js/region-updater\n         */\n        getValue: function (quoteItem) {\n            return quoteItem.name;\n        }\n    });\n});\n","Magento_Checkout/js/view/summary/item/details/message.js":"/**\n * Copyright \u00a9 Magento, Inc. All rights reserved.\n * See COPYING.txt for license details.\n */\n\ndefine(['uiComponent'], function (Component) {\n    'use strict';\n\n    var quoteMessages = window.checkoutConfig.quoteMessages;\n\n    return Component.extend({\n        defaults: {\n            template: 'Magento_Checkout/summary/item/details/message'\n        },\n        displayArea: 'item_message',\n        quoteMessages: quoteMessages,\n\n        /**\n         * @param {Object} item\n         * @return {null}\n         */\n        getMessage: function (item) {\n            if (this.quoteMessages[item['item_id']]) {\n                return this.quoteMessages[item['item_id']];\n            }\n\n            return null;\n        }\n    });\n});\n","Magento_Checkout/js/view/summary/item/details/thumbnail.js":"/**\n * Copyright \u00a9 Magento, Inc. All rights reserved.\n * See COPYING.txt for license details.\n */\n\ndefine(['uiComponent'], function (Component) {\n    'use strict';\n\n    var imageData = window.checkoutConfig.imageData;\n\n    return Component.extend({\n        defaults: {\n            template: 'Magento_Checkout/summary/item/details/thumbnail'\n        },\n        displayArea: 'before_details',\n        imageData: imageData,\n\n        /**\n         * @param {Object} item\n         * @return {Array}\n         */\n        getImageItem: function (item) {\n            if (this.imageData[item['item_id']]) {\n                return this.imageData[item['item_id']];\n            }\n\n            return [];\n        },\n\n        /**\n         * @param {Object} item\n         * @return {null}\n         */\n        getSrc: function (item) {\n            if (this.imageData[item['item_id']]) {\n                return this.imageData[item['item_id']].src;\n            }\n\n            return null;\n        },\n\n        /**\n         * @param {Object} item\n         * @return {null}\n         */\n        getWidth: function (item) {\n            if (this.imageData[item['item_id']]) {\n                return this.imageData[item['item_id']].width;\n            }\n\n            return null;\n        },\n\n        /**\n         * @param {Object} item\n         * @return {null}\n         */\n        getHeight: function (item) {\n            if (this.imageData[item['item_id']]) {\n                return this.imageData[item['item_id']].height;\n            }\n\n            return null;\n        },\n\n        /**\n         * @param {Object} item\n         * @return {null}\n         */\n        getAlt: function (item) {\n            if (this.imageData[item['item_id']]) {\n                return this.imageData[item['item_id']].alt;\n            }\n\n            return null;\n        }\n    });\n});\n","Magento_Checkout/js/view/summary/item/details/subtotal.js":"/**\n * Copyright \u00a9 Magento, Inc. All rights reserved.\n * See COPYING.txt for license details.\n */\n\ndefine([\n    'Magento_Checkout/js/view/summary/abstract-total'\n], function (viewModel) {\n    'use strict';\n\n    return viewModel.extend({\n        defaults: {\n            displayArea: 'after_details',\n            template: 'Magento_Checkout/summary/item/details/subtotal'\n        },\n\n        /**\n         * @param {Object} quoteItem\n         * @return {*|String}\n         */\n        getValue: function (quoteItem) {\n            return this.getFormattedPrice(quoteItem['row_total']);\n        }\n    });\n});\n","Magento_Checkout/js/view/checkout/placeOrderCaptcha.js":"/**\n * Copyright \u00a9 Magento, Inc. All rights reserved.\n * See COPYING.txt for license details.\n */\n\ndefine([\n    'Magento_Captcha/js/view/checkout/defaultCaptcha',\n    'Magento_Captcha/js/model/captchaList',\n    'underscore',\n    'Magento_Checkout/js/model/payment/place-order-hooks'\n],\nfunction (defaultCaptcha, captchaList, _, placeOrderHooks) {\n    'use strict';\n\n    return defaultCaptcha.extend({\n        /** @inheritdoc */\n        initialize: function () {\n            var self = this,\n                currentCaptcha;\n\n            this._super();\n            currentCaptcha = captchaList.getCaptchaByFormId(this.formId);\n            if (currentCaptcha != null) {\n                currentCaptcha.setIsVisible(true);\n                this.setCurrentCaptcha(currentCaptcha);\n                placeOrderHooks.requestModifiers.push(function (headers) {\n                    if (self.isRequired()) {\n                        headers['X-Captcha'] = self.captchaValue()();\n                    }\n                });\n                if (self.isRequired()) {\n                    placeOrderHooks.afterRequestListeners.push(function () {\n                        self.refresh();\n                    });\n                }\n            }\n        }\n    });\n});\n","Magento_Checkout/js/view/checkout/minicart/subtotal/totals.js":"/**\n * Copyright \u00a9 Magento, Inc. All rights reserved.\n * See COPYING.txt for license details.\n */\ndefine([\n    'ko',\n    'uiComponent',\n    'Magento_Customer/js/customer-data'\n], function (ko, Component, customerData) {\n    'use strict';\n\n    return Component.extend({\n        displaySubtotal: ko.observable(true),\n\n        /**\n         * @override\n         */\n        initialize: function () {\n            this._super();\n            this.cart = customerData.get('cart');\n        }\n    });\n});\n","Magento_Checkout/js/view/billing-address/list.js":"/**\n * Copyright \u00a9 Magento, Inc. All rights reserved.\n * See COPYING.txt for license details.\n */\n\ndefine([\n    'uiComponent',\n    'Magento_Customer/js/model/address-list',\n    'mage/translate',\n    'Magento_Customer/js/model/customer'\n], function (Component, addressList, $t, customer) {\n    'use strict';\n\n    var newAddressOption = {\n            /**\n             * Get new address label\n             * @returns {String}\n             */\n            getAddressInline: function () {\n                return $t('New Address');\n            },\n            customerAddressId: null\n        },\n        addressOptions = addressList().filter(function (address) {\n            return address.getType() === 'customer-address';\n        }),\n        addressDefaultIndex = addressOptions.findIndex(function (address) {\n            return address.isDefaultBilling();\n        });\n\n    return Component.extend({\n        defaults: {\n            template: 'Magento_Checkout/billing-address',\n            selectedAddress: null,\n            isNewAddressSelected: false,\n            addressOptions: addressOptions,\n            exports: {\n                selectedAddress: '${ $.parentName }:selectedAddress'\n            }\n        },\n\n        /**\n         * @returns {Object} Chainable.\n         */\n        initConfig: function () {\n            this._super();\n            this.addressOptions.push(newAddressOption);\n\n            return this;\n        },\n\n        /**\n         * @return {exports.initObservable}\n         */\n        initObservable: function () {\n            this._super()\n                .observe('selectedAddress isNewAddressSelected')\n                .observe({\n                    isNewAddressSelected: !customer.isLoggedIn() || !addressOptions.length,\n                    selectedAddress: this.addressOptions[addressDefaultIndex]\n                });\n\n            return this;\n        },\n\n        /**\n         * @param {Object} address\n         * @return {*}\n         */\n        addressOptionsText: function (address) {\n            return address.getAddressInline();\n        },\n\n        /**\n         * @param {Object} address\n         */\n        onAddressChange: function (address) {\n            this.isNewAddressSelected(address === newAddressOption);\n        }\n    });\n});\n","Magento_Checkout/js/model/shipping-rates-validator.js":"/**\n * Copyright \u00a9 Magento, Inc. All rights reserved.\n * See COPYING.txt for license details.\n */\n\n/**\n * @api\n */\ndefine([\n    'jquery',\n    'ko',\n    './shipping-rates-validation-rules',\n    '../model/address-converter',\n    '../action/select-shipping-address',\n    './postcode-validator',\n    './default-validator',\n    'mage/translate',\n    'uiRegistry',\n    'Magento_Checkout/js/model/shipping-address/form-popup-state',\n    'Magento_Checkout/js/model/shipping-service',\n    'Magento_Checkout/js/model/quote'\n], function (\n    $,\n    ko,\n    shippingRatesValidationRules,\n    addressConverter,\n    selectShippingAddress,\n    postcodeValidator,\n    defaultValidator,\n    $t,\n    uiRegistry,\n    formPopUpState,\n    shippingService\n) {\n    'use strict';\n\n    var checkoutConfig = window.checkoutConfig,\n        validators = [],\n        observedElements = [],\n        postcodeElements = [],\n        postcodeElementName = 'postcode';\n\n    validators.push(defaultValidator);\n\n    return {\n        validateAddressTimeout: 0,\n        validateZipCodeTimeout: 0,\n        validateDelay: 2000,\n\n        /**\n         * @param {String} carrier\n         * @param {Object} validator\n         */\n        registerValidator: function (carrier, validator) {\n            if (checkoutConfig.activeCarriers.indexOf(carrier) !== -1) {\n                validators.push(validator);\n            }\n        },\n\n        /**\n         * @param {Object} address\n         * @return {Boolean}\n         */\n        validateAddressData: function (address) {\n            return validators.some(function (validator) {\n                return validator.validate(address);\n            });\n        },\n\n        /**\n         * Perform postponed binding for fieldset elements\n         *\n         * @param {String} formPath\n         */\n        initFields: function (formPath) {\n            var self = this,\n                elements = shippingRatesValidationRules.getObservableFields();\n\n            if ($.inArray(postcodeElementName, elements) === -1) {\n                // Add postcode field to observables if not exist for zip code validation support\n                elements.push(postcodeElementName);\n            }\n\n            $.each(elements, function (index, field) {\n                uiRegistry.async(formPath + '.' + field)(self.doElementBinding.bind(self));\n            });\n        },\n\n        /**\n         * Bind shipping rates request to form element\n         *\n         * @param {Object} element\n         * @param {Boolean} force\n         * @param {Number} delay\n         */\n        doElementBinding: function (element, force, delay) {\n            var observableFields = shippingRatesValidationRules.getObservableFields();\n\n            if (element && (observableFields.indexOf(element.index) !== -1 || force)) {\n                if (element.index !== postcodeElementName) {\n                    this.bindHandler(element, delay);\n                }\n            }\n\n            if (element.index === postcodeElementName) {\n                this.bindHandler(element, delay);\n                postcodeElements.push(element);\n            }\n        },\n\n        /**\n         * @param {*} elements\n         * @param {Boolean} force\n         * @param {Number} delay\n         */\n        bindChangeHandlers: function (elements, force, delay) {\n            var self = this;\n\n            $.each(elements, function (index, elem) {\n                self.doElementBinding(elem, force, delay);\n            });\n        },\n\n        /**\n         * @param {Object} element\n         * @param {Number} delay\n         */\n        bindHandler: function (element, delay) {\n            var self = this;\n\n            delay = typeof delay === 'undefined' ? self.validateDelay : delay;\n\n            if (element.component.indexOf('/group') !== -1) {\n                $.each(element.elems(), function (index, elem) {\n                    self.bindHandler(elem);\n                });\n            } else {\n                element.on('value', function () {\n                    clearTimeout(self.validateZipCodeTimeout);\n                    self.validateZipCodeTimeout = setTimeout(function () {\n                        if (element.index === postcodeElementName) {\n                            self.postcodeValidation(element);\n                        } else {\n                            $.each(postcodeElements, function (index, elem) {\n                                self.postcodeValidation(elem);\n                            });\n                        }\n                    }, delay);\n\n                    if (!formPopUpState.isVisible()) {\n                        // Prevent shipping methods showing none available whilst we resolve\n                        shippingService.isLoading(true);\n                        clearTimeout(self.validateAddressTimeout);\n                        self.validateAddressTimeout = setTimeout(function () {\n                            self.validateFields();\n                        }, delay);\n                    }\n                });\n                observedElements.push(element);\n            }\n        },\n\n        /**\n         * @return {*}\n         */\n        postcodeValidation: function (postcodeElement) {\n            var countryId = $('select[name=\"country_id\"]:visible').val(),\n                validationResult,\n                warnMessage;\n\n            if (postcodeElement == null || postcodeElement.value() == null) {\n                return true;\n            }\n\n            postcodeElement.warn(null);\n            validationResult = postcodeValidator.validate(postcodeElement.value(), countryId);\n\n            if (!validationResult) {\n                warnMessage = $t('Provided Zip/Postal Code seems to be invalid.');\n\n                if (postcodeValidator.validatedPostCodeExample.length) {\n                    warnMessage += $t(' Example: ') + postcodeValidator.validatedPostCodeExample.join('; ') + '. ';\n                }\n                warnMessage += $t('If you believe it is the right one you can ignore this notice.');\n                postcodeElement.warn(warnMessage);\n            }\n\n            return validationResult;\n        },\n\n        /**\n         * Convert form data to quote address and validate fields for shipping rates\n         */\n        validateFields: function () {\n            var addressFlat = addressConverter.formDataProviderToFlatData(\n                this.collectObservedData(),\n                'shippingAddress'\n                ),\n                address;\n\n            if (this.validateAddressData(addressFlat)) {\n                addressFlat = uiRegistry.get('checkoutProvider').shippingAddress;\n                address = addressConverter.formAddressDataToQuoteAddress(addressFlat);\n                selectShippingAddress(address);\n            }\n        },\n\n        /**\n         * Collect observed fields data to object\n         *\n         * @returns {*}\n         */\n        collectObservedData: function () {\n            var observedValues = {};\n\n            $.each(observedElements, function (index, field) {\n                observedValues[field.dataScope] = field.value();\n            });\n\n            return observedValues;\n        }\n    };\n});\n","Magento_Checkout/js/model/shipping-rate-service.js":"/**\n * Copyright \u00a9 Magento, Inc. All rights reserved.\n * See COPYING.txt for license details.\n */\n\ndefine([\n    'Magento_Checkout/js/model/quote',\n    'Magento_Checkout/js/model/shipping-rate-processor/new-address',\n    'Magento_Checkout/js/model/shipping-rate-processor/customer-address'\n], function (quote, defaultProcessor, customerAddressProcessor) {\n    'use strict';\n\n    var processors = {};\n\n    processors.default =  defaultProcessor;\n    processors['customer-address'] = customerAddressProcessor;\n\n    quote.shippingAddress.subscribe(function () {\n        var type = quote.shippingAddress().getType();\n\n        if (processors[type]) {\n            processors[type].getRates(quote.shippingAddress());\n        } else {\n            processors.default.getRates(quote.shippingAddress());\n        }\n    });\n\n    return {\n        /**\n         * @param {String} type\n         * @param {*} processor\n         */\n        registerProcessor: function (type, processor) {\n            processors[type] = processor;\n        }\n    };\n});\n","Magento_Checkout/js/model/payment-service.js":"/**\n * Copyright \u00a9 Magento, Inc. All rights reserved.\n * See COPYING.txt for license details.\n */\n\ndefine([\n    'underscore',\n    'Magento_Checkout/js/model/quote',\n    'Magento_Checkout/js/model/payment/method-list',\n    'Magento_Checkout/js/action/select-payment-method'\n], function (_, quote, methodList, selectPaymentMethod) {\n    'use strict';\n\n    /**\n    * Free method filter\n    * @param {Object} paymentMethod\n    * @return {Boolean}\n    */\n    var isFreePaymentMethod = function (paymentMethod) {\n            return paymentMethod.method === 'free';\n        },\n\n        /**\n         * Grabs the grand total from quote\n         * @return {Number}\n         */\n        getGrandTotal = function () {\n            return quote.totals()['grand_total'];\n        };\n\n    return {\n        isFreeAvailable: false,\n\n        /**\n         * Populate the list of payment methods\n         * @param {Array} methods\n         */\n        setPaymentMethods: function (methods) {\n            var freeMethod,\n                filteredMethods,\n                methodIsAvailable,\n                methodNames;\n\n            freeMethod = _.find(methods, isFreePaymentMethod);\n            this.isFreeAvailable = !!freeMethod;\n\n            if (freeMethod && getGrandTotal() <= 0) {\n                methods.splice(0, methods.length, freeMethod);\n                selectPaymentMethod(freeMethod);\n            }\n\n            filteredMethods = _.without(methods, freeMethod);\n            if (filteredMethods.length === 1) {\n                selectPaymentMethod(filteredMethods[0]);\n            } else if (quote.paymentMethod()) {\n                methodIsAvailable = methods.some(function (item) {\n                    return item.method === quote.paymentMethod().method;\n                });\n\n                if (!methodIsAvailable && !_.isEmpty(window.checkoutConfig.vault)) {\n                    methodIsAvailable = Object.keys(window.checkoutConfig.payment.vault)\n                        .findIndex((vaultPayment) => vaultPayment === quote.paymentMethod().method) !== -1;\n                }\n\n                //Unset selected payment method if not available\n                if (!methodIsAvailable) {\n                    selectPaymentMethod(null);\n                }\n            }\n\n            /**\n             * Overwrite methods with existing methods to preserve ko array references.\n             * This prevent ko from re-rendering those methods.\n             */\n            methodNames = _.pluck(methods, 'method');\n            _.map(methodList(), function (existingMethod) {\n                var existingMethodIndex = methodNames.indexOf(existingMethod.method);\n\n                if (existingMethodIndex !== -1) {\n                    methods[existingMethodIndex] = existingMethod;\n                }\n            });\n\n            methodList(methods);\n        },\n\n        /**\n         * Get the list of available payment methods.\n         * @return {Array}\n         */\n        getAvailablePaymentMethods: function () {\n            var allMethods = methodList().slice(),\n                grandTotalOverZero = getGrandTotal() > 0;\n\n            if (!this.isFreeAvailable) {\n                return allMethods;\n            }\n\n            if (grandTotalOverZero) {\n                return _.reject(allMethods, isFreePaymentMethod);\n            }\n\n            return _.filter(allMethods, isFreePaymentMethod);\n        }\n    };\n});\n","Magento_Checkout/js/model/shipping-rates-validation-rules.js":"/**\n * Copyright \u00a9 Magento, Inc. All rights reserved.\n * See COPYING.txt for license details.\n */\n\n/**\n * @api\n */\ndefine(['jquery'], function ($) {\n    'use strict';\n\n    var ratesRules = {},\n        checkoutConfig = window.checkoutConfig;\n\n    return {\n        /**\n         * @param {String} carrier\n         * @param {Object} rules\n         */\n        registerRules: function (carrier, rules) {\n            if (checkoutConfig.activeCarriers.indexOf(carrier) !== -1) {\n                ratesRules[carrier] = rules.getRules();\n            }\n        },\n\n        /**\n         * @return {Object}\n         */\n        getRules: function () {\n            return ratesRules;\n        },\n\n        /**\n         * @return {Array}\n         */\n        getObservableFields: function () {\n            var self = this,\n                observableFields = [];\n\n            $.each(self.getRules(), function (carrier, fields) {\n                $.each(fields, function (field) {\n                    if (observableFields.indexOf(field) === -1) {\n                        observableFields.push(field);\n                    }\n                });\n            });\n\n            return observableFields;\n        }\n    };\n});\n","Magento_Checkout/js/model/full-screen-loader.js":"/**\n * Copyright \u00a9 Magento, Inc. All rights reserved.\n * See COPYING.txt for license details.\n */\n\ndefine([\n    'jquery',\n    'rjsResolver'\n], function ($, resolver) {\n    'use strict';\n\n    var containerId = '#checkout';\n\n    return {\n\n        /**\n         * Start full page loader action\n         */\n        startLoader: function () {\n            $(containerId).trigger('processStart');\n        },\n\n        /**\n         * Stop full page loader action\n         *\n         * @param {Boolean} [forceStop]\n         */\n        stopLoader: function (forceStop) {\n            var $elem = $(containerId),\n                stop = $elem.trigger.bind($elem, 'processStop'); //eslint-disable-line jquery-no-bind-unbind\n\n            forceStop ? stop() : resolver(stop);\n        }\n    };\n});\n","Magento_Checkout/js/model/checkout-data-resolver.js":"/**\n * Copyright \u00a9 Magento, Inc. All rights reserved.\n * See COPYING.txt for license details.\n */\n\n/**\n * Checkout adapter for customer data storage\n */\ndefine([\n    'Magento_Customer/js/model/address-list',\n    'Magento_Checkout/js/model/quote',\n    'Magento_Checkout/js/checkout-data',\n    'Magento_Checkout/js/action/create-shipping-address',\n    'Magento_Checkout/js/action/select-shipping-address',\n    'Magento_Checkout/js/action/select-shipping-method',\n    'Magento_Checkout/js/model/payment-service',\n    'Magento_Checkout/js/action/select-payment-method',\n    'Magento_Checkout/js/model/address-converter',\n    'Magento_Checkout/js/action/select-billing-address',\n    'Magento_Checkout/js/action/create-billing-address',\n    'underscore'\n], function (\n    addressList,\n    quote,\n    checkoutData,\n    createShippingAddress,\n    selectShippingAddress,\n    selectShippingMethodAction,\n    paymentService,\n    selectPaymentMethodAction,\n    addressConverter,\n    selectBillingAddress,\n    createBillingAddress,\n    _\n) {\n    'use strict';\n\n    var isBillingAddressResolvedFromBackend = false;\n\n    return {\n\n        /**\n         * Resolve estimation address. Used local storage\n         */\n        resolveEstimationAddress: function () {\n            var address;\n\n            if (quote.isVirtual()) {\n                if (checkoutData.getBillingAddressFromData()) {\n                    address = addressConverter.formAddressDataToQuoteAddress(\n                        checkoutData.getBillingAddressFromData()\n                    );\n                    selectBillingAddress(address);\n                } else {\n                    this.resolveBillingAddress();\n                }\n            } else if (checkoutData.getShippingAddressFromData()) {\n                address = addressConverter.formAddressDataToQuoteAddress(checkoutData.getShippingAddressFromData());\n                selectShippingAddress(address);\n            } else {\n                this.resolveShippingAddress();\n            }\n        },\n\n        /**\n         * Resolve shipping address. Used local storage\n         */\n        resolveShippingAddress: function () {\n            var newCustomerShippingAddress;\n\n            if (!checkoutData.getShippingAddressFromData() &&\n                window.checkoutConfig.shippingAddressFromData\n            ) {\n                checkoutData.setShippingAddressFromData(window.checkoutConfig.shippingAddressFromData);\n            }\n\n            newCustomerShippingAddress = checkoutData.getNewCustomerShippingAddress();\n\n            if (newCustomerShippingAddress) {\n                createShippingAddress(newCustomerShippingAddress);\n            }\n            this.applyShippingAddress();\n        },\n\n        /**\n         * Apply resolved estimated address to quote\n         *\n         * @param {Object} isEstimatedAddress\n         */\n        applyShippingAddress: function (isEstimatedAddress) {\n            var address,\n                shippingAddress,\n                isConvertAddress;\n\n            if (addressList().length === 0) {\n                address = addressConverter.formAddressDataToQuoteAddress(\n                    checkoutData.getShippingAddressFromData()\n                );\n                selectShippingAddress(address);\n            }\n            shippingAddress = quote.shippingAddress();\n            isConvertAddress = isEstimatedAddress || false;\n\n            if (!shippingAddress) {\n                shippingAddress = this.getShippingAddressFromCustomerAddressList();\n\n                if (shippingAddress) {\n                    selectShippingAddress(\n                        isConvertAddress ?\n                            addressConverter.addressToEstimationAddress(shippingAddress)\n                            : shippingAddress\n                    );\n                }\n            }\n        },\n\n        /**\n         * @param {Object} ratesData\n         */\n        resolveShippingRates: function (ratesData) {\n            var selectedShippingRate = checkoutData.getSelectedShippingRate(),\n                availableRate = false;\n\n            if (ratesData.length === 1 && !quote.shippingMethod()) {\n                //set shipping rate if we have only one available shipping rate\n                selectShippingMethodAction(ratesData[0]);\n\n                return;\n            }\n\n            if (quote.shippingMethod()) {\n                availableRate = _.find(ratesData, function (rate) {\n                    return rate['carrier_code'] == quote.shippingMethod()['carrier_code'] && //eslint-disable-line\n                        rate['method_code'] == quote.shippingMethod()['method_code']; //eslint-disable-line eqeqeq\n                });\n            }\n\n            if (!availableRate && selectedShippingRate) {\n                availableRate = _.find(ratesData, function (rate) {\n                    return rate['carrier_code'] + '_' + rate['method_code'] === selectedShippingRate;\n                });\n            }\n\n            if (!availableRate && window.checkoutConfig.selectedShippingMethod) {\n                availableRate = _.find(ratesData, function (rate) {\n                    var selectedShippingMethod = window.checkoutConfig.selectedShippingMethod;\n\n                    return rate['carrier_code'] == selectedShippingMethod['carrier_code'] && //eslint-disable-line\n                        rate['method_code'] == selectedShippingMethod['method_code']; //eslint-disable-line eqeqeq\n                });\n            }\n\n            //Unset selected shipping method if not available\n            if (!availableRate) {\n                selectShippingMethodAction(null);\n            } else {\n                selectShippingMethodAction(availableRate);\n            }\n        },\n\n        /**\n         * Resolve payment method. Used local storage\n         */\n        resolvePaymentMethod: function () {\n            var availablePaymentMethods = paymentService.getAvailablePaymentMethods(),\n                selectedPaymentMethod = checkoutData.getSelectedPaymentMethod();\n\n            if (selectedPaymentMethod) {\n                availablePaymentMethods.some(function (payment) {\n                    if (payment.method == selectedPaymentMethod) { //eslint-disable-line eqeqeq\n                        selectPaymentMethodAction(payment);\n                    }\n                });\n            }\n        },\n\n        /**\n         * Resolve billing address. Used local storage\n         */\n        resolveBillingAddress: function () {\n            var selectedBillingAddress,\n                newCustomerBillingAddressData;\n\n            selectedBillingAddress = checkoutData.getSelectedBillingAddress();\n            newCustomerBillingAddressData = checkoutData.getNewCustomerBillingAddress();\n\n            if (selectedBillingAddress) {\n                if (selectedBillingAddress === 'new-customer-billing-address' && newCustomerBillingAddressData) {\n                    selectBillingAddress(createBillingAddress(newCustomerBillingAddressData));\n                } else {\n                    addressList.some(function (address) {\n                        if (selectedBillingAddress === address.getKey()) {\n                            selectBillingAddress(address);\n                        }\n                    });\n                }\n            } else {\n                this.applyBillingAddress();\n            }\n\n            if (!isBillingAddressResolvedFromBackend &&\n                !checkoutData.getBillingAddressFromData() &&\n                !_.isEmpty(window.checkoutConfig.billingAddressFromData) &&\n                !quote.billingAddress()\n            ) {\n                if (window.checkoutConfig.isBillingAddressFromDataValid === true) {\n                    selectBillingAddress(createBillingAddress(window.checkoutConfig.billingAddressFromData));\n                } else {\n                    checkoutData.setBillingAddressFromData(window.checkoutConfig.billingAddressFromData);\n                }\n                isBillingAddressResolvedFromBackend = true;\n            }\n        },\n\n        /**\n         * Apply resolved billing address to quote\n         */\n        applyBillingAddress: function () {\n            var shippingAddress,\n                isBillingAddressInitialized;\n\n            if (quote.billingAddress()) {\n                selectBillingAddress(quote.billingAddress());\n\n                return;\n            }\n\n            if (quote.isVirtual() || !quote.billingAddress()) {\n                isBillingAddressInitialized = addressList.some(function (addrs) {\n                    if (addrs.isDefaultBilling()) {\n                        selectBillingAddress(addrs);\n\n                        return true;\n                    }\n\n                    return false;\n                });\n            }\n\n            shippingAddress = quote.shippingAddress();\n\n            if (!isBillingAddressInitialized &&\n                shippingAddress &&\n                shippingAddress.canUseForBilling() &&\n                (shippingAddress.isDefaultShipping() || !quote.isVirtual())\n            ) {\n                //set billing address same as shipping by default if it is not empty\n                selectBillingAddress(quote.shippingAddress());\n            }\n        },\n\n        /**\n         * Get shipping address from address list\n         *\n         * @return {Object|null}\n         */\n        getShippingAddressFromCustomerAddressList: function () {\n            var shippingAddress = _.find(\n                    addressList(),\n                    function (address) {\n                        return checkoutData.getSelectedShippingAddress() == address.getKey() //eslint-disable-line\n                    }\n                );\n\n            if (!shippingAddress) {\n                shippingAddress = _.find(\n                    addressList(),\n                    function (address) {\n                        return address.isDefaultShipping();\n                    }\n                );\n            }\n\n            if (!shippingAddress && addressList().length === 1) {\n                shippingAddress = addressList()[0];\n            }\n\n            return shippingAddress;\n        }\n    };\n});\n","Magento_Checkout/js/model/default-validation-rules.js":"/**\n * Copyright \u00a9 Magento, Inc. All rights reserved.\n * See COPYING.txt for license details.\n */\n\ndefine([], function () {\n    'use strict';\n\n    return {\n        /**\n         * @return {Object}\n         */\n        getRules: function () {\n            return {\n                'country_id': {\n                    'required': true\n                }\n            };\n        }\n    };\n});\n","Magento_Checkout/js/model/shipping-save-processor.js":"/**\n * Copyright \u00a9 Magento, Inc. All rights reserved.\n * See COPYING.txt for license details.\n */\n\n/**\n * @api\n */\ndefine([\n    'Magento_Checkout/js/model/shipping-save-processor/default'\n], function (defaultProcessor) {\n    'use strict';\n\n    var processors = {};\n\n    processors['default'] =  defaultProcessor;\n\n    return {\n        /**\n         * @param {String} type\n         * @param {*} processor\n         */\n        registerProcessor: function (type, processor) {\n            processors[type] = processor;\n        },\n\n        /**\n         * @param {String} type\n         * @return {Array}\n         */\n        saveShippingInformation: function (type) {\n            var rates = [];\n\n            if (processors[type]) {\n                rates = processors[type].saveShippingInformation();\n            } else {\n                rates = processors['default'].saveShippingInformation();\n            }\n\n            return rates;\n        }\n    };\n});\n","Magento_Checkout/js/model/authentication-messages.js":"/**\n * Copyright \u00a9 Magento, Inc. All rights reserved.\n * See COPYING.txt for license details.\n */\n\ndefine([\n    'ko',\n    'Magento_Ui/js/model/messages'\n], function (ko, Messages) {\n    'use strict';\n\n    return new Messages();\n});\n","Magento_Checkout/js/model/step-navigator.js":"/**\n * Copyright \u00a9 Magento, Inc. All rights reserved.\n * See COPYING.txt for license details.\n */\n\n/**\n * @api\n */\ndefine([\n    'jquery',\n    'ko'\n], function ($, ko) {\n    'use strict';\n\n    var steps = ko.observableArray();\n\n    return {\n        steps: steps,\n        stepCodes: [],\n        validCodes: [],\n\n        /**\n         * @return {Boolean}\n         */\n        handleHash: function () {\n            var hashString = window.location.hash.replace('#', ''),\n                isRequestedStepVisible;\n\n            if (hashString === '') {\n                return false;\n            }\n\n            if ($.inArray(hashString, this.validCodes) === -1) {\n                window.location.href = window.checkoutConfig.pageNotFoundUrl;\n\n                return false;\n            }\n\n            isRequestedStepVisible = steps.sort(this.sortItems).some(function (element) {\n                return (element.code == hashString || element.alias == hashString) && element.isVisible(); //eslint-disable-line\n            });\n\n            //if requested step is visible, then we don't need to load step data from server\n            if (isRequestedStepVisible) {\n                return false;\n            }\n\n            steps().sort(this.sortItems).forEach(function (element) {\n                if (element.code == hashString || element.alias == hashString) { //eslint-disable-line eqeqeq\n                    element.navigate(element);\n                } else {\n                    element.isVisible(false);\n                }\n\n            });\n\n            return false;\n        },\n\n        /**\n         * @param {String} code\n         * @param {*} alias\n         * @param {*} title\n         * @param {Function} isVisible\n         * @param {*} navigate\n         * @param {*} sortOrder\n         */\n        registerStep: function (code, alias, title, isVisible, navigate, sortOrder) {\n            var hash, active;\n\n            if ($.inArray(code, this.validCodes) !== -1) {\n                throw new DOMException('Step code [' + code + '] already registered in step navigator');\n            }\n\n            if (alias != null) {\n                if ($.inArray(alias, this.validCodes) !== -1) {\n                    throw new DOMException('Step code [' + alias + '] already registered in step navigator');\n                }\n                this.validCodes.push(alias);\n            }\n            this.validCodes.push(code);\n            steps.push({\n                code: code,\n                alias: alias != null ? alias : code,\n                title: title,\n                isVisible: isVisible,\n                navigate: navigate,\n                sortOrder: sortOrder\n            });\n            active = this.getActiveItemIndex();\n            steps.each(function (elem, index) {\n                if (active !== index) {\n                    elem.isVisible(false);\n                }\n            });\n            this.stepCodes.push(code);\n            hash = window.location.hash.replace('#', '');\n\n            if (hash != '' && hash != code) { //eslint-disable-line eqeqeq\n                //Force hiding of not active step\n                isVisible(false);\n            }\n        },\n\n        /**\n         * @param {Object} itemOne\n         * @param {Object} itemTwo\n         * @return {Number}\n         */\n        sortItems: function (itemOne, itemTwo) {\n            return itemOne.sortOrder > itemTwo.sortOrder ? 1 : -1;\n        },\n\n        /**\n         * @return {Number}\n         */\n        getActiveItemIndex: function () {\n            var activeIndex = 0;\n\n            steps().sort(this.sortItems).some(function (element, index) {\n                if (element.isVisible()) {\n                    activeIndex = index;\n\n                    return true;\n                }\n\n                return false;\n            });\n\n            return activeIndex;\n        },\n\n        /**\n         * @param {*} code\n         * @return {Boolean}\n         */\n        isProcessed: function (code) {\n            var activeItemIndex = this.getActiveItemIndex(),\n                sortedItems = steps().sort(this.sortItems),\n                requestedItemIndex = -1;\n\n            sortedItems.forEach(function (element, index) {\n                if (element.code == code) { //eslint-disable-line eqeqeq\n                    requestedItemIndex = index;\n                }\n            });\n\n            return activeItemIndex > requestedItemIndex;\n        },\n\n        /**\n         * @param {*} code\n         * @param {*} scrollToElementId\n         */\n        navigateTo: function (code, scrollToElementId) {\n            var sortedItems = steps().sort(this.sortItems),\n                bodyElem = $('body');\n\n            scrollToElementId = scrollToElementId || null;\n\n            if (!this.isProcessed(code)) {\n                return;\n            }\n            sortedItems.forEach(function (element) {\n                if (element.code == code) { //eslint-disable-line eqeqeq\n                    element.isVisible(true);\n                    bodyElem.animate({\n                        scrollTop: $('#' + code).offset().top\n                    }, 0, function () {\n                        window.location = window.checkoutConfig.checkoutUrl + '#' + code;\n                    });\n\n                    if (scrollToElementId && $('#' + scrollToElementId).length) {\n                        bodyElem.animate({\n                            scrollTop: $('#' + scrollToElementId).offset().top\n                        }, 0);\n                    }\n                } else {\n                    element.isVisible(false);\n                }\n\n            });\n        },\n\n        /**\n         * Sets window location hash.\n         *\n         * @param {String} hash\n         */\n        setHash: function (hash) {\n            window.location.hash = hash;\n        },\n\n        /**\n         * Next step.\n         */\n        next: function () {\n            var activeIndex = 0,\n                code;\n\n            steps().sort(this.sortItems).forEach(function (element, index) {\n                if (element.isVisible()) {\n                    element.isVisible(false);\n                    activeIndex = index;\n                }\n            });\n\n            if (steps().length > activeIndex + 1) {\n                code = steps()[activeIndex + 1].code;\n                steps()[activeIndex + 1].isVisible(true);\n                this.setHash(code);\n                document.body.scrollTop = document.documentElement.scrollTop = 0;\n            }\n        }\n    };\n});\n","Magento_Checkout/js/model/place-order.js":"/**\n * Copyright \u00a9 Magento, Inc. All rights reserved.\n * See COPYING.txt for license details.\n */\n/**\n * @api\n */\ndefine(\n    [\n        'mage/storage',\n        'Magento_Checkout/js/model/error-processor',\n        'Magento_Checkout/js/model/full-screen-loader',\n        'Magento_Customer/js/customer-data',\n        'Magento_Checkout/js/model/payment/place-order-hooks',\n        'underscore'\n    ],\n    function (storage, errorProcessor, fullScreenLoader, customerData, hooks, _) {\n        'use strict';\n\n        return function (serviceUrl, payload, messageContainer) {\n            var headers = {}, redirectURL = '';\n\n            fullScreenLoader.startLoader();\n            _.each(hooks.requestModifiers, function (modifier) {\n                modifier(headers, payload);\n            });\n\n            return storage.post(\n                serviceUrl, JSON.stringify(payload), true, 'application/json', headers\n            ).fail(\n                function (response) {\n                    errorProcessor.process(response, messageContainer);\n                    redirectURL = response.getResponseHeader('errorRedirectAction');\n\n                    if (redirectURL) {\n                        setTimeout(function () {\n                            errorProcessor.redirectTo(redirectURL);\n                        }, 3000);\n                    }\n                }\n            ).done(\n                function (response) {\n                    var clearData = {\n                        'selectedShippingAddress': null,\n                        'shippingAddressFromData': null,\n                        'newCustomerShippingAddress': null,\n                        'selectedShippingRate': null,\n                        'selectedPaymentMethod': null,\n                        'selectedBillingAddress': null,\n                        'billingAddressFromData': null,\n                        'newCustomerBillingAddress': null\n                    };\n\n                    if (response.responseType !== 'error') {\n                        customerData.set('checkout-data', clearData);\n                    }\n                }\n            ).always(\n                function () {\n                    fullScreenLoader.stopLoader();\n                    _.each(hooks.afterRequestListeners, function (listener) {\n                        listener();\n                    });\n                }\n            );\n        };\n    }\n);\n","Magento_Checkout/js/model/new-customer-address.js":"/**\n * Copyright \u00a9 Magento, Inc. All rights reserved.\n * See COPYING.txt for license details.\n */\n/**\n * @api\n */\ndefine([\n    'underscore',\n    'Magento_Checkout/js/model/default-post-code-resolver'\n], function (_, DefaultPostCodeResolver) {\n    'use strict';\n\n    /**\n     * @param {Object} addressData\n     * Returns new address object\n     */\n    return function (addressData) {\n        var identifier = Date.now(),\n            countryId = addressData['country_id'] || addressData.countryId || window.checkoutConfig.defaultCountryId,\n            regionId;\n\n        if (addressData.region && addressData.region['region_id']) {\n            regionId = addressData.region['region_id'];\n        } else if (\n            /* eslint-disable */\n            addressData['country_id'] && addressData['country_id'] == window.checkoutConfig.defaultCountryId ||\n            !addressData['country_id'] && countryId == window.checkoutConfig.defaultCountryId\n            /* eslint-enable */\n        ) {\n            regionId = window.checkoutConfig.defaultRegionId || undefined;\n        }\n\n        return {\n            email: addressData.email,\n            countryId: countryId,\n            regionId: regionId || addressData.regionId,\n            regionCode: addressData.region ? addressData.region['region_code'] : null,\n            region: addressData.region ? addressData.region.region : null,\n            customerId: addressData['customer_id'] || addressData.customerId,\n            street: addressData.street,\n            company: addressData.company,\n            telephone: addressData.telephone,\n            fax: addressData.fax,\n            postcode: addressData.postcode ? addressData.postcode : DefaultPostCodeResolver.resolve(),\n            city: addressData.city,\n            firstname: addressData.firstname,\n            lastname: addressData.lastname,\n            middlename: addressData.middlename,\n            prefix: addressData.prefix,\n            suffix: addressData.suffix,\n            vatId: addressData['vat_id'],\n            saveInAddressBook: addressData['save_in_address_book'],\n            customAttributes: addressData['custom_attributes'],\n            extensionAttributes: addressData['extension_attributes'],\n\n            /**\n             * @return {*}\n             */\n            isDefaultShipping: function () {\n                return addressData['default_shipping'];\n            },\n\n            /**\n             * @return {*}\n             */\n            isDefaultBilling: function () {\n                return addressData['default_billing'];\n            },\n\n            /**\n             * @return {String}\n             */\n            getType: function () {\n                return 'new-customer-address';\n            },\n\n            /**\n             * @return {String}\n             */\n            getKey: function () {\n                return this.getType();\n            },\n\n            /**\n             * @return {String}\n             */\n            getCacheKey: function () {\n                return this.getType() + identifier;\n            },\n\n            /**\n             * @return {Boolean}\n             */\n            isEditable: function () {\n                return true;\n            },\n\n            /**\n             * @return {Boolean}\n             */\n            canUseForBilling: function () {\n                return true;\n            }\n        };\n    };\n});\n","Magento_Checkout/js/model/shipping-service.js":"/**\n * Copyright \u00a9 Magento, Inc. All rights reserved.\n * See COPYING.txt for license details.\n */\n\ndefine([\n    'ko',\n    'Magento_Checkout/js/model/checkout-data-resolver'\n], function (ko, checkoutDataResolver) {\n    'use strict';\n\n    var shippingRates = ko.observableArray([]);\n\n    return {\n        isLoading: ko.observable(false),\n\n        /**\n         * Set shipping rates\n         *\n         * @param {*} ratesData\n         */\n        setShippingRates: function (ratesData) {\n            shippingRates(ratesData);\n            shippingRates.valueHasMutated();\n            checkoutDataResolver.resolveShippingRates(ratesData);\n        },\n\n        /**\n         * Get shipping rates\n         *\n         * @returns {*}\n         */\n        getShippingRates: function () {\n            return shippingRates;\n        }\n    };\n});\n","Magento_Checkout/js/model/resource-url-manager.js":"/**\n * Copyright \u00a9 Magento, Inc. All rights reserved.\n * See COPYING.txt for license details.\n */\n\n/**\n * @api\n */\ndefine([\n    'Magento_Customer/js/model/customer',\n    'Magento_Checkout/js/model/url-builder',\n    'mageUtils'\n], function (customer, urlBuilder, utils) {\n        'use strict';\n\n        return {\n            /**\n             * @param {Object} quote\n             * @return {*}\n             */\n            getUrlForTotalsEstimationForNewAddress: function (quote) {\n                var params = this.getCheckoutMethod() == 'guest' ? //eslint-disable-line eqeqeq\n                        {\n                            cartId: quote.getQuoteId()\n                        } : {},\n                    urls = {\n                        'guest': '/guest-carts/:cartId/totals-information',\n                        'customer': '/carts/mine/totals-information'\n                    };\n\n                return this.getUrl(urls, params);\n            },\n\n            /**\n             * @param {Object} quote\n             * @return {*}\n             */\n            getUrlForEstimationShippingMethodsForNewAddress: function (quote) {\n                var params = this.getCheckoutMethod() == 'guest' ? //eslint-disable-line eqeqeq\n                        {\n                            quoteId: quote.getQuoteId()\n                        } : {},\n                    urls = {\n                        'guest': '/guest-carts/:quoteId/estimate-shipping-methods',\n                        'customer': '/carts/mine/estimate-shipping-methods'\n                    };\n\n                return this.getUrl(urls, params);\n            },\n\n            /**\n             * @param {Object} quote\n             * @return {*}\n             */\n            getUrlForEstimationShippingMethodsByAddressId: function (quote) {\n                var params = this.getCheckoutMethod() == 'guest' ? //eslint-disable-line eqeqeq\n                        {\n                            quoteId: quote.getQuoteId()\n                        } : {},\n                    urls = {\n                        'default': '/carts/mine/estimate-shipping-methods-by-address-id'\n                    };\n\n                return this.getUrl(urls, params);\n            },\n\n            /**\n             * @param {String} couponCode\n             * @param {String} quoteId\n             * @return {*}\n             */\n            getApplyCouponUrl: function (couponCode, quoteId) {\n                var params = this.getCheckoutMethod() == 'guest' ? //eslint-disable-line eqeqeq\n                        {\n                            quoteId: quoteId\n                        } : {},\n                    urls = {\n                        'guest': '/guest-carts/' + quoteId + '/coupons/' + encodeURIComponent(couponCode),\n                        'customer': '/carts/mine/coupons/' + encodeURIComponent(couponCode)\n                    };\n\n                return this.getUrl(urls, params);\n            },\n\n            /**\n             * @param {String} quoteId\n             * @return {*}\n             */\n            getCancelCouponUrl: function (quoteId) {\n                var params = this.getCheckoutMethod() == 'guest' ? //eslint-disable-line eqeqeq\n                        {\n                            quoteId: quoteId\n                        } : {},\n                    urls = {\n                        'guest': '/guest-carts/' + quoteId + '/coupons/',\n                        'customer': '/carts/mine/coupons/'\n                    };\n\n                return this.getUrl(urls, params);\n            },\n\n            /**\n             * @param {Object} quote\n             * @return {*}\n             */\n            getUrlForCartTotals: function (quote) {\n                var params = this.getCheckoutMethod() == 'guest' ? //eslint-disable-line eqeqeq\n                        {\n                            quoteId: quote.getQuoteId()\n                        } : {},\n                    urls = {\n                        'guest': '/guest-carts/:quoteId/totals',\n                        'customer': '/carts/mine/totals'\n                    };\n\n                return this.getUrl(urls, params);\n            },\n\n            /**\n             * @param {Object} quote\n             * @return {*}\n             */\n            getUrlForSetShippingInformation: function (quote) {\n                var params = this.getCheckoutMethod() == 'guest' ? //eslint-disable-line eqeqeq\n                        {\n                            cartId: quote.getQuoteId()\n                        } : {},\n                    urls = {\n                        'guest': '/guest-carts/:cartId/shipping-information',\n                        'customer': '/carts/mine/shipping-information'\n                    };\n\n                return this.getUrl(urls, params);\n            },\n\n            /**\n             * Get url for service.\n             *\n             * @param {*} urls\n             * @param {*} urlParams\n             * @return {String|*}\n             */\n            getUrl: function (urls, urlParams) {\n                var url;\n\n                if (utils.isEmpty(urls)) {\n                    return 'Provided service call does not exist.';\n                }\n\n                if (!utils.isEmpty(urls['default'])) {\n                    url = urls['default'];\n                } else {\n                    url = urls[this.getCheckoutMethod()];\n                }\n\n                return urlBuilder.createUrl(url, urlParams);\n            },\n\n            /**\n             * @return {String}\n             */\n            getCheckoutMethod: function () {\n                return customer.isLoggedIn() ? 'customer' : 'guest';\n            }\n        };\n    }\n);\n","Magento_Checkout/js/model/billing-address-postcode-validator.js":"/**\n * Copyright \u00a9 Magento, Inc. All rights reserved.\n * See COPYING.txt for license details.\n */\n\ndefine([\n           'jquery',\n           'Magento_Checkout/js/model/postcode-validator',\n           'mage/translate',\n           'uiRegistry'\n       ], function (\n    $,\n    postcodeValidator,\n    $t,\n    uiRegistry\n) {\n    'use strict';\n\n    var postcodeElementName = 'postcode';\n\n    return {\n        validateZipCodeTimeout: 0,\n        validateDelay: 2000,\n\n        /**\n         * Perform postponed binding for fieldset elements\n         *\n         * @param {String} formPath\n         */\n        initFields: function (formPath) {\n            var self = this;\n\n            uiRegistry.async(formPath + '.' + postcodeElementName)(self.bindHandler.bind(self));\n        },\n\n        /**\n         * @param {Object} element\n         * @param {Number} delay\n         */\n        bindHandler: function (element, delay) {\n            var self = this;\n\n            delay = typeof delay === 'undefined' ? self.validateDelay : delay;\n\n            element.on('value', function () {\n                clearTimeout(self.validateZipCodeTimeout);\n                self.validateZipCodeTimeout = setTimeout(function () {\n                    self.postcodeValidation(element);\n                }, delay);\n            });\n        },\n\n        /**\n         * @param {Object} postcodeElement\n         * @return {*}\n         */\n        postcodeValidation: function (postcodeElement) {\n            var countryId = $('select[name=\"country_id\"]:visible').val(),\n                validationResult,\n                warnMessage;\n\n            if (postcodeElement == null || postcodeElement.value() == null) {\n                return true;\n            }\n\n            postcodeElement.warn(null);\n            validationResult = postcodeValidator.validate(postcodeElement.value(), countryId);\n\n            if (!validationResult) {\n                warnMessage = $t('Provided Zip/Postal Code seems to be invalid.');\n\n                if (postcodeValidator.validatedPostCodeExample.length) {\n                    warnMessage += $t(' Example: ') + postcodeValidator.validatedPostCodeExample.join('; ') + '. ';\n                }\n                warnMessage += $t('If you believe it is the right one you can ignore this notice.');\n                postcodeElement.warn(warnMessage);\n            }\n\n            return validationResult;\n        }\n    };\n});\n","Magento_Checkout/js/model/default-post-code-resolver.js":"/**\n * Copyright \u00a9 Magento, Inc. All rights reserved.\n * See COPYING.txt for license details.\n */\ndefine([], function () {\n    'use strict';\n\n    /**\n     * Define necessity of using default post code value\n     */\n    var useDefaultPostCode;\n\n    return {\n        /**\n         * Resolve default post code\n         *\n         * @returns {String|null}\n         */\n        resolve: function () {\n            return useDefaultPostCode ?  window.checkoutConfig.defaultPostcode : null;\n        },\n\n        /**\n         * Set state to useDefaultPostCode variable\n         *\n         * @param {Boolean} shouldUseDefaultPostCode\n         * @returns {underscore}\n         */\n        setUseDefaultPostCode: function (shouldUseDefaultPostCode) {\n            useDefaultPostCode = shouldUseDefaultPostCode;\n\n            return this;\n        }\n    };\n});\n","Magento_Checkout/js/model/address-converter.js":"/**\n * Copyright \u00a9 Magento, Inc. All rights reserved.\n * See COPYING.txt for license details.\n */\n/**\n * @api\n */\ndefine([\n    'jquery',\n    'Magento_Checkout/js/model/new-customer-address',\n    'Magento_Customer/js/customer-data',\n    'mage/utils/objects',\n    'underscore'\n], function ($, address, customerData, mageUtils, _) {\n    'use strict';\n\n    var countryData = customerData.get('directory-data');\n\n    return {\n        /**\n         * Convert address form data to Address object\n         *\n         * @param {Object} formData\n         * @returns {Object}\n         */\n        formAddressDataToQuoteAddress: function (formData) {\n            // clone address form data to new object\n            var addressData = $.extend(true, {}, formData),\n                region,\n                regionName = addressData.region,\n                customAttributes;\n\n            if (mageUtils.isObject(addressData.street)) {\n                addressData.street = this.objectToArray(addressData.street);\n            }\n\n            addressData.region = {\n                'region_id': addressData['region_id'],\n                'region_code': addressData['region_code'],\n                region: regionName\n            };\n\n            if (addressData['region_id'] &&\n                countryData()[addressData['country_id']] &&\n                countryData()[addressData['country_id']].regions\n            ) {\n                region = countryData()[addressData['country_id']].regions[addressData['region_id']];\n\n                if (region) {\n                    addressData.region['region_id'] = addressData['region_id'];\n                    addressData.region['region_code'] = region.code;\n                    addressData.region.region = region.name;\n                }\n            } else if (\n                !addressData['region_id'] &&\n                countryData()[addressData['country_id']] &&\n                countryData()[addressData['country_id']].regions\n            ) {\n                addressData.region['region_code'] = '';\n                addressData.region.region = '';\n            }\n            delete addressData['region_id'];\n\n            if (addressData['custom_attributes']) {\n                addressData['custom_attributes'] = _.map(\n                    addressData['custom_attributes'],\n                    function (value, key) {\n                        customAttributes = {\n                            'attribute_code': key,\n                            'value': value\n                        };\n\n                        if (typeof value === 'boolean') {\n                            customAttributes = {\n                                'attribute_code': key,\n                                'value': value,\n                                'label': value === true ? 'Yes' : 'No'\n                            };\n                        }\n\n                        return customAttributes;\n                    }\n                );\n            }\n\n            return address(addressData);\n        },\n\n        /**\n         * Convert Address object to address form data.\n         *\n         * @param {Object} addrs\n         * @returns {Object}\n         */\n        quoteAddressToFormAddressData: function (addrs) {\n            var self = this,\n                output = {},\n                streetObject,\n                customAttributesObject;\n\n            $.each(addrs, function (key) {\n                if (addrs.hasOwnProperty(key) && typeof addrs[key] !== 'function') {\n                    output[self.toUnderscore(key)] = addrs[key];\n                }\n            });\n\n            if (Array.isArray(addrs.street)) {\n                streetObject = {};\n                addrs.street.forEach(function (value, index) {\n                    streetObject[index] = value;\n                });\n                output.street = streetObject;\n            }\n\n            //jscs:disable requireCamelCaseOrUpperCaseIdentifiers\n            if (Array.isArray(addrs.customAttributes)) {\n                customAttributesObject = {};\n                addrs.customAttributes.forEach(function (value) {\n                    customAttributesObject[value.attribute_code] = value.value;\n                });\n                output.custom_attributes = customAttributesObject;\n            }\n            //jscs:enable requireCamelCaseOrUpperCaseIdentifiers\n\n            return output;\n        },\n\n        /**\n         * @param {String} string\n         */\n        toUnderscore: function (string) {\n            return string.replace(/([A-Z])/g, function ($1) {\n                return '_' + $1.toLowerCase();\n            });\n        },\n\n        /**\n         * @param {Object} formProviderData\n         * @param {String} formIndex\n         * @return {Object}\n         */\n        formDataProviderToFlatData: function (formProviderData, formIndex) {\n            var addressData = {};\n\n            $.each(formProviderData, function (path, value) {\n                var pathComponents = path.split('.'),\n                    dataObject = {};\n\n                pathComponents.splice(pathComponents.indexOf(formIndex), 1);\n                pathComponents.reverse();\n                $.each(pathComponents, function (index, pathPart) {\n                    var parent = {};\n\n                    if (index == 0) { //eslint-disable-line eqeqeq\n                        dataObject[pathPart] = value;\n                    } else {\n                        parent[pathPart] = dataObject;\n                        dataObject = parent;\n                    }\n                });\n                $.extend(true, addressData, dataObject);\n            });\n\n            return addressData;\n        },\n\n        /**\n         * Convert object to array\n         * @param {Object} object\n         * @returns {Array}\n         */\n        objectToArray: function (object) {\n            var convertedArray = [];\n\n            $.each(object, function (key) {\n                return typeof object[key] === 'string' ? convertedArray.push(object[key]) : false;\n            });\n\n            return convertedArray.slice(0);\n        },\n\n        /**\n         * @param {Object} addrs\n         * @return {*|Object}\n         */\n        addressToEstimationAddress: function (addrs) {\n            var self = this,\n                estimatedAddressData = {};\n\n            $.each(addrs, function (key) {\n                estimatedAddressData[self.toUnderscore(key)] = addrs[key];\n            });\n\n            return this.formAddressDataToQuoteAddress(estimatedAddressData);\n        }\n    };\n});\n","Magento_Checkout/js/model/totals.js":"/**\n * Copyright \u00a9 Magento, Inc. All rights reserved.\n * See COPYING.txt for license details.\n */\n\n/**\n * @api\n */\ndefine([\n    'ko',\n    'Magento_Checkout/js/model/quote',\n    'Magento_Customer/js/customer-data'\n], function (ko, quote, customerData) {\n    'use strict';\n\n    var quoteItems = ko.observable(quote.totals().items),\n        cartData = customerData.get('cart'),\n        quoteSubtotal = parseFloat(quote.totals().subtotal),\n        subtotalAmount = parseFloat(cartData().subtotalAmount);\n\n    quote.totals.subscribe(function (newValue) {\n        quoteItems(newValue.items);\n    });\n\n    if (!isNaN(subtotalAmount) && quoteSubtotal !== subtotalAmount && quoteSubtotal !== 0) {\n        customerData.reload(['cart'], false);\n    }\n\n    return {\n        totals: quote.totals,\n        isLoading: ko.observable(false),\n\n        /**\n         * @return {Function}\n         */\n        getItems: function () {\n            return quoteItems;\n        },\n\n        /**\n         * @param {*} code\n         * @return {*}\n         */\n        getSegment: function (code) {\n            var i, total;\n\n            if (!this.totals()) {\n                return null;\n            }\n\n            for (i in this.totals()['total_segments']) { //eslint-disable-line guard-for-in\n                total = this.totals()['total_segments'][i];\n\n                if (total.code == code) { //eslint-disable-line eqeqeq\n                    return total;\n                }\n            }\n\n            return null;\n        }\n    };\n});\n","Magento_Checkout/js/model/customer-email-validator.js":"/**\n * Copyright \u00a9 Magento, Inc. All rights reserved.\n * See COPYING.txt for license details.\n */\n\ndefine([\n    'jquery',\n    'Magento_Customer/js/model/customer',\n    'mage/validation'\n], function ($, customer) {\n    'use strict';\n\n    return {\n        /**\n         * Validate checkout agreements\n         *\n         * @returns {Boolean}\n         */\n        validate: function () {\n            var emailValidationResult = customer.isLoggedIn(),\n                loginFormSelector = 'form[data-role=email-with-possible-login]';\n\n            if (!customer.isLoggedIn()) {\n                $(loginFormSelector).validation();\n                emailValidationResult = Boolean($(loginFormSelector + ' input[name=username]').valid());\n            }\n\n            return emailValidationResult;\n        }\n    };\n});\n","Magento_Checkout/js/model/quote.js":"/**\n * Copyright \u00a9 Magento, Inc. All rights reserved.\n * See COPYING.txt for license details.\n */\n/**\n * @api\n */\ndefine([\n    'ko',\n    'underscore',\n    'domReady!'\n], function (ko, _) {\n    'use strict';\n\n    /**\n     * Get totals data from the extension attributes.\n     * @param {*} data\n     * @returns {*}\n     */\n    var proceedTotalsData = function (data) {\n            if (_.isObject(data) && _.isObject(data['extension_attributes'])) {\n                _.each(data['extension_attributes'], function (element, index) {\n                    data[index] = element;\n                });\n            }\n\n            return data;\n        },\n        billingAddress = ko.observable(null),\n        shippingAddress = ko.observable(null),\n        shippingMethod = ko.observable(null),\n        paymentMethod = ko.observable(null),\n        quoteData = window.checkoutConfig.quoteData,\n        basePriceFormat = window.checkoutConfig.basePriceFormat,\n        priceFormat = window.checkoutConfig.priceFormat,\n        storeCode = window.checkoutConfig.storeCode,\n        totalsData = proceedTotalsData(window.checkoutConfig.totalsData),\n        totals = ko.observable(totalsData),\n        collectedTotals = ko.observable({});\n\n    return {\n        totals: totals,\n        shippingAddress: shippingAddress,\n        shippingMethod: shippingMethod,\n        billingAddress: billingAddress,\n        paymentMethod: paymentMethod,\n        guestEmail: null,\n\n        /**\n         * @return {*}\n         */\n        getQuoteId: function () {\n            return quoteData['entity_id'];\n        },\n\n        /**\n         * @return {Boolean}\n         */\n        isVirtual: function () {\n            return !!Number(quoteData['is_virtual']);\n        },\n\n        /**\n         * @return {*}\n         */\n        getPriceFormat: function () {\n            return priceFormat;\n        },\n\n        /**\n         * @return {*}\n         */\n        getBasePriceFormat: function () {\n            return basePriceFormat;\n        },\n\n        /**\n         * @return {*}\n         */\n        getItems: function () {\n            return window.checkoutConfig.quoteItemData;\n        },\n\n        /**\n         *\n         * @return {*}\n         */\n        getTotals: function () {\n            return totals;\n        },\n\n        /**\n         * @param {Object} data\n         */\n        setTotals: function (data) {\n            data = proceedTotalsData(data);\n            totals(data);\n            this.setCollectedTotals('subtotal_with_discount', parseFloat(data['subtotal_with_discount']));\n        },\n\n        /**\n         * @param {*} paymentMethodCode\n         */\n        setPaymentMethod: function (paymentMethodCode) {\n            paymentMethod(paymentMethodCode);\n        },\n\n        /**\n         * @return {*}\n         */\n        getPaymentMethod: function () {\n            return paymentMethod;\n        },\n\n        /**\n         * @return {*}\n         */\n        getStoreCode: function () {\n            return storeCode;\n        },\n\n        /**\n         * @param {String} code\n         * @param {*} value\n         */\n        setCollectedTotals: function (code, value) {\n            var colTotals = collectedTotals();\n\n            colTotals[code] = value;\n            collectedTotals(colTotals);\n        },\n\n        /**\n         * @return {Number}\n         */\n        getCalculatedTotal: function () {\n            var total = 0.; //eslint-disable-line no-floating-decimal\n\n            _.each(collectedTotals(), function (value) {\n                total += value;\n            });\n\n            return total;\n        },\n\n        /**\n         * @return {Boolean}\n         */\n        isPersistent: function () {\n            return !!Number(quoteData['is_persistent']);\n        }\n    };\n});\n","Magento_Checkout/js/model/postcode-validator.js":"/**\n * Copyright \u00a9 Magento, Inc. All rights reserved.\n * See COPYING.txt for license details.\n */\n\ndefine([\n    'mageUtils'\n], function (utils) {\n    'use strict';\n\n    return {\n        validatedPostCodeExample: [],\n\n        /**\n         * @param {*} postCode\n         * @param {*} countryId\n         * @param {Array} postCodesPatterns\n         * @return {Boolean}\n         */\n        validate: function (postCode, countryId, postCodesPatterns) {\n            var pattern, regex,\n                patterns = postCodesPatterns ? postCodesPatterns[countryId] :\n                    window.checkoutConfig.postCodes[countryId];\n\n            this.validatedPostCodeExample = [];\n\n            if (!utils.isEmpty(postCode) && !utils.isEmpty(patterns)) {\n                for (pattern in patterns) {\n                    if (patterns.hasOwnProperty(pattern)) { //eslint-disable-line max-depth\n                        this.validatedPostCodeExample.push(patterns[pattern].example);\n                        regex = new RegExp(patterns[pattern].pattern);\n\n                        if (regex.test(postCode)) { //eslint-disable-line max-depth\n                            return true;\n                        }\n                    }\n                }\n\n                return false;\n            }\n\n            return true;\n        }\n    };\n});\n","Magento_Checkout/js/model/error-processor.js":"/**\n * Copyright \u00a9 Magento, Inc. All rights reserved.\n * See COPYING.txt for license details.\n */\n\n/**\n * @api\n */\ndefine([\n    'mage/url',\n    'Magento_Ui/js/model/messageList',\n    'mage/translate'\n], function (url, globalMessageList, $t) {\n    'use strict';\n\n    return {\n        /**\n         * @param {Object} response\n         * @param {Object} messageContainer\n         */\n        process: function (response, messageContainer) {\n            var error;\n\n            messageContainer = messageContainer || globalMessageList;\n\n            if (response.status == 401) { //eslint-disable-line eqeqeq\n                this.redirectTo(url.build('customer/account/login/'));\n            } else {\n                try {\n                    error = JSON.parse(response.responseText);\n                } catch (exception) {\n                    error = {\n                        message: $t('Something went wrong with your request. Please try again later.')\n                    };\n                }\n                messageContainer.addErrorMessage(error);\n            }\n        },\n\n        /**\n         * Method to redirect by requested URL.\n         */\n        redirectTo: function (redirectUrl) {\n            window.location.replace(redirectUrl);\n        }\n    };\n});\n","Magento_Checkout/js/model/default-validator.js":"/**\n * Copyright \u00a9 Magento, Inc. All rights reserved.\n * See COPYING.txt for license details.\n */\n\ndefine([\n    'jquery',\n    'mageUtils',\n    './default-validation-rules',\n    'mage/translate'\n], function ($, utils, validationRules, $t) {\n    'use strict';\n\n    return {\n        validationErrors: [],\n\n        /**\n         * @param {Object} address\n         * @return {Boolean}\n         */\n        validate: function (address) {\n            var self = this;\n\n            this.validationErrors = [];\n            $.each(validationRules.getRules(), function (field, rule) {\n                var message;\n\n                if (rule.required && utils.isEmpty(address[field])) {\n                    message = $t('Field ') + field + $t(' is required.');\n\n                    self.validationErrors.push(message);\n                }\n            });\n\n            return !this.validationErrors.length;\n        }\n    };\n});\n","Magento_Checkout/js/model/sidebar.js":"/**\n * Copyright \u00a9 Magento, Inc. All rights reserved.\n * See COPYING.txt for license details.\n */\n\ndefine([], function () {\n    'use strict';\n\n    return {\n        popUp: false,\n\n        /**\n         * @param {Object} popUp\n         */\n        setPopup: function (popUp) {\n            this.popUp = popUp;\n        },\n\n        /**\n         * Show popup.\n         */\n        show: function () {\n            if (this.popUp) {\n                this.popUp.modal('openModal');\n            }\n        },\n\n        /**\n         * Hide popup.\n         */\n        hide: function () {\n            if (this.popUp) {\n                this.popUp.modal('closeModal');\n            }\n        }\n    };\n});\n","Magento_Checkout/js/model/url-builder.js":"/**\n * Copyright \u00a9 Magento, Inc. All rights reserved.\n * See COPYING.txt for license details.\n */\n\ndefine(['jquery'], function ($) {\n    'use strict';\n\n    return {\n        method: 'rest',\n        storeCode: window.checkoutConfig.storeCode,\n        version: 'V1',\n        serviceUrl: ':method/:storeCode/:version',\n\n        /**\n         * @param {String} url\n         * @param {Object} params\n         * @return {*}\n         */\n        createUrl: function (url, params) {\n            var completeUrl = this.serviceUrl + url;\n\n            return this.bindParams(completeUrl, params);\n        },\n\n        /**\n         * @param {String} url\n         * @param {Object} params\n         * @return {*}\n         */\n        bindParams: function (url, params) {\n            var urlParts;\n\n            params.method = this.method;\n            params.storeCode = this.storeCode;\n            params.version = this.version;\n\n            urlParts = url.split('/');\n            urlParts = urlParts.filter(Boolean);\n\n            $.each(urlParts, function (key, part) {\n                part = part.replace(':', '');\n\n                if (params[part] != undefined) { //eslint-disable-line eqeqeq\n                    urlParts[key] = params[part];\n                }\n            });\n\n            return urlParts.join('/');\n        }\n    };\n});\n","Magento_Checkout/js/model/shipping-rate-registry.js":"/**\n * Copyright \u00a9 Magento, Inc. All rights reserved.\n * See COPYING.txt for license details.\n */\n\ndefine([], function () {\n    'use strict';\n\n    var cache = [];\n\n    return {\n        /**\n         * @param {String} addressKey\n         * @return {*}\n         */\n        get: function (addressKey) {\n            if (cache[addressKey]) {\n                return cache[addressKey];\n            }\n\n            return false;\n        },\n\n        /**\n         * @param {String} addressKey\n         * @param {*} data\n         */\n        set: function (addressKey, data) {\n            cache[addressKey] = data;\n        }\n    };\n});\n","Magento_Checkout/js/model/shipping-save-processor/default.js":"/**\n * Copyright \u00a9 Magento, Inc. All rights reserved.\n * See COPYING.txt for license details.\n */\n\ndefine([\n    'ko',\n    'Magento_Checkout/js/model/quote',\n    'Magento_Checkout/js/model/resource-url-manager',\n    'mage/storage',\n    'Magento_Checkout/js/model/payment-service',\n    'Magento_Checkout/js/model/payment/method-converter',\n    'Magento_Checkout/js/model/error-processor',\n    'Magento_Checkout/js/model/full-screen-loader',\n    'Magento_Checkout/js/action/select-billing-address',\n    'Magento_Checkout/js/model/shipping-save-processor/payload-extender'\n], function (\n    ko,\n    quote,\n    resourceUrlManager,\n    storage,\n    paymentService,\n    methodConverter,\n    errorProcessor,\n    fullScreenLoader,\n    selectBillingAddressAction,\n    payloadExtender\n) {\n    'use strict';\n\n    return {\n        /**\n         * @return {jQuery.Deferred}\n         */\n        saveShippingInformation: function () {\n            var payload;\n\n            if (!quote.billingAddress() && quote.shippingAddress().canUseForBilling()) {\n                selectBillingAddressAction(quote.shippingAddress());\n            }\n\n            payload = {\n                addressInformation: {\n                    'shipping_address': quote.shippingAddress(),\n                    'billing_address': quote.billingAddress(),\n                    'shipping_method_code': quote.shippingMethod()['method_code'],\n                    'shipping_carrier_code': quote.shippingMethod()['carrier_code']\n                }\n            };\n\n            payloadExtender(payload);\n\n            fullScreenLoader.startLoader();\n\n            return storage.post(\n                resourceUrlManager.getUrlForSetShippingInformation(quote),\n                JSON.stringify(payload)\n            ).done(\n                function (response) {\n                    quote.setTotals(response.totals);\n                    paymentService.setPaymentMethods(methodConverter(response['payment_methods']));\n                    fullScreenLoader.stopLoader();\n                }\n            ).fail(\n                function (response) {\n                    errorProcessor.process(response);\n                    fullScreenLoader.stopLoader();\n                }\n            );\n        }\n    };\n});\n","Magento_Checkout/js/model/shipping-save-processor/payload-extender.js":"define([], function () {\n    'use strict';\n\n    return function (payload) {\n        payload.addressInformation['extension_attributes'] = {};\n\n        return payload;\n    };\n});\n","Magento_Checkout/js/model/cart/estimate-service.js":"/**\n * Copyright \u00a9 Magento, Inc. All rights reserved.\n * See COPYING.txt for license details.\n */\n\ndefine([\n    'underscore',\n    'Magento_Checkout/js/model/quote',\n    'Magento_Checkout/js/model/shipping-rate-processor/new-address',\n    'Magento_Checkout/js/model/cart/totals-processor/default',\n    'Magento_Checkout/js/model/shipping-service',\n    'Magento_Checkout/js/model/cart/cache',\n    'Magento_Customer/js/customer-data'\n], function (_, quote, defaultProcessor, totalsDefaultProvider, shippingService, cartCache, customerData) {\n    'use strict';\n\n    var rateProcessors = {},\n        totalsProcessors = {},\n\n        /**\n         * Cache shipping address until changed\n         */\n        setShippingAddress = function () {\n            var shippingAddress = _.pick(quote.shippingAddress(), cartCache.requiredFields);\n\n            cartCache.set('shipping-address', shippingAddress);\n        },\n\n        /**\n         * Estimate totals for shipping address and update shipping rates.\n         */\n        estimateTotalsAndUpdateRates = function () {\n            var type = quote.shippingAddress().getType();\n\n            if (\n                quote.isVirtual() ||\n                window.checkoutConfig.activeCarriers && window.checkoutConfig.activeCarriers.length === 0\n            ) {\n                // update totals block when estimated address was set\n                totalsProcessors['default'] = totalsDefaultProvider;\n                totalsProcessors[type] ?\n                    totalsProcessors[type].estimateTotals(quote.shippingAddress()) :\n                    totalsProcessors['default'].estimateTotals(quote.shippingAddress());\n            } else {\n                // check if user data not changed -> load rates from cache\n                if (!cartCache.isChanged('address', quote.shippingAddress()) &&\n                    !cartCache.isChanged('cartVersion', customerData.get('cart')()['data_id']) &&\n                    cartCache.get('rates') && !cartCache.isChanged('totals', quote.getTotals())\n                ) {\n                    shippingService.setShippingRates(cartCache.get('rates'));\n                    quote.setTotals(cartCache.get('totals'));\n                    return;\n                }\n\n                // update rates list when estimated address was set\n                rateProcessors['default'] = defaultProcessor;\n                rateProcessors[type] ?\n                    rateProcessors[type].getRates(quote.shippingAddress()) :\n                    rateProcessors['default'].getRates(quote.shippingAddress());\n\n                // save rates to cache after load\n                shippingService.getShippingRates().subscribe(function (rates) {\n                    cartCache.set('rates', rates);\n                    setShippingAddress();\n                });\n\n                // update totals based on updated shipping address / rates changes\n                if (cartCache.get('shipping-address') && cartCache.get('shipping-address').countryId &&\n                    cartCache.isChanged('shipping-address',  quote.shippingAddress()) &&\n                    (!quote.shippingMethod() || !quote.shippingMethod()['method_code'])) {\n                    totalsDefaultProvider.estimateTotals(quote.shippingAddress());\n                    cartCache.set('totals', quote.getTotals());\n                }\n            }\n            // unset loader on shipping rates list\n            shippingService.isLoading(false);\n        },\n\n        /**\n         * Estimate totals for shipping address.\n         */\n        estimateTotalsShipping = function () {\n            totalsDefaultProvider.estimateTotals(quote.shippingAddress());\n        },\n\n        /**\n         * Estimate totals for billing address.\n         */\n        estimateTotalsBilling = function () {\n            var type = quote.billingAddress().getType();\n\n            if (quote.isVirtual()) {\n                // update totals block when estimated address was set\n                totalsProcessors['default'] = totalsDefaultProvider;\n                totalsProcessors[type] ?\n                    totalsProcessors[type].estimateTotals(quote.billingAddress()) :\n                    totalsProcessors['default'].estimateTotals(quote.billingAddress());\n            }\n        };\n\n    quote.shippingAddress.subscribe(estimateTotalsAndUpdateRates);\n    quote.shippingMethod.subscribe(estimateTotalsShipping);\n    quote.billingAddress.subscribe(estimateTotalsBilling);\n});\n","Magento_Checkout/js/model/cart/cache.js":"/**\n * Copyright \u00a9 Magento, Inc. All rights reserved.\n * See COPYING.txt for license details.\n */\n\n/**\n * Cart adapter for customer data storage.\n * It stores cart data in customer data(localStorage) without saving on server.\n * Adapter is created for shipping rates and totals data caching. It eliminates unneeded calculations requests.\n */\ndefine([\n    'underscore',\n    'Magento_Customer/js/customer-data',\n    'mageUtils'\n], function (_, storage, utils) {\n    'use strict';\n\n    var cacheKey = 'cart-data',\n        cartData = {\n            totals: null,\n            address: null,\n            cartVersion: null,\n            shippingMethodCode: null,\n            shippingCarrierCode: null,\n            rates: null\n        },\n\n        /**\n         * Set data to local storage.\n         *\n         * @param {Object} checkoutData\n         */\n        setData = function (checkoutData) {\n            storage.set(cacheKey, checkoutData);\n        },\n\n        /**\n         * Get data from local storage.\n         *\n         * @param {String} [key]\n         * @returns {*}\n         */\n        getData = function (key) {\n            var data = key ? storage.get(cacheKey)()[key] : storage.get(cacheKey)();\n\n            if (_.isEmpty(storage.get(cacheKey)())) {\n                setData(utils.copy(cartData));\n            }\n\n            return data;\n        },\n\n        /**\n         * Build method name base on name, prefix and suffix.\n         *\n         * @param {String} name\n         * @param {String} prefix\n         * @param {String} suffix\n         * @return {String}\n         */\n        getMethodName = function (name, prefix, suffix) {\n            prefix = prefix || '';\n            suffix = suffix || '';\n\n            return prefix + name.charAt(0).toUpperCase() + name.slice(1) + suffix;\n        };\n\n    /**\n     * Provides get/set/isChanged/clear methods for work with cart data.\n     * Can be customized via mixin functionality.\n     */\n    return {\n        cartData: cartData,\n\n        /**\n         * Array of required address fields\n         */\n        requiredFields: ['countryId', 'region', 'regionId', 'postcode'],\n\n        /**\n         * Get data from customer data.\n         * Concatenate provided key with method name and call method if it exist or makes get by key.\n         *\n         * @param {String} key\n         * @return {*}\n         */\n        get: function (key) {\n            var methodName = getMethodName(key, '_get');\n\n            if (key === cacheKey) {\n                return getData();\n            }\n\n            if (this[methodName]) {\n                return this[methodName]();\n            }\n\n            return getData(key);\n        },\n\n        /**\n         * Set data to customer data.\n         * Concatenate provided key with method name and call method if it exist or makes set by key.\n         * @example _setCustomAddress method will be called, if it exists.\n         *  set('address', customAddressValue)\n         * @example Will set value by provided key.\n         *  set('rates', ratesToCompare)\n         *\n         * @param {String} key\n         * @param {*} value\n         */\n        set: function (key, value) {\n            var methodName = getMethodName(key, '_set'),\n                obj;\n\n            if (key === cacheKey) {\n                _.each(value, function (val, k) {\n                    this.set(k, val);\n                }, this);\n\n                return;\n            }\n\n            if (this[methodName]) {\n                this[methodName](value);\n            } else {\n                obj = getData();\n                obj[key] = value;\n                setData(obj);\n            }\n        },\n\n        /**\n         * Clear data in cache.\n         * Concatenate provided key with method name and call method if it exist or clear by key.\n         * @example _clearCustomAddress method will be called, if it exist.\n         *  clear('customAddress')\n         * @example Will clear data by provided key.\n         *  clear('rates')\n         *\n         * @param {String} key\n         */\n        clear: function (key) {\n            var methodName = getMethodName(key, '_clear');\n\n            if (key === cacheKey) {\n                setData(this.cartData);\n\n                return;\n            }\n\n            if (this[methodName]) {\n                this[methodName]();\n            } else {\n                this.set(key, null);\n            }\n        },\n\n        /**\n         * Check if provided data has difference with cached data.\n         * Concatenate provided key with method name and call method if it exist or makes strict equality.\n         * @example Will call existing _isAddressChanged.\n         *  isChanged('address', addressToCompare)\n         * @example Will get data by provided key and make strict equality with provided value.\n         *  isChanged('rates', ratesToCompare)\n         *\n         * @param {String} key\n         * @param {*} value\n         * @return {Boolean}\n         */\n        isChanged: function (key, value) {\n            var methodName = getMethodName(key, '_is', 'Changed');\n\n            if (this[methodName]) {\n                return this[methodName](value);\n            }\n\n            return this.get(key) !== value;\n        },\n\n        /**\n         * Compare cached address with provided.\n         * Custom method for check object equality.\n         *\n         * @param {Object} address\n         * @returns {Boolean}\n         */\n        _isAddressChanged: function (address) {\n            return JSON.stringify(_.pick(this.get('address'), this.requiredFields)) !==\n                JSON.stringify(_.pick(address, this.requiredFields));\n        },\n\n        /**\n         * Compare cached subtotal with provided.\n         * Custom method for check object equality.\n         *\n         * @param {float} subtotal\n         * @returns {Boolean}\n         */\n        _isSubtotalChanged: function (subtotal) {\n            var cached = parseFloat(this.get('totals').subtotal);\n\n            return subtotal !== cached;\n        }\n    };\n});\n","Magento_Checkout/js/model/cart/totals-processor/default.js":"/**\n * Copyright \u00a9 Magento, Inc. All rights reserved.\n * See COPYING.txt for license details.\n */\n\ndefine([\n    'underscore',\n    'Magento_Checkout/js/model/resource-url-manager',\n    'Magento_Checkout/js/model/quote',\n    'mage/storage',\n    'Magento_Checkout/js/model/totals',\n    'Magento_Checkout/js/model/error-processor',\n    'Magento_Checkout/js/model/cart/cache',\n    'Magento_Customer/js/customer-data'\n], function (_, resourceUrlManager, quote, storage, totalsService, errorProcessor, cartCache, customerData) {\n    'use strict';\n\n    /**\n     * Load data from server.\n     *\n     * @param {Object} address\n     */\n    var loadFromServer = function (address) {\n        var serviceUrl,\n            payload;\n\n        // Start loader for totals block\n        totalsService.isLoading(true);\n        serviceUrl = resourceUrlManager.getUrlForTotalsEstimationForNewAddress(quote);\n        payload = {\n            addressInformation: {\n                address: _.pick(address, cartCache.requiredFields)\n            }\n        };\n\n        if (quote.shippingMethod() && quote.shippingMethod()['method_code']) {\n            payload.addressInformation['shipping_method_code'] = quote.shippingMethod()['method_code'];\n            payload.addressInformation['shipping_carrier_code'] = quote.shippingMethod()['carrier_code'];\n        }\n\n        return storage.post(\n            serviceUrl, JSON.stringify(payload), false\n        ).done(function (result) {\n            var data = {\n                totals: result,\n                address: address,\n                cartVersion: customerData.get('cart')()['data_id'],\n                shippingMethodCode: null,\n                shippingCarrierCode: null\n            };\n\n            if (quote.shippingMethod() && quote.shippingMethod()['method_code']) {\n                data.shippingMethodCode = quote.shippingMethod()['method_code'];\n                data.shippingCarrierCode = quote.shippingMethod()['carrier_code'];\n            }\n\n            quote.setTotals(result);\n            cartCache.set('cart-data', data);\n        }).fail(function (response) {\n            errorProcessor.process(response);\n        }).always(function () {\n            // Stop loader for totals block\n            totalsService.isLoading(false);\n        });\n    };\n\n    return {\n        /**\n         * Array of required address fields.\n         * @property {Array.String} requiredFields\n         * @deprecated Use cart cache.\n         */\n        requiredFields: cartCache.requiredFields,\n\n        /**\n         * Get shipping rates for specified address.\n         * @param {Object} address\n         */\n        estimateTotals: function (address) {\n            return loadFromServer(address);\n        }\n    };\n});\n","Magento_Checkout/js/model/payment/method-list.js":"/**\n * Copyright \u00a9 Magento, Inc. All rights reserved.\n * See COPYING.txt for license details.\n */\n\ndefine([\n    'ko'\n], function (ko) {\n    'use strict';\n\n    return ko.observableArray([]);\n});\n","Magento_Checkout/js/model/payment/method-group.js":"/**\n * Copyright \u00a9 Magento, Inc. All rights reserved.\n * See COPYING.txt for license details.\n */\n\ndefine([\n        'uiElement',\n        'mage/translate'\n], function (Element, $t) {\n    'use strict';\n\n    var DEFAULT_GROUP_ALIAS = 'default';\n\n    return Element.extend({\n        defaults: {\n            alias: DEFAULT_GROUP_ALIAS,\n            title: $t('Payment Method'),\n            sortOrder: 100,\n            displayArea: 'payment-methods-items-${ $.alias }'\n        },\n\n        /**\n         * Checks if group instance is default\n         *\n         * @returns {Boolean}\n         */\n        isDefault: function () {\n            return this.alias === DEFAULT_GROUP_ALIAS;\n        }\n    });\n});\n","Magento_Checkout/js/model/payment/place-order-hooks.js":"/**\n * Copyright \u00a9 Magento, Inc. All rights reserved.\n * See COPYING.txt for license details.\n */\n\ndefine([], function () {\n    'use strict';\n\n    return {\n        requestModifiers: [],\n        afterRequestListeners: []\n    };\n});\n","Magento_Checkout/js/model/payment/method-converter.js":"/**\n * Copyright \u00a9 Magento, Inc. All rights reserved.\n * See COPYING.txt for license details.\n */\n\ndefine([\n    'underscore'\n], function (_) {\n    'use strict';\n\n    return function (methods) {\n        _.each(methods, function (method) {\n            if (method.hasOwnProperty('code')) {\n                method.method = method.code;\n                delete method.code;\n            }\n        });\n\n        return methods;\n    };\n});\n","Magento_Checkout/js/model/payment/additional-validators.js":"/**\n * Copyright \u00a9 Magento, Inc. All rights reserved.\n * See COPYING.txt for license details.\n */\n\n/**\n * @api\n */\ndefine([], function () {\n    'use strict';\n\n    var validators = [];\n\n    return {\n        /**\n         * Register unique validator\n         *\n         * @param {*} validator\n         */\n        registerValidator: function (validator) {\n            validators.push(validator);\n        },\n\n        /**\n         * Returns array of registered validators\n         *\n         * @returns {Array}\n         */\n        getValidators: function () {\n            return validators;\n        },\n\n        /**\n         * Process validators\n         *\n         * @returns {Boolean}\n         */\n        validate: function (hideError) {\n            var validationResult = true;\n\n            hideError = hideError || false;\n\n            if (validators.length <= 0) {\n                return validationResult;\n            }\n\n            validators.forEach(function (item) {\n                if (item.validate(hideError) == false) { //eslint-disable-line eqeqeq\n                    validationResult = false;\n\n                    return false;\n                }\n            });\n\n            return validationResult;\n        }\n    };\n});\n","Magento_Checkout/js/model/payment/renderer-list.js":"/**\n * Copyright \u00a9 Magento, Inc. All rights reserved.\n * See COPYING.txt for license details.\n */\n\ndefine([\n    'ko'\n], function (ko) {\n    'use strict';\n\n    return ko.observableArray([]);\n});\n","Magento_Checkout/js/model/shipping-rate-processor/new-address.js":"/**\n * Copyright \u00a9 Magento, Inc. All rights reserved.\n * See COPYING.txt for license details.\n */\ndefine([\n    'Magento_Checkout/js/model/resource-url-manager',\n    'Magento_Checkout/js/model/quote',\n    'mage/storage',\n    'Magento_Checkout/js/model/shipping-service',\n    'Magento_Checkout/js/model/shipping-rate-registry',\n    'Magento_Checkout/js/model/error-processor'\n], function (resourceUrlManager, quote, storage, shippingService, rateRegistry, errorProcessor) {\n    'use strict';\n\n    return {\n        /**\n         * Get shipping rates for specified address.\n         * @param {Object} address\n         */\n        getRates: function (address) {\n            var cache, serviceUrl, payload;\n\n            shippingService.isLoading(true);\n            cache = rateRegistry.get(address.getCacheKey());\n            serviceUrl = resourceUrlManager.getUrlForEstimationShippingMethodsForNewAddress(quote);\n            payload = JSON.stringify({\n                    address: {\n                        'street': address.street,\n                        'city': address.city,\n                        'region_id': address.regionId,\n                        'region': address.region,\n                        'country_id': address.countryId,\n                        'postcode': address.postcode,\n                        'email': address.email,\n                        'customer_id': address.customerId,\n                        'firstname': address.firstname,\n                        'lastname': address.lastname,\n                        'middlename': address.middlename,\n                        'prefix': address.prefix,\n                        'suffix': address.suffix,\n                        'vat_id': address.vatId,\n                        'company': address.company,\n                        'telephone': address.telephone,\n                        'fax': address.fax,\n                        'custom_attributes': address.customAttributes,\n                        'save_in_address_book': address.saveInAddressBook\n                    }\n                }\n            );\n\n            if (cache) {\n                shippingService.setShippingRates(cache);\n                shippingService.isLoading(false);\n            } else {\n                let async = quote.isPersistent() ? false : true;\n\n                storage.post(\n                    serviceUrl, payload, false, 'application/json', {}, async\n                ).done(function (result) {\n                    rateRegistry.set(address.getCacheKey(), result);\n                    shippingService.setShippingRates(result);\n                }).fail(function (response) {\n                    shippingService.setShippingRates([]);\n                    errorProcessor.process(response);\n                }).always(function () {\n                    shippingService.isLoading(false);\n                });\n            }\n        }\n    };\n});\n","Magento_Checkout/js/model/shipping-rate-processor/customer-address.js":"/**\n * Copyright \u00a9 Magento, Inc. All rights reserved.\n * See COPYING.txt for license details.\n */\n\ndefine([\n    'Magento_Checkout/js/model/resource-url-manager',\n    'Magento_Checkout/js/model/quote',\n    'mage/storage',\n    'Magento_Checkout/js/model/shipping-service',\n    'Magento_Checkout/js/model/shipping-rate-registry',\n    'Magento_Checkout/js/model/error-processor'\n], function (resourceUrlManager, quote, storage, shippingService, rateRegistry, errorProcessor) {\n    'use strict';\n\n    return {\n        /**\n         * @param {Object} address\n         */\n        getRates: function (address) {\n            var cache;\n\n            shippingService.isLoading(true);\n            cache = rateRegistry.get(address.getKey());\n\n            if (cache) {\n                shippingService.setShippingRates(cache);\n                shippingService.isLoading(false);\n            } else {\n                storage.post(\n                    resourceUrlManager.getUrlForEstimationShippingMethodsByAddressId(),\n                    JSON.stringify({\n                        addressId: address.customerAddressId\n                    }),\n                    false\n                ).done(function (result) {\n                    rateRegistry.set(address.getKey(), result);\n                    shippingService.setShippingRates(result);\n                }).fail(function (response) {\n                    shippingService.setShippingRates([]);\n                    errorProcessor.process(response);\n                }).always(function () {\n                    shippingService.isLoading(false);\n                }\n                );\n            }\n        }\n    };\n});\n","Magento_Checkout/js/model/shipping-address/form-popup-state.js":"/**\n * Copyright \u00a9 Magento, Inc. All rights reserved.\n * See COPYING.txt for license details.\n */\n\ndefine([\n    'ko'\n], function (ko) {\n    'use strict';\n\n    return {\n        isVisible: ko.observable(false)\n    };\n});\n","PayPal_Braintree/js/validator.js":"/**\n * Copyright \u00a9 Magento, Inc. All rights reserved.\n * See COPYING.txt for license details.\n */\n/*browser:true*/\ndefine([\n    'underscore'\n], function (_) {\n    'use strict';\n\n    return {\n        config: {},\n\n        /**\n         * Set configuration\n         * @param {Object} config\n         */\n        setConfig: function (config) {\n            this.config = config;\n        },\n\n        /**\n         * Get List of available card types\n         * @returns {*|exports.defaults.availableCardTypes|{}}\n         */\n        getAvailableCardTypes: function () {\n            return this.config.availableCardTypes;\n        },\n\n        /**\n         * Get list of card types\n         * @returns {Object}\n         */\n        getCcTypesMapper: function () {\n            return this.config.ccTypesMapper;\n        },\n\n        /**\n         * Find mage card type by Braintree type\n         * @param {String} type\n         * @param {Object} availableTypes\n         * @returns {*}\n         */\n        getMageCardType: function (type, availableTypes) {\n            var storedCardType = null,\n                mapper = this.getCcTypesMapper();\n\n            if (type && typeof mapper[type] !== 'undefined') {\n                storedCardType = mapper[type];\n\n                if (_.indexOf(availableTypes, storedCardType) !== -1) {\n                    return storedCardType;\n                }\n            }\n\n            return null;\n        },\n\n        /**\n         * Filter list of available card types\n         * @param {Object} availableTypes\n         * @param {Object} countrySpecificCardTypes\n         * @returns {Object}\n         */\n        collectTypes: function (availableTypes, countrySpecificCardTypes) {\n            var key,\n                filteredTypes = [];\n\n            for (key in availableTypes) {\n                if (_.indexOf(countrySpecificCardTypes, availableTypes[key]) !== -1) {\n                    filteredTypes.push(availableTypes[key]);\n                }\n            }\n\n            return filteredTypes;\n        },\n\n        /**\n         * Get list of card types for country\n         * @param {String} countryId\n         * @returns {*}\n         */\n        getCountrySpecificCardTypes: function (countryId) {\n            if (typeof this.config.countrySpecificCardTypes[countryId] !== 'undefined') {\n                return this.config.countrySpecificCardTypes[countryId];\n            }\n\n            return false;\n        }\n    };\n});\n","PayPal_Braintree/js/form-builder.js":"/**\n * Copyright \u00a9 Magento, Inc. All rights reserved.\n * See COPYING.txt for license details.\n */\ndefine(\n    [\n        'jquery',\n        'underscore',\n        'mage/template'\n    ],\n    function ($, _, mageTemplate) {\n        'use strict';\n\n        return {\n\n            /**\n             * @param {Object} formData\n             * @returns {*|jQuery}\n             */\n            build: function (formData) {\n                var formTmpl = mageTemplate('<form action=\"<%= data.action %>\"' +\n                    ' method=\"POST\" hidden enctype=\"application/x-www-form-urlencoded\">' +\n                        '<% _.each(data.fields, function(val, key){ %>' +\n                            '<input value=\\'<%= val %>\\' name=\"<%= key %>\" type=\"hidden\">' +\n                        '<% }); %>' +\n                    '</form>');\n\n                return $(formTmpl({\n                    data: {\n                        action: formData.action,\n                        fields: formData.fields\n                    }\n                })).appendTo($('[data-container=\"body\"]'));\n            }\n        };\n    }\n);\n","PayPal_Braintree/js/helper/format-amount.js":"define(function () {\n    'use strict';\n\n    /**\n     * Format amount (string) to two decimals.\n     *\n     * @param {string} str\n     * @return {string}\n     */\n    return function (amount) {\n        return parseFloat(amount).toFixed(2);\n    };\n});\n","PayPal_Braintree/js/helper/remove-non-digit-characters.js":"define([\n    'underscore'\n], function (_) {\n    'use strict';\n\n    /**\n     * Remove any non-digit characters from string.\n     *\n     * @param {string} value\n     * @return {string}\n     */\n    return function (value) {\n        return _.isString(value) ? value.replace(/\\D/g, '') : '';\n    };\n});\n","PayPal_Braintree/js/helper/create-client-token.js":"define(['jquery'], function ($) {\n    'use strict';\n\n    return function () {\n        return $.ajax({\n            method: 'POST',\n            url: '/graphql',\n            contentType: 'application/json',\n            data: JSON.stringify({\n                query: `\n                    mutation {\n                      createBraintreeClientToken\n                    }`\n            })\n        });\n    };\n});\n","PayPal_Braintree/js/helper/escape-non-ascii-characters.js":"define(function () {\n    'use strict';\n\n    /**\n     * Convert Non-ASCII characters into unicode.\n     *\n     * @param {string} value\n     * @return {string}\n     */\n    return function (value) {\n        return value.split('').map(function (c) {\n            return /^[\\x00-\\x7F]$/.test(c) ? c : c.split('').map(function (a) {\n                return '\\\\u00' + a.charCodeAt(0).toString(16);\n            }).join('');\n        }).join('');\n    };\n});\n","PayPal_Braintree/js/helper/replace-single-quote-character.js":"define([\n    'underscore'\n], function (_) {\n    'use strict';\n\n    /**\n     * Replace single quote character to HTML entity string.\n     *\n     * @param {string} value\n     * @return {string}\n     */\n    return function (value) {\n        return _.isString(value) ? value.replace(/'/g, '&apos;') : '';\n    };\n});\n","PayPal_Braintree/js/helper/get-braintree-config.js":"define(['jquery'], function ($) {\n    'use strict';\n\n    return function () {\n        return $.ajax({\n            method: 'POST',\n            url: '/graphql',\n            contentType: 'application/json',\n            data: JSON.stringify({\n                query: `{\n                    storeConfig {\n                        braintree_merchant_account_id,\n                        braintree_3dsecure_verify_3dsecure,\n                        braintree_3dsecure_always_request_3ds,\n                        braintree_3dsecure_threshold_amount,\n                        braintree_3dsecure_allowspecific,\n                        braintree_3dsecure_specificcountry\n                    }\n                  }`\n            })\n        });\n    };\n});\n","PayPal_Braintree/js/helper/replace-unsupported-characters.js":"define(function () {\n    'use strict';\n\n    /**\n     * Regex to replace all unsupported characters from string.\n     *\n     * @param {String} str\n     * @return {String}\n     */\n    return function (str) {\n        // eslint-disable-next-line no-useless-escape\n        return str.replace('/[^a-zA-Z0-9\\s\\-.\\']/', '').substring(0, 127);\n    };\n});\n","PayPal_Braintree/js/helper/get-cart-line-items-helper.js":"define([\n    'jquery',\n    'underscore',\n    'PayPal_Braintree/js/helper/format-amount',\n    'PayPal_Braintree/js/helper/replace-unsupported-characters',\n    'Magento_Checkout/js/model/quote'\n], function (\n    $,\n    _,\n    formatAmount,\n    replaceUnsupportedCharacters,\n    quote\n) {\n    'use strict';\n\n    /**\n     * Get line items\n     *\n     * @returns {Array}\n     */\n    return function () {\n        let lineItems = [];\n\n        /**\n         * Line items array\n         *\n         * {Array}\n         */\n        var lineItemsArray = [\n            'name',\n            'kind',\n            'quantity',\n            'unitAmount',\n            'productCode',\n            'description'\n        ];\n\n        if (window.checkoutConfig.payment['braintree_paypal'].canSendLineItems) {\n            let giftWrappingItems = 0, giftWrappingOrder = 0, storeCredit = 0, giftCardAccount = 0,\n                giftWrappingPrintedCard = 0,\n                baseDiscountAmount = formatAmount(Math.abs(quote.totals()['base_discount_amount']).toString()),\n                baseTaxAmount = formatAmount(quote.totals()['base_tax_amount']);\n\n            $.each(quote.totals()['total_segments'], function (segmentsKey, segmentsItem) {\n                if (segmentsItem['code'] === 'customerbalance') {\n                    storeCredit = formatAmount(Math.abs(segmentsItem['value']).toString());\n                }\n                if (segmentsItem['code'] === 'giftcardaccount') {\n                    giftCardAccount = formatAmount(Math.abs(segmentsItem['value']).toString());\n                }\n                if (segmentsItem['code'] === 'giftwrapping') {\n                    let extensionAttributes = segmentsItem['extension_attributes'];\n\n                    giftWrappingOrder = extensionAttributes['gw_base_price'];\n                    giftWrappingItems = extensionAttributes['gw_items_base_price'];\n                    giftWrappingPrintedCard = extensionAttributes['gw_card_base_price'];\n                }\n            });\n\n            $.each(quote.getItems(), function (quoteItemKey, quoteItem) {\n                if (quoteItem.parent_item_id !== null || quoteItem.price === 0.0) {\n                    return true;\n                }\n\n                let floatQty = parseFloat(quoteItem.qty),\n                    itemName = replaceUnsupportedCharacters(quoteItem.name),\n                    itemSku = replaceUnsupportedCharacters(quoteItem.sku),\n                    hasQty = floatQty > Math.floor(floatQty) && floatQty < Math.ceil(floatQty),\n                    description = hasQty\n                        ? 'Item quantity is ' + floatQty.toFixed(2) + ' and per unit amount is '\n                            + parseFloat(quoteItem.price).toFixed(2)\n                        : '',\n                    itemUnitAmount = hasQty\n                        ? parseFloat(floatQty * parseFloat(quoteItem.price)) : parseFloat(quoteItem.price),\n                    itemQty = hasQty ? parseFloat('1') : floatQty,\n                    lineItemValues = [\n                        itemName,\n                        'debit',\n                        itemQty.toFixed(2),\n                        itemUnitAmount.toFixed(2),\n                        itemSku,\n                        description\n                    ],\n\n                    mappedLineItems = $.map(lineItemsArray, function (itemElement, itemIndex) {\n                        return [[\n                            lineItemsArray[itemIndex],\n                            lineItemValues[itemIndex]\n                        ]];\n                    });\n\n                lineItems[quoteItemKey] = Object.fromEntries(mappedLineItems);\n            });\n\n            /**\n             * Adds credit (refund or discount) kind as LineItems for the\n             * PayPal transaction if discount amount is greater than 0(Zero)\n             * as discountAmount lineItem field is not being used by PayPal.\n             *\n             * developer.paypal.com/braintree/docs/reference/response/transaction-line-item/php#discount_amount\n             */\n            if (baseDiscountAmount > 0) {\n                let discountLineItem = {\n                    'name': 'Discount',\n                    'kind': 'credit',\n                    'quantity': 1.00,\n                    'unitAmount': baseDiscountAmount\n                };\n\n                lineItems = $.merge(lineItems, [discountLineItem]);\n            }\n\n            /**\n             * Adds shipping as LineItems for the PayPal transaction\n             * if shipping amount is greater than 0(Zero) to manage\n             * the totals with client-side implementation as there is\n             * no any field exist in the client-side implementation\n             * to send the shipping amount to the Braintree.\n             */\n            if (quote.totals()['base_shipping_amount'] > 0) {\n                let shippingLineItem = {\n                    'name': 'Shipping',\n                    'kind': 'debit',\n                    'quantity': 1.00,\n                    'unitAmount': quote.totals()['base_shipping_amount']\n                };\n\n                lineItems = $.merge(lineItems, [shippingLineItem]);\n            }\n\n            if (baseTaxAmount > 0) {\n                let taxLineItem = {\n                    'name': 'Tax',\n                    'kind': 'debit',\n                    'quantity': 1.00,\n                    'unitAmount': baseTaxAmount\n                };\n\n                lineItems = $.merge(lineItems, [taxLineItem]);\n            }\n\n            /**\n             * Adds credit (Store Credit) kind as LineItems for the\n             * PayPal transaction if store credit is greater than 0(Zero)\n             * to manage the totals with client-side implementation\n             */\n            if (storeCredit > 0) {\n                let storeCreditItem = {\n                    'name': 'Store Credit',\n                    'kind': 'credit',\n                    'quantity': 1.00,\n                    'unitAmount': storeCredit\n                };\n\n                lineItems = $.merge(lineItems, [storeCreditItem]);\n            }\n\n            /**\n             * Adds Gift Wrapping for items as LineItems for the PayPal\n             * transaction if it is greater than 0(Zero) to manage\n             * the totals with client-side implementation\n             */\n            if (giftWrappingItems > 0) {\n                let gwItems = {\n                    'name': 'Gift Wrapping for Items',\n                    'kind': 'debit',\n                    'quantity': 1.00,\n                    'unitAmount': giftWrappingItems\n                };\n\n                lineItems = $.merge(lineItems, [gwItems]);\n            }\n\n            /**\n             * Adds Gift Wrapping for order as LineItems for the PayPal\n             * transaction if it is greater than 0(Zero) to manage\n             * the totals with client-side implementation\n             */\n            if (giftWrappingOrder > 0) {\n                let gwOrderItem = {\n                    'name': 'Gift Wrapping for Order',\n                    'kind': 'debit',\n                    'quantity': 1.00,\n                    'unitAmount': giftWrappingOrder\n                };\n\n                lineItems = $.merge(lineItems, [gwOrderItem]);\n            }\n\n            /**\n             * Adds Gift Wrapping Printed Card as LineItems for the PayPal\n             * transaction if it is greater than 0(Zero) to manage\n             * the totals with client-side implementation\n             */\n            if (giftWrappingPrintedCard > 0) {\n                let gwPrintedCard = {\n                    'name': 'Printed Card',\n                    'kind': 'debit',\n                    'quantity': 1.00,\n                    'unitAmount': giftWrappingPrintedCard\n                };\n\n                lineItems = $.merge(lineItems, [gwPrintedCard]);\n            }\n\n            /**\n             * Adds Gift Cards as credit LineItems for the PayPal\n             * transaction if it is greater than 0(Zero) to manage\n             * the totals with client-side implementation\n             */\n            if (giftCardAccount > 0) {\n                let giftCardItem = {\n                    'name': 'Gift Cards',\n                    'kind': 'credit',\n                    'quantity': 1.00,\n                    'unitAmount': giftCardAccount\n                };\n\n                lineItems = $.merge(lineItems, [giftCardItem]);\n            }\n\n            if (lineItems.length >= 250) {\n                lineItems = [];\n            }\n        }\n        return lineItems;\n    };\n});\n","PayPal_Braintree/js/lpm/process-fallback-response.js":"/**\n * Copyright \u00a9 Magento, Inc. All rights reserved.\n * See COPYING.txt for license details.\n */\n/*browser:true*/\ndefine([\n    'Magento_Checkout/js/view/payment/default',\n    'Magento_Customer/js/customer-data',\n    'Magento_Checkout/js/model/quote',\n    'jquery',\n    'braintree',\n    'braintreeLpm',\n    'PayPal_Braintree/js/model/full-screen-loader',\n    'mage/translate',\n    'underscore'\n], function (Component, customerData, quote, $, braintree, lpm, fullScreenLoader, $t, _) {\n    'use strict';\n\n    return Component.extend({\n        code: 'braintree_local_payment',\n        paymentMethodNonce: null,\n        config: {\n            clientToken: null,\n            merchantAccountId: null,\n            redirectOnFail: null\n        },\n\n        /**\n         * Initialize config values\n         *\n         * @param config\n         */\n        initialize: function (config) {\n            this._super();\n            this.config.clientToken = config.clientToken;\n            this.config.merchantAccountId = config.merchantAccountId;\n            this.config.redirectOnFail = config.redirectOnFail;\n            this.setupLpmFallback();\n        },\n\n        /**\n         * Setup local payment fallback scenario\n         */\n        setupLpmFallback: function () {\n            let self = this;\n\n            fullScreenLoader.startLoader();\n\n            braintree.create({\n                authorization: self.config.clientToken\n            }, function (clientError, clientInstance) {\n                if (clientError) {\n                    self.redirectCustomerOnFailure($t('Unable to initialize Braintree Client.'));\n                    return;\n                }\n\n                lpm.create({\n                    client: clientInstance,\n                    merchantAccountId: self.config.merchantAccountId\n                }, function (lpmError, lpmInstance) {\n                    if (lpmError) {\n                        self.redirectCustomerOnFailure($t(lpmError.message));\n                    }\n\n                    if (lpmInstance.hasTokenizationParams()) {\n                        lpmInstance.tokenize(function (tokenizeError, payload) {\n                            if (tokenizeError) {\n                                self.redirectCustomerOnFailure($t(tokenizeError.message));\n                            } else {\n                                // Send the nonce to the server to create a transaction\n                                self.setPaymentMethodNonce(payload.nonce);\n                                self.isPlaceOrderActionAllowed(true);\n\n                                if (!window.checkoutConfig.isCustomerLoggedIn) {\n                                    // Set the email to the quote.\n                                    let checkoutData = customerData.get('checkout-data')();\n\n                                    quote.guestEmail = checkoutData.inputFieldEmailValue;\n                                }\n\n                                // Check all agreements if any available.\n                                let agreements = $('.checkout-agreements input[type=\"checkbox\"]');\n\n                                if (agreements.length) {\n                                    agreements.prop('checked', true);\n                                }\n\n                                self.placeOrder();\n                            }\n                        });\n                    } else {\n                        let error = 'Payment can not be processed as invalid parameters received';\n\n                        self.redirectCustomerOnFailure($t(error));\n                    }\n                });\n            });\n        },\n\n        /**\n         * Get code\n         *\n         * @returns {string}\n         */\n        getCode: function () {\n            return this.code;\n        },\n\n        /**\n         * Set payment method nonce\n         *\n         * @param nonce\n         */\n        setPaymentMethodNonce: function (nonce) {\n            this.paymentMethodNonce = nonce;\n        },\n\n        /**\n         * Get data\n         *\n         * @returns {{additional_data: {payment_method_nonce: null}, method: string}}\n         */\n        getData: function () {\n            let data = {\n                'method': this.getCode(),\n                'additional_data': {\n                    'payment_method_nonce': this.paymentMethodNonce\n                }\n            };\n\n            data['additional_data'] = _.extend(data['additional_data'], this.additionalData);\n\n            return data;\n        },\n\n        /**\n         * redirect customer to the configured page if any error/failure/cancelled.\n         */\n        redirectCustomerOnFailure: function (message) {\n            if (message) {\n                let braintreeData = customerData.get('braintree')(),\n                    errors = braintreeData.errors || [];\n\n                errors.push(message);\n\n                customerData.set('braintree', { errors: errors });\n            }\n\n            window.location.href = this.config.redirectOnFail;\n        }\n    });\n});\n","PayPal_Braintree/js/checkoutAgreements/view/checkout-agreements-mixin.js":"/**\n * Copyright \u00a9 Magento, Inc. All rights reserved.\n * See COPYING.txt for license details.\n */\ndefine([\n    'underscore'\n], function (_) {\n    'use strict';\n\n    return function (CheckoutAgreements) {\n        return CheckoutAgreements.extend({\n            /**\n             * Replace checkboxes unique id with Braintree PayPal Vault unique id using the index.\n             * First call the original & extend in order to prevent unwanted behaviour.\n             *\n             * @param {Object} context - the ko context\n             * @param {Number} agreementId\n             */\n            getCheckboxId: function (context, agreementId) {\n                let result = this._super(context, agreementId),\n\n                    /* Fetch corresponding payment method from parent context */\n                    paymentMethodRenderer = context.$parents[1],\n                    paymentMethodName;\n\n                /* We only want to check for Braintree PayPal Vault methods with set properties     */\n                if (!paymentMethodRenderer ||\n                    _.get(paymentMethodRenderer, ['code'], null) !== 'braintree_paypal_vault' ||\n                    !_.has(paymentMethodRenderer, 'index')\n                ) {\n                    return result;\n                }\n\n                paymentMethodName = paymentMethodRenderer.index;\n\n                /* Now check that the relevant index `braintree_paypal_vault_X` has global variables set */\n                if (!this.hasVaultInCheckoutConfig(paymentMethodName)) {\n                    return result;\n                }\n\n                /* If yes, use unique name */\n                return 'agreement_' + paymentMethodName + '_' + agreementId;\n            },\n\n            /**\n             * Check whether the current method renderer index has configuration in the checkout global.\n             *\n             * @param {String} vaultIndex\n             * @return {Boolean}\n             */\n            hasVaultInCheckoutConfig: function (vaultIndex) {\n                return _.has(window.checkoutConfig.payment, ['vault', vaultIndex]);\n            }\n        });\n    };\n});\n","PayPal_Braintree/js/customer/utilities.js":"/* eslint-disable max-depth */\ndefine([\n    'jquery',\n    'ko',\n    'mage/url',\n    'mage/translate',\n    'mage/calendar'\n], function ($, ko, urlBuilder) {\n    'use strict';\n    return {\n\n        viewModel: {\n            activeVM: ko.observableArray(null),\n            pausedVM: ko.observableArray(null),\n            pendingVM: ko.observableArray(null),\n\n            updatedOrderEntityId: ko.observable(null),\n            showBanner: ko.observable(false),\n            errorModal: {\n                visible: ko.observable(false),\n                message: ko.observable(null)\n            }\n        },\n        sectionCounter: 0,\n\n        makeCall: function (url, verb, callback, viewModel) {\n            var self = this;\n\n            $.ajax({\n                url: urlBuilder.build(url),\n                contentType: 'application/json',\n                global: true,\n                type: verb,\n                showLoader: true,\n                cache: false,\n                success: function (response) {\n                    callback(response);\n                    self.handleSuccess(self.viewModel.updatedOrderEntityId());\n                },\n                error: function (xhr, status, error) {\n                    $('body').trigger('processStop');\n                    if (viewModel) {\n                        self.hideModal(viewModel);\n                    }\n\n                    self.handleError(xhr, status, error);\n                }\n            });\n        },\n\n        //Get entity ID from response json back from update\n        //After section updates, run this to find the updatedOrderEntityId value and add the class\n        //Find a div with that ID and add a class to it\n        handleSuccess: function (entity_id) {\n            var self = this,\n                successClass = 'updated-success',\n                orderItem = $('.repeat-order-id-' + entity_id),\n                parentContainer = orderItem.closest('.repeat-order');\n\n            // If there is another success message on an item then reset\n            if ($('.updated-success').length) {\n                $(this).removeClass(successClass);\n            }\n\n            orderItem.addClass(successClass);\n            parentContainer.addClass(successClass);\n\n            //Remove the class\n            //Set the entityid value back to null, so the success message is only shown once\n            setTimeout(function () {\n                orderItem.removeClass(successClass);\n                parentContainer.removeClass(successClass);\n                self.viewModel.updatedOrderEntityId(null);\n            }, 20000);\n        },\n\n        hideModal: function (viewModel) {\n            return viewModel.visible(false);\n        },\n\n        //Get a message relating to a particular response and show it on the page in a modal\n        handleError: function (xhr) {\n            this.viewModel.errorModal.message(JSON.parse(xhr.responseText).message);\n            this.viewModel.errorModal.visible(true);\n        },\n\n        formatDate: function (value, format) {\n            if (!format || typeof format == 'undefined') {\n                format = 'MM dd, yy';\n            }\n\n            return $.datepicker.formatDate(format, new Date(value));\n        },\n\n        formatCurrency: function (value) {\n            //If the price is a negative number, make it a positive number. eg -1.25 becomes 1.25\n            var formattedValue = Math.abs(value);\n\n            //Set number to 2 decimal places as it is a price\n            formattedValue = formattedValue.toFixed(2);\n\n            return formattedValue;\n        },\n\n        formatWeeks: function (value) {\n            var dayValue = value / 7;\n\n            return dayValue === 1 ? $.mage.__('Week') : dayValue + ' ' + $.mage.__('Weeks');\n        },\n\n        //Used for payment details as they are formatted as a string of json:\n        //eg '{\"type\":\"VI\",\"maskedCC\":\"1111\",\"expirationDate\":\"11\\/2022\"}'\n        parseStringtoJSON: function (string) {\n            var result = JSON.parse(string);\n\n            return result;\n        },\n\n        //Find the image url in the product.media_gallery_entries array\n        getImgUrl: function (data) {\n            var imgUrl,\n                i = 0,\n                j = 0,\n                dataLength = data.length;\n\n            for (i = 0; i < dataLength; i++) {\n\n                for (j = 0; j < data[i].types.length; j++) {\n                    if (data[i].types[j] === 'thumbnail') {\n                        imgUrl = data[i].file;\n\n                        break;\n                    }\n                }\n            }\n\n            return '/media/catalog/product' + imgUrl;\n        },\n\n        //Find the image label to be used as an alt tag in the product.media_gallery_entries array\n        getImgAltTag: function (data) {\n            var altTag,\n                i = 0,\n                j = 0,\n                dataLength = data.length;\n\n            for (i = 0; i < dataLength; i++) {\n\n                for (j = 0; j < data[i].types.length; j++) {\n                    altTag = this.updateAltTag(data[i].types[j]);\n\n                    if (data[i].types[j] === 'thumbnail') {\n\n                        if (data[i].label === null || data[i].label === '') {\n                            altTag = ' ';\n                        }\n                        else {\n                            altTag = data[i].label;\n                        }\n\n                        break;\n                    }\n                }\n            }\n\n            return altTag;\n        }\n    };\n});\n","PayPal_Braintree/js/customer/modals/address-modal.js":"define([\n    'jquery',\n    'ko',\n    'PayPal_Braintree/js/customer/utilities',\n    'mageUtils'\n], function ($, ko, utilities, utils) {\n    'use strict';\n\n    return {\n        viewModel: {\n            visible: ko.observable(false),\n            newAddressFormVisible: ko.observable(false),\n            selectExistingVisible: ko.observable(false),\n            currentAddresses: ko.observableArray([]),\n            initialSubscriptionAddressId: ko.observable(null),\n            currentShippingId: ko.observable(null),\n            currentEntityId: ko.observable(null),\n            currentOrderIsGrouped: ko.observable(false),\n            useForSelected: ko.observable(false),\n            saveAddressDisabled: ko.observable(true),\n            confirmationVisibleType: ko.observable(null),\n            defaultForAllAddressId: ko.observable(null),\n            isLookup: ko.observable(true),\n            newAddress: {\n                firstName: document.getElementById('firstname').value,\n                lastName: document.getElementById('lastname').value,\n                street: document.getElementById('street_1').value,\n                street2: document.getElementById('street_2').value,\n                city: document.getElementById('city').value,\n                postcode: document.getElementById('zip').value,\n                country: document.getElementById('country').value,\n                telephone: document.getElementById('telephone').value,\n                region: document.getElementById('region_id').value\n            },\n            currentCountryId: ko.observable(null),\n            countries: ko.observableArray(null)\n        },\n\n        fetchAllAddressUrl: 'rest/V1/repeat-orders/user-addresses',\n        assignAddressUrl: 'rest/V1/repeat-orders/grouped/set-shipping-address/',\n        useForAllUrl: 'rest/V1/repeat-orders/set-shipping-address-for-all/',\n        addAddressUrl: 'rest/V1/repeat-orders/add-shipping-address/',\n        validatedPostCodeExample: [],\n\n        showAddressModal: function (entity_id, groupedOrdersLength, shippingId, countryId) {\n            var self = this;\n\n            this.viewModel.visible(true);\n            this.viewModel.selectExistingVisible(true);\n            this.viewModel.currentEntityId(entity_id);\n            this.viewModel.initialSubscriptionAddressId(shippingId);\n            this.viewModel.currentOrderIsGrouped(groupedOrdersLength > 1);\n            this.viewModel.useForSelected(false);\n            this.clearAddressField();\n\n            fetch('/graphql', {\n                method: 'POST',\n                headers: {\n                    'Content-Type': 'application/json'\n                },\n                body: JSON.stringify({\n                    query: `{\n                customer {\n                    addresses {\n                        id,\n                        street,\n                        country_id,\n                        region {\n                            region_code\n                        },\n                        telephone,\n                        postcode,\n                        firstname,\n                        lastname,\n                        city\n                    }\n                }\n              }`\n                })\n            }).then(response => response.json()).then(response => {\n                const addresses = response.data.customer?.addresses || [];\n\n                self.viewModel.currentAddresses.removeAll();\n\n                //Get addresses from response and put them in an observable array\n                //The template looks at the array and builds the <select> dropdown form\n                for (let i = 0; i < addresses.length; i++) {\n                    const address = {\n                        id: addresses[i].id,\n                        firstname: addresses[i].firstname,\n                        lastname: addresses[i].lastname,\n                        region: {\n                            region_code: addresses[i].region.region_code\n                        },\n                        telephone: addresses[i].telephone,\n                        postcode: addresses[i].postcode,\n                        country_id: addresses[i].country_id,\n                        city: addresses[i].city,\n                        street: addresses[i].street.join(', ')\n                    };\n\n                    self.viewModel.currentAddresses.push(address);\n                }\n\n                self.viewModel.currentShippingId(shippingId);\n                self.viewModel.currentCountryId(countryId);\n                self.viewModel.saveAddressDisabled(true);\n            });\n        },\n\n        hideAddressModal: function () {\n            this.viewModel.newAddressFormVisible(false);\n            this.viewModel.selectExistingVisible(false);\n            this.viewModel.confirmationVisibleType(null);\n            this.viewModel.visible(false);\n\n            // Remove previous clickToAddress initialization block\n            $('#cc_c2a').remove();\n        },\n\n        showConfirmChangeAddress: function (event, context, type) {\n            if (type === 'new') {\n                let form = $(event.target).closest('form');\n\n                if (!(form.validation() && form.validation('isValid'))) {\n                    return false;\n                }\n            }\n\n            this.viewModel.newAddressFormVisible(false);\n            this.viewModel.selectExistingVisible(false);\n            this.viewModel.confirmationVisibleType(type);\n        },\n\n        /**\n     * @param {*} postCode\n     * @param {*} countryId\n     * @return {Boolean}\n     */\n        validatePostCode: function (postCode, countryId) {\n            var pattern, regex,\n                patterns = window.checkout.postCodes[countryId];\n\n            this.validatedPostCodeExample = [];\n\n            if (!utils.isEmpty(postCode) && !utils.isEmpty(patterns)) {\n                for (pattern in patterns) {\n                    if (patterns.hasOwnProperty(pattern)) { //eslint-disable-line max-depth\n                        this.validatedPostCodeExample.push(patterns[pattern].example);\n                        regex = new RegExp(patterns[pattern].pattern);\n\n                        if (regex.test(postCode)) { //eslint-disable-line max-depth\n                            return true;\n                        }\n                    }\n                }\n\n                return false;\n            }\n\n            return true;\n        },\n\n        postcodeValidation: function (postcodeElement) {\n            var countryId = $('select[name=\"country\"]:visible').val(),\n                validationResult,\n                warnMessage,\n                warnElement = $('.warning-postcode');\n\n            if (postcodeElement == null || postcodeElement.val() == null) {\n                return true;\n            }\n\n            warnElement.hide();\n            warnElement.text('');\n\n            validationResult = this.validatePostCode(postcodeElement.val(), countryId, []);\n\n            if (!validationResult) {\n                warnMessage = 'Please enter a valid post code.';\n                warnElement.show();\n                warnElement.text(warnMessage);\n\n                if (warnMessage) {\n                    warnElement.prev().addClass('input-postcode-error');\n                }\n\n            } else {\n                warnElement.prev().removeClass('input-postcode-error');\n            }\n\n            return validationResult;\n        },\n\n        toggleNewAddAddressForm: function (show) {\n            this.viewModel.newAddressFormVisible(show);\n            this.viewModel.selectExistingVisible(!show);\n            this.viewModel.isLookup(show);\n            this.clearAddressField();\n        },\n\n        clearAddressField: function () {\n            $('#cc_c2a').remove();\n            this.viewModel.currentShippingId(null);\n            this.viewModel.newAddress.street = null;\n            this.viewModel.newAddress.street = null;\n            this.viewModel.newAddress.street2 = null;\n            this.viewModel.newAddress.city = null;\n            this.viewModel.newAddress.postcode = null;\n            this.viewModel.newAddress.telephone = null;\n            this.viewModel.newAddress.country = this.viewModel.currentCountryId();\n        },\n\n        updateCurrentAddressId: function () {\n            var current = this.viewModel.currentShippingId(),\n                initial = this.viewModel.initialSubscriptionAddressId();\n\n            this.viewModel.saveAddressDisabled(current === initial);\n            this.viewModel.useForSelected(false);\n        },\n\n        onUseForAllChange: function (type, event) {\n            if (event && event.target) {\n                this.viewModel.useForSelected(event.target.checked);\n            }\n\n            if (type === 'existing') {\n                let currentId = this.viewModel.currentShippingId(),\n                    initialId = this.viewModel.initialSubscriptionAddressId(),\n                    defaultForAll = this.viewModel.defaultForAllAddressId();\n\n                if (currentId === initialId && defaultForAll === currentId && this.viewModel.useForSelected()) {\n                    this.viewModel.saveAddressDisabled(!this.viewModel.saveAddressDisabled());\n                }\n            }\n\n            return true;\n        },\n\n        submitChanges: function (event) {\n            if (this.viewModel.confirmationVisibleType() === 'new') {\n                return this.submitNewAddress(event);\n            }\n\n            return this.submitExistingAddress();\n        },\n\n        submitExistingAddress: function () {\n            var self = this,\n                entityId = this.viewModel.currentEntityId(),\n                addressId = this.viewModel.currentShippingId(),\n                useForAll = this.viewModel.useForSelected(),\n                url = (useForAll ? this.useForAllUrl : this.assignAddressUrl + entityId + '/') + addressId,\n                verb = useForAll ? 'POST' : 'PUT';\n\n            utilities.makeCall(url, verb, function () {\n                self.hideAddressModal();\n                utilities.viewModel.updatedOrderEntityId(entityId);\n            }, self.viewModel);\n\n            return true;\n        },\n\n        submitNewAddress: function () {\n            var self = this,\n                entityId = this.viewModel.currentEntityId,\n                firstName = this.viewModel.newAddress.firstName,\n                lastName = this.viewModel.newAddress.lastName,\n                street = this.viewModel.newAddress.street,\n                city = this.viewModel.newAddress.city,\n                postcode = this.viewModel.newAddress.postcode,\n                country = this.viewModel.currentCountryId,\n                telephone = this.viewModel.newAddress.telephone,\n                url = this.addAddressUrl +\n          '?entityId=' + entityId +\n          '&firstName=' + firstName +\n          '&lastName=' + lastName +\n          '&street=' + street +\n          '&postcode=' + postcode +\n          '&city=' + city +\n          '&countryId=' + country +\n          '&telephone=' + telephone;\n\n            utilities.makeCall(\n                url,\n                'POST',\n                function (response) {\n                    self.viewModel.currentShippingId(response.id);\n                    self.submitExistingAddress();\n                }, self.viewModel);\n\n            return true;\n        }\n    };\n});\n","PayPal_Braintree/js/customer/payment/address-form-initializer.js":"define([\n    'jquery',\n    'uiComponent',\n    'ko',\n    'PayPal_Braintree/js/customer/modals/address-modal',\n    'mageUtils',\n    'Magento_Checkout/js/model/payment/additional-validators'\n], function (\n    $,\n    Component,\n    ko,\n    addressModal,\n    utils,\n    additionalValidators\n) {\n    'use strict';\n    return Component.extend({\n\n        defaults: {\n            template: 'Paypal_Braintree/customer/payment/address-wrapper',\n            addressModal: addressModal,\n            deliveryIntervals: ko.observableArray(null),\n            currentlySelectedInterval: ko.observable(null),\n            minDatePickerValue: 1,\n            standardDeliveryDays: 1,\n            baseUrl: ko.observable(),\n            updatedOrderEntityId: null,\n            countryId: 'GB',\n            submitBtnSelector: '#braintree_submit',\n            phoneNumberMaxLength: ko.observable(11),\n            phoneNumberMinLength: ko.observable(2),\n            phoneNumberMaxLengthErrorVisible: ko.observable(false),\n            phoneNumberMinLengthErrorVisible: ko.observable(false)\n        },\n\n        initialize: function () {\n            this._super();\n            let self = this;\n\n            additionalValidators.registerValidator({\n                validate: function () {\n                    const $form = $('#form-validate');\n\n                    $form.validation();\n                    return $form.validation('isValid');\n                }\n            });\n\n            fetch('/graphql', {\n                method: 'POST',\n                headers: {\n                    'Content-Type': 'application/json'\n                },\n                body: JSON.stringify({\n                    query: `{\n                        countries {\n                            full_name_locale,\n                            two_letter_abbreviation\n                        }\n                    }`\n                })\n            }).then(response => response.json()).then(response => {\n                const countries = response.data.countries || [];\n\n                countries.forEach(country => {\n                    self.addressModal.viewModel.countries.push({\n                        countryCode: country.two_letter_abbreviation,\n                        countryName: country.full_name_locale\n                    });\n                });\n            });\n        },\n\n        toggleSubmit: function (disable) {\n            var submitBtn = $(this.submitBtnSelector);\n\n            if (submitBtn.length) {\n                submitBtn.attr('disabled', disable);\n            }\n        },\n\n        showAddressModal: function (entity_id, groupedOrdersLength, shippingId, countryId) {\n            this.addressModal.viewModel.selectExistingVisible(true);\n            this.addressModal.viewModel.currentCountryId(this.countryId);\n            this.addressModal.showAddressModal(entity_id, groupedOrdersLength, shippingId, countryId);\n            let addressLength = this.addressModal.viewModel.currentAddresses().length;\n\n            this.addressModal.viewModel.newAddressFormVisible(addressLength === 0);\n            this.showLookupForm();\n            this.toggleSubmit(true);\n        },\n\n        showNewAddressForm: function () {\n            this.addressModal.toggleNewAddAddressForm(true);\n            if (this.addressModal.toggleNewAddAddressForm) {\n                document.getElementById('form-validate').style.display = 'block';\n            }\n            this.addressModal.viewModel.isLookup(false);\n\n            this.toggleSubmit(false);\n        },\n\n        showLookupForm: function () {\n            this.addressModal.toggleNewAddAddressForm(true);\n        },\n\n        showExistingSelector: function () {\n            this.addressModal.toggleNewAddAddressForm(false);\n            if (this.addressModal.toggleNewAddAddressForm) {\n                document.getElementById('form-validate').style.display = 'none';\n            }\n\n            this.toggleSubmit(false);\n        },\n\n        /**\n         * @param {*} postCode\n         * @param {*} countryId\n         * @param {Array} postCodesPatterns\n         * @return {Boolean}\n         */\n        validatePostCode: function (postCode, countryId) {\n            var pattern, regex,\n                patterns = window.checkout.postCodes[countryId];\n\n            this.validatedPostCodeExample = [];\n\n            if (!utils.isEmpty(postCode) && !utils.isEmpty(patterns)) {\n                for (pattern in patterns) {\n                    if (patterns.hasOwnProperty(pattern)) { //eslint-disable-line max-depth\n                        this.validatedPostCodeExample.push(patterns[pattern].example);\n                        regex = new RegExp(patterns[pattern].pattern);\n\n                        if (regex.test(postCode)) { //eslint-disable-line max-depth\n                            return true;\n                        }\n                    }\n                }\n\n                return false;\n            }\n\n            return true;\n        },\n\n        postcodeValidation: function (postcodeElement) {\n            var countryId = this.countryId,\n                validationResult,\n                warnMessage,\n                warnElement = $('.warning-postcode');\n\n            if (postcodeElement == null || postcodeElement.val() == null) {\n                return true;\n            }\n\n            warnElement.hide();\n            warnElement.text('');\n\n            validationResult = this.validatePostCode(postcodeElement.val(), countryId, []);\n\n            if (!validationResult) {\n                warnMessage = 'Please enter a valid post code.';\n\n                warnElement.show();\n                warnElement.text(warnMessage);\n\n                if (warnMessage) {\n                    warnElement.prev().addClass('input-postcode-error');\n                }\n            } else {\n                warnElement.prev().removeClass('input-postcode-error');\n            }\n\n            return validationResult;\n        }\n    });\n});\n","PayPal_Braintree/js/customer/payment/update-payment.js":"define([\n    'uiComponent',\n    'jquery',\n    'ko',\n    'uiRegistry'\n], function (Component, $, ko, registry) {\n    'use strict';\n    return Component.extend({\n        defaults: {\n            addNewCardVM: {\n                visible: ko.observable(false)\n            },\n            addNewPayPalVM: {\n                visible: ko.observable(false)\n            },\n            errorModalVM: {\n                visible: ko.observable(false),\n                message: ko.observable(null),\n                header: ko.observable('Error')\n            }\n        },\n\n        /**\n         * Add the repeat order block to the frontend\n         */\n        initialize: function () {\n            this.modifyKnockoutRemovalBehaviour();\n\n            this._super();\n        },\n\n        /**\n         * By moving the billing address form inside of Knockout it\n         * conflicts with the mage.directoryRegionUpdater widget.\n         *\n         * Knockout will run a cleanData method that removes jQuery events so removes the region updater events\n         * so User's will no longer see the correct region fields.\n         */\n        modifyKnockoutRemovalBehaviour: function () {\n            const normalFunction = ko.utils.domNodeDisposal.cleanExternalData;\n\n            ko.utils.domNodeDisposal.cleanExternalData = function (node) {\n                if (node.id === 'country') {\n                    return;\n                }\n\n                normalFunction(node);\n            };\n        },\n\n        showAddCardModal: function () {\n            this.addNewCardVM.visible(true);\n\n            $('html, body').animate({scrollTop: 0}, 400);\n        },\n\n        hideAddCardModal: function () {\n            this.addNewCardVM.visible(false);\n        },\n\n        showAddPayPalModal: function () {\n            var braintreePaypal = registry.get('new-form-braintree-paypal');\n\n            braintreePaypal.setup();\n            this.addNewPayPalVM.visible(true);\n        },\n\n        hideAddPayPalModal: function () {\n            var braintreePaypal = registry.get('new-form-braintree-paypal');\n\n            braintreePaypal.teardownPayPalInstance();\n            this.addNewPayPalVM.visible(false);\n        }\n    });\n});\n","PayPal_Braintree/js/customer/payment/braintree-card.js":"define([\n    'uiComponent',\n    'jquery',\n    'ko',\n    'underscore',\n    'mage/translate',\n    'uiRegistry',\n    'braintreeThreeDSecure',\n    'Magento_Checkout/js/model/payment/additional-validators',\n    'PayPal_Braintree/js/helper/get-braintree-config',\n    'PayPal_Braintree/js/view/payment/adapter'\n], function (Component, $, ko, _,  $t, uiRegistry, threeDSecure, additionalValidators, getBraintreeConfig, braintree) {\n    'use strict';\n\n    /**\n     * braintree is not an instance of Component so we need to merge in our changes\n     * and return an instance of Component with the final merged object.\n     */\n    var uiC = _.extend(braintree, {\n        clientToken: null,\n        uiConfig: null,\n        paymentMethodNonce: null,\n        selectedCardType: null,\n\n        isValidCardNumber: false,\n        isValidExpirationDate: false,\n        isValidCvvNumber: false,\n\n        viewModel: {\n            paymentMethodNonce: ko.observable(null),\n            publicHash: ko.observable(null),\n            paymentMethodCode: 'braintree',\n            total: ko.observable(0),\n            isThreeDSecureEnabled: ko.observable(false),\n            selectedMethod: {\n                price: ko.observable(0)\n            },\n            errorMessage: ko.observable()\n        },\n\n        /**\n         * Additional payment data\n         *\n         * {Object}\n         */\n        additionalData: {},\n\n        /**\n         * @inheritDoc\n         */\n        initialize: async function (uiConfig) {\n            this._super().observe([\n                'selectedCardType'\n            ]);\n\n            await this.getBraintreeConfig();\n\n            this.uiConfig = uiConfig;\n            this.icons = uiConfig.icons;\n            this.cvvImage = uiConfig.cvvImage;\n            this.viewModel.isThreeDSecureEnabled(uiConfig.isThreeDSecureEnabled);\n            this.viewModel.total(parseFloat(uiConfig.amount).toFixed(2));\n\n            let self = this;\n\n            const elm = await this._waitForElm('#co-transparent-form-braintree');\n\n            if (elm) {\n                this.clientConfig = {\n                    additionalData: {},\n\n                    /**\n                     * Device data initialization\n                     * @param {String} deviceData\n                     */\n                    onDeviceDataReceived: function (deviceData) {\n                        this.additionalData['device_data'] = deviceData;\n                    },\n\n                    /**\n                     * Triggers on any Braintree error\n                     * @param {Object} response\n                     */\n                    onError: function (response) {\n                        self.showError($t('Please enter a valid card number, expiry date and CVV Number.'));\n                        throw response.message;\n                    },\n\n                    /**\n                     * Triggers when customer click \"Cancel\"\n                     */\n                    onCancelled: function () {\n                        self.showError($t('The process has been cancelled'));\n                    },\n\n                    onReady: function (context) {\n                        context.setupHostedFields();\n                    },\n\n                    /**\n                     * Allow a new nonce to be generated\n                     */\n                    onPaymentMethodError: function () {\n                        this.isProcessing = false;\n                    },\n\n                    /**\n                     * Set payment nonce\n                     * @param {String} paymentMethodNonce\n                     */\n                    setPaymentMethodNonce: function (paymentMethodNonce) {\n                        this.paymentMethodNonce = paymentMethodNonce;\n                    },\n\n\n                    /**\n                     * After Braintree instance initialization\n                     */\n                    onInstanceReady: function (instance) {\n                        instance.on('validityChange', self.onValidityChange.bind(self));\n                        instance.on('cardTypeChange', self.onCardTypeChange.bind(self));\n                    },\n\n                    id: 'co-transparent-form-braintree',\n\n                    hostedFields: {\n                        number: {\n                            selector: '#braintree_cc_number',\n                            placeholder: '4111 1111 1111 1111'\n                        },\n                        expirationDate: {\n                            selector: '#braintree_expirationDate',\n                            placeholder: $t('MM/YYYY')\n                        },\n                        cvv: {\n                            selector: '#braintree_cc_cid',\n                            placeholder: $t('000')\n                        }\n                    },\n\n                    styles: {\n                        'input': {\n                            'font-size': '14px',\n                            'color': '#3A3A3A'\n                        },\n                        ':focus': {\n                            'color': 'black'\n                        },\n                        '.valid': {\n                            'color': 'green'\n                        },\n                        '.invalid': {\n                            'color': 'red'\n                        }\n                    },\n\n                    onPaymentMethodReceived: function (response) {\n                        $.ajax({\n                            url: '/rest/default/V1/braintree/mine/payment/vault',\n                            type: 'POST',\n                            data: JSON.stringify({\n                                billingAddress: {},\n                                payment: {\n                                    payment_method_code: self.viewModel.paymentMethodCode,\n                                    payment_method_nonce: response.nonce,\n                                    device_data: this.additionalData.device_data\n                                }\n                            }),\n                            contentType:'application/json; charset=utf-8',\n                            success: function () {\n                                window.location.reload();\n                            },\n                            error: function (error) {\n                                $('body').trigger('processStop');\n                                console.warn(error.message);\n                            }\n                        });\n                    }\n                };\n\n                this.setConfig(this.clientConfig);\n                this.clientToken = uiConfig.clientToken;\n                this.setup();\n            }\n        },\n\n        /**\n         * Get list of card types\n         * @returns {Object}\n         */\n        getCcTypesMapper: function () {\n            return this.uiConfig.ccTypeMapper;\n        },\n\n        /**\n         * Find mage card type by Braintree type\n         * @param {String} type\n         * @param {Object} availableTypes\n         * @returns {*}\n         */\n        getMageCardType: function (type, availableTypes) {\n            var storedCardType = null,\n                mapper = this.getCcTypesMapper();\n\n            if (type && typeof mapper[type] !== 'undefined') {\n                storedCardType = mapper[type];\n\n                if (_.indexOf(availableTypes, storedCardType) !== -1) {\n                    return storedCardType;\n                }\n            }\n\n            return null;\n        },\n\n        getBraintreeConfig: function () {\n            return getBraintreeConfig()\n                .then(response => {\n                    this.merchantAccountId = response.data.storeConfig.braintree_merchant_account_id;\n                });\n        },\n\n        /**\n         * Triggers on Hosted Field changes\n         * @param {Object} event\n         * @returns {Boolean}\n         */\n        onValidityChange: function (event) {\n            // Handle a change in validation or card type\n            if (event.emittedBy === 'number') {\n                this.selectedCardType(null);\n\n                if (event.cards.length === 1) {\n                    this.isValidCardNumber = event.fields.number.isValid;\n                    this.selectedCardType(\n                        this.getMageCardType(event.cards[0].type, this.uiConfig.availableCardTypes));\n                    this.validateCardType();\n                } else {\n                    this.isValidCardNumber = event.fields.number.isValid;\n                    this.validateCardType();\n                }\n            }\n\n            // Other field validations\n            if (event.emittedBy === 'expirationDate') {\n                this.isValidExpirationDate = event.fields.expirationDate.isValid;\n            }\n            if (event.emittedBy === 'cvv') {\n                this.isValidCvvNumber = event.fields.cvv.isValid;\n            }\n        },\n\n        /**\n         * Triggers on Hosted Field card type changes\n         * @param {Object} event\n         * @returns {Boolean}\n         */\n        onCardTypeChange: function (event) {\n            if (event.cards.length === 1) {\n                this.selectedCardType(\n                    this.getMageCardType(event.cards[0].type, this.uiConfig.availableCardTypes)\n                );\n            } else {\n                this.selectedCardType(null);\n            }\n        },\n\n        _waitForElm: function (selector) {\n            return new Promise(resolve => {\n                if (document.querySelector(selector)) {\n                    return resolve(document.querySelector(selector));\n                }\n\n                const observer = new MutationObserver(() => {\n                    if (document.querySelector(selector)) {\n                        resolve(document.querySelector(selector));\n                        observer.disconnect();\n                    }\n                });\n\n                observer.observe(document.body, {\n                    childList: true,\n                    subtree: true\n                });\n            });\n        },\n\n        /**\n         * @inheritDoc\n         */\n        getClientToken: function () {\n            return this.clientToken;\n        },\n\n        /**\n         * Trigger order placing\n         */\n        placeOrderClick: function () {\n            if (this.validateFormFields() && additionalValidators.validate()) {\n                this.handleNonce();\n            }\n        },\n\n        /**\n         * Get jQuery selector\n         * @param {String} field\n         * @returns {String}\n         */\n        getSelector: function (field) {\n            return '#' + this.code + '_' + field;\n        },\n\n        /**\n         * Get card icons\n         *\n         * @param {String} type\n         * @returns {Object|Boolean}\n         */\n        getIcons: function (findType) {\n            return this.icons.find(({ type }) => type === findType);\n        },\n\n        /**\n         * Toggle invalid class on selector\n         * @param selector\n         * @param state\n         * @returns {boolean}\n         */\n        validateField: function (selector, state) {\n            var $selector = $(this.getSelector(selector)),\n                invalidClass = 'braintree-hosted-fields-invalid';\n\n            if (state === true) {\n                $selector.removeClass(invalidClass);\n                return true;\n            }\n\n            $selector.addClass(invalidClass);\n            return false;\n        },\n\n        /**\n         * Validate all fields\n         * @returns {boolean}\n         */\n        validateFormFields: function () {\n            return (this.validateCardType() && this.validateExpirationDate() && this.validateCvvNumber()) === true;\n        },\n\n        /**\n         * Validate current credit card type\n         * @returns {Boolean}\n         */\n        validateCardType: function () {\n            return this.validateField(\n                'cc_number',\n                this.isValidCardNumber\n            );\n        },\n\n        /**\n         * Validate current expiry date\n         * @returns {boolean}\n         */\n        validateExpirationDate: function () {\n            return this.validateField(\n                'expirationDate',\n                this.isValidExpirationDate === true\n            );\n        },\n\n        /**\n         * Validate current CVV field\n         * @returns {boolean}\n         */\n        validateCvvNumber: function () {\n            return this.validateField(\n                'cc_cid',\n                this.isValidCvvNumber === true\n            );\n        },\n\n        /**\n         * Get image for CVV\n         * @returns {String}\n         */\n        getCvvImageHtml: function () {\n            return '<img src=\"' + this.cvvImage +\n                '\" alt=\"' + $t('Card Verification Number Visual Reference') +\n                '\" title=\"' + $t('Card Verification Number Visual Reference') +\n                '\" />';\n        },\n\n        /**\n         * Prepare data to place order\n         */\n        handleNonce: function () {\n\n            $('body').trigger('processStart');\n            this.viewModel.errorMessage('');\n\n            let state = $.Deferred(),\n                addressBilling = uiRegistry.get('store-braintree-card-form.address'),\n                shippingId = addressBilling.addressModal.viewModel.currentShippingId(),\n\n                // If we have a shipping ID then get the selected address otherwise use the new address.\n                currentAddress = shippingId\n                    ? addressBilling.addressModal.viewModel.currentAddresses().find(function (address) {\n                        return address.id === shippingId;\n                    }) : {\n                        firstname: document.getElementById('firstname').value,\n                        lastname: document.getElementById('lastname').value,\n                        telephone: document.getElementById('telephone').value,\n                        street: [\n                            document.getElementById('street_1').value,\n                            document.getElementById('street_2').value\n                        ],\n                        city: document.getElementById('city').value,\n                        region: {\n                            region_code: document.getElementById('region_id').value\n                        },\n                        postcode: document.getElementById('zip').value,\n                        country_id: document.getElementById('country').value\n                    };\n\n            const billingAddress = {\n                givenName: currentAddress.firstname,\n                surname: currentAddress.lastname,\n                phoneNumber: currentAddress.telephone,\n                streetAddress: currentAddress.street[0],\n                extendedAddress: currentAddress.street[1],\n                locality: currentAddress.city,\n                region: currentAddress.region.region_code,\n                postalCode: currentAddress.postcode,\n                countryCodeAlpha2: currentAddress.country_id\n            };\n\n            this.hostedFieldsInstance\n                .tokenize({\n                    vault: true,\n                    billingAddress\n                }).then(function (payload) {\n                    this.viewModel.paymentMethodNonce(payload.nonce);\n                    let threeDSEnabled = this.viewModel.isThreeDSecureEnabled();\n\n                    const callback = () => {\n                        const nonce = this.viewModel.paymentMethodNonce();\n\n                        this.clientConfig.onPaymentMethodReceived({ nonce });\n                    };\n\n                    if (threeDSEnabled) {\n                        threeDSecure.create({\n                            version: 2,\n                            client: this.clientInstance\n                        }, function (threeDSecureErr, threeDSecureInstance) {\n                            if (threeDSecureErr) {\n                                console.warn(threeDSecureErr);\n                                return;\n                            }\n\n                            threeDSecureInstance.verifyCard({\n                                amount: this.viewModel.total(),\n                                nonce: payload.nonce,\n                                bin: payload.details.bin,\n                                cardAddChallengeRequested: true,\n                                vault: true,\n\n                                onLookupComplete: function (data, next) {\n                                    next();\n                                }\n                            }, function (err, response) {\n                                if (err) {\n                                    $('body').trigger('processStop');\n                                    this.viewModel.errorMessage($t('Please try again with another form of payment.'));\n                                    return state.reject($t('Please try again with another form of payment.'));\n                                }\n\n                                let liability = {\n                                    shifted: response.liabilityShifted,\n                                    shiftPossible: response.liabilityShiftPossible\n                                };\n\n                                if (liability.shifted || !liability.shifted && !liability.shiftPossible) {\n                                    this.viewModel.paymentMethodNonce(response.nonce);\n                                    state.resolve();\n\n                                    // Validation Passed\n                                    callback();\n\n                                } else {\n                                    // eslint-disable-next-line max-len\n                                    this.viewModel.errorMessage($t('We could not validate your payment method. Please try again with another form of payment.'));\n                                    $('body').trigger('processStop');\n                                    state.reject($t('Please try again with another form of payment.'));\n                                }\n                            }.bind(this));\n                        }.bind(this));\n                    } else {\n                        callback();\n                    }\n                }.bind(this))\n                .catch(function () {\n                    $('body').trigger('processStop');\n                });\n        }\n    });\n\n    return Component.extend(uiC);\n});\n","PayPal_Braintree/js/customer/payment/braintree-paypal.js":"define([\n    'uiComponent',\n    'jquery',\n    'ko',\n    'underscore',\n    'PayPal_Braintree/js/view/payment/adapter',\n    'braintreePayPalCheckout',\n    'mage/translate'\n], function (Component, $, ko, _, braintree, paypalCheckout, $t) {\n    'use strict';\n\n    /**\n     * braintree is not an instance of Component so we need to merge in our changes\n     * and return an instance of Component with the final merged object.\n     */\n    var uiC = _.extend(braintree, {\n        clientToken: null,\n        uiConfig: null,\n        paymentMethodNonce: null,\n\n        viewModel: {\n            errorMessage: ko.observable()\n        },\n\n        /**\n         * @inheritDoc\n         */\n        initialize: function (uiConfig) {\n            this._super();\n\n            this.uiConfig = uiConfig;\n            this.merchantName = uiConfig.merchantName;\n            this.locale = uiConfig.locale;\n            this.currency = uiConfig.currency;\n            this.orderAmount = uiConfig.orderAmount;\n            const self = this;\n\n            this.clientConfig = {\n\n                additionalData: {},\n                buttonId: 'paypal_container',\n\n                /**\n                 * Device data initialization\n                 * @param {String} deviceData\n                 */\n                onDeviceDataReceived: function (deviceData) {\n                    this.additionalData['device_data'] = deviceData;\n                },\n\n                /**\n                 * Triggers when widget is loaded\n                 * @param {Object} context\n                 */\n                onReady: function (context) {\n                    paypalCheckout.create({\n                        client: context.clientInstance\n                    }, async function (paypalCheckoutErr, paypalCheckoutInstance) {\n                        self.setPayPalInstance(paypalCheckoutInstance);\n\n                        await paypalCheckoutInstance.loadPayPalSDK({\n                            vault: true\n                        });\n\n                        window.paypal.Buttons({\n                            fundingSource: window.paypal.FUNDING.PAYPAL,\n\n                            createBillingAgreement: function () {\n                                return paypalCheckoutInstance.createPayment({\n                                    flow: 'vault',\n\n                                    enableShippingAddress: false,\n                                    shippingAddressEditable: false,\n\n                                    amount: self.orderAmount,\n                                    currency: self.currency,\n                                    locale: self.locale\n                                });\n                            },\n\n                            onApprove: function (data) {\n                                $('body').trigger('processStart');\n                                return paypalCheckoutInstance.tokenizePayment(data, function (err, payload) {\n                                    if (err) {\n                                        $('body').trigger('processStop');\n                                        self.viewModel.errorMessage(\n                                            $t('Please try again with another form of payment.'));\n                                        return;\n                                    }\n\n                                    $.ajax({\n                                        url: '/rest/default/V1/braintree/mine/payment/vault',\n                                        type: 'POST',\n                                        data: JSON.stringify({\n                                            payment: {\n                                                payment_method_code: 'braintree_paypal',\n                                                payment_method_nonce: payload.nonce,\n                                                device_data: self.deviceData\n                                            }\n                                        }),\n                                        contentType:'application/json; charset=utf-8',\n                                        success: function () {\n                                            window.location.reload();\n                                        },\n                                        error: function (error) {\n                                            $('body').trigger('processStop');\n                                            console.warn(error.message);\n                                        }\n                                    });\n                                });\n                            },\n\n                            onCancel: function (data) {\n                                console.log('PayPal payment canceled', JSON.stringify(data, 0, 2));\n                            },\n\n                            onError: function (err) {\n                                console.error('PayPal error', err);\n                            }\n                        }).render('#paypal_container_account');\n                    });\n                },\n\n                /**\n                 * Triggers on any Braintree error\n                 * @param {Object} response\n                 */\n                onError: function (response) {\n                    self.showError($t('PayPal error msg'));\n                    throw response.message;\n                },\n\n                /**\n                 * Triggers when customer click \"Cancel\"\n                 */\n                onCancelled: function () {\n                    self.showError($t('The process has been cancelled'));\n                },\n\n                onPaymentMethodReceived: function (response) {\n                    self.paymentMethodNonce = response.nonce;\n                    $('#braintree-paypal-payment-method-nonce').val(response.nonce);\n                    $('#braintree-paypal-form').trigger('submit');\n                },\n\n                dataCollector: {\n                    paypal: true\n                },\n                paypal: {\n                    container: 'paypal_container_account',\n                    flow: 'vault',\n                    singleUse: false,\n                    amount: self.orderAmount,\n                    currency: self.currency,\n                    locale: self.locale,\n                    enableShippingAddress: false,\n                    displayName: self.merchantName,\n\n                    /**\n                     * Triggers on any Braintree error\n                     */\n                    onError: function () {\n                        this.paymentMethodNonce = null;\n                    },\n\n                    /**\n                     * Triggers if browser doesn't support PayPal Checkout\n                     */\n                    onUnsupported: function () {\n                        this.paymentMethodNonce = null;\n                    }\n                }\n            };\n\n            this.setConfig(this.clientConfig);\n            this.clientToken = uiConfig.clientToken;\n        },\n\n        /**\n         * @inheritDoc\n         */\n        getClientToken: function () {\n            return this.clientToken;\n        },\n\n        /**\n         * @returns {String}\n         */\n        getColor: function () {\n            return this.color;\n        },\n\n        /**\n         * @returns {String}\n         */\n        getShape: function () {\n            return this.shape;\n        },\n\n        /**\n         * @returns {String}\n         */\n        getLayout: function () {\n            return this.layout;\n        },\n\n        /**\n         * @returns {String}\n         */\n        getSize: function () {\n            return this.size;\n        },\n\n        /**\n         * @returns {String}\n         */\n        getEnvironment: function () {\n            return this.environment;\n        },\n\n        /**\n         * @returns {String}\n         */\n        getDisabledFunding: function () {\n            return this.disabledFunding;\n        },\n\n        /**\n         * Set the PayPal instance or null it by setting the value of the property.\n         *\n         * @param val\n         */\n        setPayPalInstance: function (val) {\n            this.paypalInstance = val;\n        },\n\n        /**\n         * Run the teardown script to remove the PayPal instance.\n         */\n        teardownPayPalInstance: function () {\n            if (this.paypalInstance) {\n                this.paypalInstance.teardown(function () {\n                    $('#paypal_container_account').empty();\n                });\n                this.paypalInstance = null;\n            }\n\n            window.dispatchEvent(new Event('paypal:reinit-express'));\n        }\n    });\n\n    return Component.extend(uiC);\n});\n","PayPal_Braintree/js/googlepay/api.js":"/**\n * Braintree Google Pay button api\n **/\ndefine([\n    'uiComponent',\n    'underscore',\n    'jquery',\n    'mage/translate',\n    'mage/storage',\n    'PayPal_Braintree/js/form-builder',\n    'PayPal_Braintree/js/googlepay/implementations/shortcut/3d-secure',\n    'PayPal_Braintree/js/googlepay/model/parsed-response',\n    'PayPal_Braintree/js/googlepay/model/payment-data',\n    'PayPal_Braintree/js/helper/remove-non-digit-characters',\n    'PayPal_Braintree/js/view/payment/validator-manager'\n], function (\n    Component,\n    _,\n    $,\n    $t,\n    storage,\n    formBuilder,\n    threeDSecureValidator,\n    parsedResponseModel,\n    paymentDataModel,\n    removeNonDigitCharacters,\n    validatorManager\n) {\n    'use strict';\n\n    return Component.extend({\n        defaults: {\n            validatorManager: validatorManager,\n            threeDSecureValidator: threeDSecureValidator,\n            clientToken: null,\n            merchantId: null,\n            currencyCode: null,\n            actionSuccess: null,\n            amount: null,\n            cardTypes: [],\n            btnColor: 0,\n            email: null,\n            paymentMethodNonce: null,\n            creditCardBin: null\n        },\n\n        /**\n         * Set & get environment\n         * \"PRODUCTION\" or \"TEST\"\n         */\n        setEnvironment: function (value) {\n            this.environment = value;\n        },\n        getEnvironment: function () {\n            return this.environment;\n        },\n\n        /**\n         * Set & get api token\n         */\n        setClientToken: function (value) {\n            this.clientToken = value;\n        },\n        getClientToken: function () {\n            return this.clientToken;\n        },\n\n        /**\n         * Set and get display name\n         */\n        setMerchantId: function (value) {\n            this.merchantId = value;\n        },\n        getMerchantId: function () {\n            return this.merchantId;\n        },\n\n        /**\n         * Set and get currency code\n         */\n        setAmount: function (value) {\n            this.amount = parseFloat(value).toFixed(2);\n        },\n        getAmount: function () {\n            return this.amount;\n        },\n\n        /**\n         * Set and get currency code\n         */\n        setCurrencyCode: function (value) {\n            this.currencyCode = value;\n        },\n        getCurrencyCode: function () {\n            return this.currencyCode;\n        },\n\n        /**\n         * Set and get success redirection url\n         */\n        setActionSuccess: function (value) {\n            this.actionSuccess = value;\n        },\n        getActionSuccess: function () {\n            return this.actionSuccess;\n        },\n\n        /**\n         * Set and get success redirection url\n         */\n        setCardTypes: function (value) {\n            this.cardTypes = value;\n        },\n        getCardTypes: function () {\n            return this.cardTypes;\n        },\n\n        /**\n         * BTN Color\n         */\n        setBtnColor: function (value) {\n            this.btnColor = value;\n        },\n        getBtnColor: function () {\n            return this.btnColor;\n        },\n\n        /**\n         * Add the 3D Secure validator config.\n         *\n         * @param {object} value\n         */\n        setThreeDSecureValidatorConfig: function (value) {\n            this.threeDSecureValidator.setConfig(value);\n        },\n\n        /**\n         * Add the 3D Secure validator to the validation manager with amount & billing address data set.\n         * It will be added only if 3D Secure is active.\n         */\n        addThreeDSecureValidator: function () {\n            this.threeDSecureValidator.setBillingAddress(this.getThreeDSecureBillingAddressData());\n            this.threeDSecureValidator.setShippingAddress(this.getThreeDSecureShippingAddressData());\n            this.threeDSecureValidator.setTotalAmount(this.getAmount());\n\n            this.validatorManager.add(this.threeDSecureValidator);\n        },\n\n        /**\n         * Payment request info\n         */\n        getPaymentRequest: function () {\n            let result = {\n                transactionInfo: {\n                    totalPriceStatus: 'ESTIMATED',\n                    totalPrice: this.getAmount(),\n                    currencyCode: this.getCurrencyCode()\n                },\n                allowedPaymentMethods: [\n                    {\n                        'type': 'CARD',\n                        'parameters': {\n                            'allowedCardNetworks': this.getCardTypes(),\n                            'billingAddressRequired': true,\n                            'billingAddressParameters': {\n                                format: 'FULL',\n                                phoneNumberRequired: true\n                            }\n                        }\n\n                    }\n                ],\n                shippingAddressRequired: true,\n                shippingAddressParameters: {\n                    phoneNumberRequired: true\n                },\n                emailRequired: true\n            };\n\n            if (this.getEnvironment() !== 'TEST') {\n                result.merchantInfo = { merchantId: this.getMerchantId() };\n            }\n\n            return result;\n        },\n\n        /**\n         * Place the order\n         */\n        startPlaceOrder: function (deviceData) {\n            let self = this,\n                payload = {\n                    details: {\n                        shippingAddress: self.getShippingAddressData(),\n                        billingAddress: self.getBillingAddressData()\n                    },\n                    nonce: self.paymentMethodNonce,\n                    isNetworkTokenized: parsedResponseModel.getIsNetworkTokenized(),\n                    deviceData: deviceData\n                };\n\n            self.email = paymentDataModel.getEmail();\n            self.paymentMethodNonce = parsedResponseModel.getNonce();\n            self.creditCardBin = parsedResponseModel.getBin();\n\n\n            if (parsedResponseModel.getIsNetworkTokenized() === false) {\n                /* Add 3D Secure verification to payment & validate payment for non network tokenized cards */\n                self.addThreeDSecureValidator();\n\n                self.validatorManager.validate(self, function () {\n                    /* Set the new nonce from the 3DS verification */\n                    payload.nonce = self.paymentMethodNonce;\n\n                    return formBuilder.build({\n                        action: self.getActionSuccess(),\n                        fields: {\n                            result: JSON.stringify(payload)\n                        }\n                    }).submit();\n                }, function () {\n                    self.paymentMethodNonce = null;\n                    self.creditCardBin = null;\n                });\n            } else {\n                formBuilder.build({\n                    action: this.getActionSuccess(),\n                    fields: {\n                        result: JSON.stringify(payload)\n                    }\n                }).submit();\n            }\n        },\n\n        /**\n         * Get the shipping address from the payment data model which should already be set by the calling script.\n         *\n         * @return {?Object}\n         */\n        getShippingAddressData: function () {\n            let shippingAddress = paymentDataModel.getShippingAddress();\n\n            if (shippingAddress === null) {\n                return null;\n            }\n\n            return {\n                streetAddress: shippingAddress.address1 + '\\n' + shippingAddress.address2,\n                locality: shippingAddress.locality,\n                postalCode: shippingAddress.postalCode,\n                countryCodeAlpha2: shippingAddress.countryCode,\n                email: paymentDataModel.getEmail(),\n                name: shippingAddress.name,\n                telephone: removeNonDigitCharacters(_.get(shippingAddress, 'phoneNumber', '')),\n                region: _.get(shippingAddress, 'administrativeArea', '')\n            };\n        },\n\n        /**\n         * Get the billing address from the payment data model which should already be set by the calling script.\n         *\n         * @return {?Object}\n         */\n        getBillingAddressData: function () {\n            let paymentMethodData = paymentDataModel.getPaymentMethodData(),\n                billingAddress = _.get(paymentMethodData, ['info', 'billingAddress'], null);\n\n            if (paymentMethodData === null) {\n                return null;\n            }\n\n\n            if (billingAddress === null) {\n                return null;\n            }\n\n            return {\n                streetAddress: billingAddress.address1 + '\\n' + billingAddress.address2,\n                locality: billingAddress.locality,\n                postalCode: billingAddress.postalCode,\n                countryCodeAlpha2: billingAddress.countryCode,\n                email: paymentDataModel.getEmail(),\n                name: billingAddress.name,\n                telephone: removeNonDigitCharacters(_.get(billingAddress, 'phoneNumber', '')),\n                region: _.get(billingAddress, 'administrativeArea', '')\n            };\n        },\n\n        /**\n         * Get the billing address data as required for 3D Secure verification.\n         *\n         * For First & last name, use a simple split by space.\n         *\n         * @return {?Object}\n         */\n        getThreeDSecureBillingAddressData: function () {\n            let paymentMethodData = paymentDataModel.getPaymentMethodData(),\n                billingAddress = _.get(paymentMethodData, ['info', 'billingAddress'], null);\n\n            if (paymentMethodData === null) {\n                return null;\n            }\n\n            if (billingAddress === null) {\n                return null;\n            }\n\n            return {\n                firstname: billingAddress.name.substring(0, billingAddress.name.indexOf(' ')),\n                lastname: billingAddress.name.substring(billingAddress.name.indexOf(' ') + 1),\n                telephone: removeNonDigitCharacters(_.get(billingAddress, 'phoneNumber', '')),\n                street: [\n                    billingAddress.address1,\n                    billingAddress.address2\n                ],\n                city: billingAddress.locality,\n                regionCode: _.get(billingAddress, 'administrativeArea', ''),\n                postcode: billingAddress.postalCode,\n                countryId: billingAddress.countryCode\n            };\n        },\n\n        /**\n         * Get the shipping address data as required for 3D Secure verification.\n         *\n         * For First & last name, use a simple split by space.\n         *\n         * @return {?Object}\n         */\n        getThreeDSecureShippingAddressData: function () {\n            let shippingAddress = paymentDataModel.getShippingAddress();\n\n            if (shippingAddress === null) {\n                return null;\n            }\n\n            return {\n                firstname: shippingAddress.name.substring(0, shippingAddress.name.indexOf(' ')),\n                lastname: shippingAddress.name.substring(shippingAddress.name.indexOf(' ') + 1),\n                telephone: removeNonDigitCharacters(_.get(shippingAddress, 'phoneNumber', '')),\n                street: [\n                    shippingAddress.address1,\n                    shippingAddress.address2\n                ],\n                city: shippingAddress.locality,\n                regionCode: _.get(shippingAddress, 'administrativeArea', ''),\n                postcode: shippingAddress.postalCode,\n                countryId: shippingAddress.countryCode\n            };\n        }\n    });\n});\n","PayPal_Braintree/js/googlepay/button.js":"/**\n * Braintree Google Pay button\n **/\ndefine(\n    [\n        'uiComponent',\n        'underscore',\n        'knockout',\n        'jquery',\n        'Magento_Checkout/js/model/payment/additional-validators',\n        'Magento_CheckoutAgreements/js/view/checkout-agreements',\n        'PayPal_Braintree/js/googlepay/model/parsed-response',\n        'PayPal_Braintree/js/googlepay/model/payment-data',\n        'PayPal_Braintree/js/view/payment/adapter',\n        'braintree',\n        'braintreeDataCollector',\n        'braintreeGooglePay',\n        'mage/translate',\n        'googlePayLibrary'\n    ],\n    function (\n        Component,\n        _,\n        ko,\n        $,\n        additionalValidators,\n        checkoutAgreements,\n        parsedResponseModel,\n        paymentDataModel,\n        braintreeMainAdapter,\n        braintree,\n        dataCollector,\n        googlePay,\n        $t\n    ) {\n        'use strict';\n\n        return {\n            init: function (element, context) {\n\n                // No element or context\n                if (!element || !context) {\n                    return;\n                }\n\n                // Context must implement these methods\n                if (typeof context.getClientToken !== 'function') {\n                    console.error(\n                        'Braintree GooglePay Context passed does not provide a getClientToken method',\n                        context\n                    );\n                    return;\n                }\n                if (typeof context.getPaymentRequest !== 'function') {\n                    console.error(\n                        'Braintree GooglePay Context passed does not provide a getPaymentRequest method',\n                        context\n                    );\n                    return;\n                }\n                if (typeof context.startPlaceOrder !== 'function') {\n                    console.error(\n                        'Braintree GooglePay Context passed does not provide a startPlaceOrder method',\n                        context\n                    );\n                    return;\n                }\n\n                // init google pay object\n                let paymentsClient = new window.google.payments.api.PaymentsClient({\n                        environment: context.getEnvironment()\n                    }),\n\n                    // Create a button within the KO element, as Google Pay can only be instantiated through\n                    // a valid on click event (ko onclick bind interferes with this).\n                    button = document.createElement('button'),\n                    color = context.getBtnColor() === 1 ? 'black' : 'white';\n\n                button.className = 'braintree-googlepay-button long ' + color;\n                button.title = $t('Buy with Google Pay');\n\n                // init braintree api\n                braintree.create({\n                    authorization: context.getClientToken()\n                }, function (clientErr, clientInstance) {\n                    this.initGooglePay(clientErr, clientInstance, paymentsClient, button, element, context);\n                }.bind(this));\n            },\n\n            initGooglePay: function (clientErr, clientInstance, paymentsClient, button, element, context) {\n                if (clientErr) {\n                    console.error('Error creating client:', clientErr);\n                    return;\n                }\n                dataCollector.create({\n                    client: clientInstance\n                }, function (dataCollectorErr, dataCollectorInstance) {\n                    if (dataCollectorErr) {\n                        return;\n                    }\n                    googlePay.create({\n                        client: clientInstance,\n                        googlePayVersion: 2\n                    }, function (googlePayErr, googlePaymentInstance) {\n                        this.render(\n                            clientInstance,\n                            googlePayErr,\n                            googlePaymentInstance,\n                            dataCollectorInstance,\n                            paymentsClient,\n                            button,\n                            element,\n                            context\n                        );\n                    }.bind(this));\n                }.bind(this));\n            },\n\n            render: function (clientInstance, googlePayErr, googlePaymentInstance,\n                dataCollectorInstance, paymentsClient, button, element, context) {\n                // No instance\n                if (googlePayErr) {\n                    console.error('Braintree GooglePay Error creating googlePayInstance:', googlePayErr);\n                    return;\n                }\n\n                /**\n                 * Assign existing client instance to braintree adapter to use existing one\n                 * otherwise new client instance needs to be created for 3DS verification\n                 * which calls the Braintree Client & Device Collector SDK twice and\n                 * makes process slow.\n                 */\n                braintreeMainAdapter.clientInstance = clientInstance;\n                braintreeMainAdapter.deviceData = dataCollectorInstance.deviceData;\n\n                paymentsClient.isReadyToPay({\n                    apiVersion: 2,\n                    apiVersionMinor: 0,\n                    allowedPaymentMethods: googlePaymentInstance.createPaymentDataRequest().allowedPaymentMethods\n                }).then(function (response) {\n                    if (response.result) {\n                        button.addEventListener('click', function (event) {\n                            let agreements = checkoutAgreements().agreements,\n                                shouldDisableActions = false;\n\n                            _.each(agreements, function (item) {\n                                if (checkoutAgreements().isAgreementRequired(item)) {\n                                    let inputId = '#agreement_braintree_googlepay_' + item.agreementId,\n                                        inputEl = document.querySelector(inputId);\n\n                                    if (inputEl !== null && !inputEl.checked) {\n                                        shouldDisableActions = true;\n                                    }\n\n                                }\n                            });\n\n                            if ($(button).parents('#braintree-googlepay-express-payment').length === 0\n                                && !additionalValidators.validate(false)) {\n                                event.preventDefault();\n                                return false;\n                            }\n\n                            if (!shouldDisableActions) {\n                                event.preventDefault();\n                                $('body').loader('show');\n\n                                let paymentDataRequest = googlePaymentInstance.createPaymentDataRequest(\n                                    context.getPaymentRequest()\n                                );\n\n                                paymentsClient.loadPaymentData(paymentDataRequest).then(function (paymentData) {\n                                    // Persist the paymentData (shipping address etc.)\n                                    paymentDataModel.setPaymentMethodData(_.get(\n                                        paymentData,\n                                        'paymentMethodData',\n                                        null\n                                    ));\n                                    paymentDataModel.setEmail(_.get(paymentData, 'email', ''));\n                                    paymentDataModel.setShippingAddress(_.get(\n                                        paymentData,\n                                        'shippingAddress',\n                                        null\n                                    ));\n                                    // Return the braintree nonce promise\n                                    return googlePaymentInstance.parseResponse(paymentData);\n                                }).then(function (result) {\n                                    parsedResponseModel.setNonce(result.nonce);\n                                    parsedResponseModel.setIsNetworkTokenized(_.get(\n                                        result,\n                                        ['details', 'isNetworkTokenized'],\n                                        false\n                                    ));\n                                    parsedResponseModel.setBin(_.get(\n                                        result,\n                                        ['details', 'bin'],\n                                        null\n                                    ));\n\n                                    context.startPlaceOrder(dataCollectorInstance.deviceData);\n                                    $('body').loader('hide');\n                                }).catch(function (err) {\n                                    // Handle errors\n                                    // err = {statusCode: \"CANCELED\"}\n                                    console.error(err);\n                                    parsedResponseModel.resetDefaultData();\n                                    $('body').loader('hide');\n                                });\n                            }\n                        });\n                        element.appendChild(button);\n                    }\n                }).catch(function (err) {\n                    console.error(err);\n                    $('body').loader('hide');\n                });\n            }\n        };\n    }\n);\n","PayPal_Braintree/js/googlepay/implementations/shortcut.js":"/**\n * Braintree Google Pay mini cart payment method integration.\n **/\ndefine(\n    [\n        'uiComponent',\n        'PayPal_Braintree/js/googlepay/button',\n        'PayPal_Braintree/js/googlepay/api',\n        'domReady!'\n    ],\n    function (\n        Component,\n        button,\n        buttonApi\n    ) {\n        'use strict';\n\n        return Component.extend({\n\n            defaults: {\n                id: null,\n                clientToken: null,\n                merchantId: null,\n                currencyCode: null,\n                actionSuccess: null,\n                amount: null,\n                environment: 'TEST',\n                cardType: [],\n                btnColor: 0,\n                threeDSecure: null\n            },\n\n            /**\n             * @returns {Object}\n             */\n            initialize: function () {\n                this._super();\n\n                /* Add client token & environment to 3DS Config */\n                this.threeDSecure.clientToken = this.clientToken;\n                this.threeDSecure.environment = this.environment;\n\n                let api = new buttonApi();\n\n                api.setEnvironment(this.environment);\n                api.setCurrencyCode(this.currencyCode);\n                api.setClientToken(this.clientToken);\n                api.setMerchantId(this.merchantId);\n                api.setActionSuccess(this.actionSuccess);\n                api.setAmount(this.amount);\n                api.setCardTypes(this.cardTypes);\n                api.setBtnColor(this.btnColor);\n                api.setThreeDSecureValidatorConfig(this.threeDSecure);\n\n                // Attach the button\n                button.init(\n                    document.getElementById(this.id),\n                    api\n                );\n\n                return this;\n            }\n        });\n    }\n);\n","PayPal_Braintree/js/googlepay/implementations/shortcut/3d-secure.js":"/**\n * Copyright \u00a9 Magento, Inc. All rights reserved.\n * See COPYING.txt for license details.\n */\n/*browser:true*/\ndefine([\n    'underscore',\n    'jquery',\n    'mage/translate',\n    'braintreeThreeDSecure',\n    'PayPal_Braintree/js/googlepay/implementations/shortcut/adapter',\n    'PayPal_Braintree/js/helper/escape-non-ascii-characters',\n    'PayPal_Braintree/js/helper/remove-non-digit-characters',\n    'PayPal_Braintree/js/helper/format-amount',\n    'PayPal_Braintree/js/model/full-screen-loader'\n], function (\n    _,\n    $,\n    $t,\n    threeDSecure,\n    braintree,\n    escapeNonAsciiCharacters,\n    removeNonDigitCharacters,\n    formatAmount,\n    defaultFullScreenLoader\n) {\n    'use strict';\n\n    /**\n     * 3D Secure implementation generic enough to be used for GooglePay button payments.\n     *\n     * This can be used in other pages along with the basket page, but not in the checkout page when placing an order.\n     */\n    return {\n        code: 'three_d_secure',\n        fullScreenLoader: defaultFullScreenLoader,\n        config: null,\n        billingAddress: null,\n        shippingAddress: null,\n        totalAmount: null,\n\n        /**\n         * Get code.\n         *\n         * @returns {string}\n         */\n        getCode: function () {\n            return this.code;\n        },\n\n        /**\n         *\n         * @return {boolean}\n         */\n        isEnabled: function () {\n            return this.config !== null ? _.get(this.config, ['enabled'], false) : false;\n        },\n\n        /**\n         * Set the full screen loader implementation.\n         *\n         * @param fullScreenLoader\n         */\n        setFullScreenLoader: function (fullScreenLoader) {\n            this.fullScreenLoader = fullScreenLoader;\n        },\n\n        /**\n         * Get the full screen loader implementation.\n         */\n        getFullScreenLoader: function () {\n            return this.fullScreenLoader;\n        },\n\n        /**\n         * Set 3d secure config.\n         *\n         * @param {object} config\n         */\n        setConfig: function (config) {\n            this.config = config;\n            this.config.thresholdAmount = parseFloat(_.get(config, 'thresholdAmount', '0.0'));\n        },\n\n        /**\n         * Get the billing address data.\n         */\n        getBillingAddress: function () {\n            return this.billingAddress;\n        },\n\n        /**\n         * Set the billing address data.\n         *\n         * @param {object} value\n         */\n        setBillingAddress: function (value) {\n            this.billingAddress = value;\n        },\n\n        /**\n         * Get the shipping address data.\n         */\n        getShippingAddress: function () {\n            return this.shippingAddress;\n        },\n\n        /**\n         * Set the shipping address data.\n         *\n         * @param {object} value\n         */\n        setShippingAddress: function (value) {\n            this.shippingAddress = value;\n        },\n\n        /**\n         * Get the total amount to be charged.\n         */\n        getTotalAmount: function () {\n            return this.totalAmount;\n        },\n\n        /**\n         * Set the full screen loader implementation.\n         *\n         * @param {string} value\n         */\n        setTotalAmount: function (value) {\n            this.totalAmount = formatAmount(value);\n        },\n\n        /**\n         * Get the Braintree environment.\n         *\n         * @return {string|null}\n         */\n        getEnvironment: function () {\n            return _.get(this.config, 'environment', 'TEST');\n        },\n\n        /**\n         * Get the Braintree Client Token.\n         *\n         * @return {string|null}\n         */\n        getClientToken: function () {\n            return _.get(this.config, 'clientToken', null);\n        },\n\n        /**\n         * Check minimal amount for 3d secure activation.\n         *\n         * @param {Number} amount\n         * @returns {Boolean}\n         */\n        isAmountAvailable: function (amount) {\n            amount = parseFloat(amount.toString());\n\n            return amount >= this.config.thresholdAmount;\n        },\n\n        /**\n         * Check if current country is available for 3d secure.\n         *\n         * @param {String} countryId\n         * @returns {Boolean}\n         */\n        isCountryAvailable: function (countryId) {\n            let key,\n                specificCountries = _.get(this.config, 'specificCountries', []);\n\n            // all countries are available\n            if (!specificCountries.length) {\n                return true;\n            }\n\n            for (key in specificCountries) {\n                if (countryId === specificCountries[key]) {\n                    return true;\n                }\n            }\n\n            return false;\n        },\n\n        /**\n         * Check billing/shipping address line lengths\n         *\n         * @param errorMessage\n         * @param billingAddress\n         * @param shippingAddress\n         * @returns {*}\n         */\n        checkBillingLineLengths: function (errorMessage, billingAddress, shippingAddress) {\n            let lineError = null;\n\n            if (billingAddress.street[0].length > 50 ||\n                (shippingAddress.street !== undefined && shippingAddress.street[0].length > 50)) {\n                lineError = 'line1';\n            } else if (billingAddress.street[1].length > 50 ||\n                (shippingAddress.street !== undefined && shippingAddress.street[1].length > 50)) {\n                lineError = 'line2';\n            }\n\n            if (lineError) {\n                let error = `Billing/Shipping ${lineError} must be string and less than 50 characters.`;\n\n                return $t(`${error} Please update the address and try again.`);\n            }\n        },\n\n        /**\n         * Get the challenge requested config (default false).\n         *\n         * @returns {Boolean}\n         */\n        getChallengeRequested: function () {\n            return _.get(this.config, 'challengeRequested', false);\n        },\n\n        /**\n         * Get Customer's IP Address\n         *\n         * @returns {Boolean}\n         */\n        getIpAddress: function () {\n            return _.get(this.config, 'ipAddress', '');\n        },\n\n        /**\n         * Trigger 3DS verification & validate Braintree payment nonce.\n         *\n         * @param {Object} context\n         * @returns {Object}\n         */\n        validate: function (context) {\n            let self = this,\n                clientInstance = braintree.getApiClient(),\n                state = $.Deferred(),\n                billingAddress = self.getBillingAddress(),\n                shippingAddress = self.getShippingAddress(),\n                setup3d;\n\n            // Handle billing address region code\n            if (billingAddress.regionCode == null) {\n                billingAddress.regionCode = undefined;\n            }\n            if (billingAddress.regionCode !== undefined && billingAddress.regionCode.length > 2) {\n                billingAddress.regionCode = undefined;\n            }\n\n            // Handle shipping address region code\n            if (shippingAddress.regionCode == null) {\n                shippingAddress.regionCode = undefined;\n            }\n            if (shippingAddress.regionCode !== undefined && shippingAddress.regionCode.length > 2) {\n                shippingAddress.regionCode = undefined;\n            }\n\n            if (!self.isAmountAvailable(self.getTotalAmount()) || !self.isCountryAvailable(billingAddress.countryId)) {\n                state.resolve();\n                return state.promise();\n            }\n\n            self.getFullScreenLoader().startLoader();\n\n            setup3d = function (client) {\n                threeDSecure.create({\n                    version: 2,\n                    client: client\n                }, function (threeDSecureErr, threeDSecureInstance) {\n                    if (threeDSecureErr) {\n                        self.getFullScreenLoader().stopLoader();\n                        return state.reject($t('Please try again with another form of payment.'));\n                    }\n\n                    let threeDSContainer = document.createElement('div'),\n                        tdMask = document.createElement('div'),\n                        tdFrame = document.createElement('div'),\n                        tdBody = document.createElement('div'),\n                        threeDSecureParameters;\n\n                    threeDSContainer.className = 'braintree-three-d-modal';\n                    tdMask.className = 'bt-mask';\n                    tdFrame.className = 'bt-modal-frame';\n                    tdBody.className = 'bt-modal-body';\n\n                    tdFrame.appendChild(tdBody);\n                    threeDSContainer.appendChild(tdMask);\n                    threeDSContainer.appendChild(tdFrame);\n\n                    threeDSecureParameters = {\n                        amount: self.getTotalAmount(),\n                        nonce: context.paymentMethodNonce,\n                        bin: context.creditCardBin,\n                        collectDeviceData: true,\n                        challengeRequested: self.getChallengeRequested(),\n                        billingAddress: {\n                            givenName: escapeNonAsciiCharacters(billingAddress.firstname),\n                            surname: escapeNonAsciiCharacters(billingAddress.lastname),\n                            phoneNumber: billingAddress.telephone !== null\n                                ? removeNonDigitCharacters(billingAddress.telephone)\n                                : billingAddress.telephone,\n                            streetAddress: billingAddress.street[0],\n                            extendedAddress: billingAddress.street[1],\n                            locality: billingAddress.city,\n                            region: billingAddress.regionCode,\n                            postalCode: billingAddress.postcode,\n                            countryCodeAlpha2: billingAddress.countryId\n                        },\n                        additionalInformation: {\n                            shippingGivenName: escapeNonAsciiCharacters(shippingAddress.firstname),\n                            shippingSurname: escapeNonAsciiCharacters(shippingAddress.lastname),\n                            shippingAddress: {\n                                streetAddress: shippingAddress.street[0],\n                                extendedAddress: shippingAddress.street[1],\n                                locality: shippingAddress.city,\n                                region: shippingAddress.regionCode,\n                                postalCode: shippingAddress.postcode,\n                                countryCodeAlpha2: shippingAddress.countryId\n                            },\n                            shippingPhone: shippingAddress.telephone !== null\n                                ? removeNonDigitCharacters(shippingAddress.telephone)\n                                : shippingAddress.telephone,\n                            ipAddress: self.getIpAddress()\n                        },\n                        onLookupComplete: function (data, next) {\n                            next();\n                        },\n                        addFrame: function (err, iframe) {\n                            self.getFullScreenLoader().stopLoader();\n\n                            if (err) {\n                                console.log('Unable to verify card over 3D Secure', err);\n                                return state.reject($t('Please try again with another form of payment.'));\n                            }\n\n                            tdBody.appendChild(iframe);\n                            document.body.appendChild(threeDSContainer);\n                        },\n                        removeFrame: function () {\n                            self.getFullScreenLoader().startLoader();\n                            document.body.removeChild(threeDSContainer);\n                        }\n                    };\n\n                    if (_.has(context, 'email') && context.email !== null) {\n                        threeDSecureParameters.email = context.email;\n                    }\n\n                    threeDSecureInstance.verifyCard(threeDSecureParameters, function (err, response) {\n                        self.getFullScreenLoader().stopLoader();\n\n                        if (err) {\n                            console.error('3DSecure validation failed', err);\n                            if (err.code === 'THREEDS_LOOKUP_VALIDATION_ERROR') {\n                                let errorMessage = err.details.originalError.details.originalError.error.message,\n                                    error = self.checkBillingLineLengths(errorMessage, billingAddress, shippingAddress);\n\n                                return error ? state.reject(error) : state.reject($t(errorMessage));\n                            }\n\n                            return state.reject($t('Please try again with another form of payment.'));\n                        }\n\n                        let liability = {\n                            shifted: response.liabilityShifted,\n                            shiftPossible: response.liabilityShiftPossible\n                        };\n\n                        if (liability.shifted || !liability.shifted && !liability.shiftPossible) {\n                            context.paymentMethodNonce = response.nonce;\n                            state.resolve();\n                        } else {\n                            state.reject($t('Please try again with another form of payment.'));\n                        }\n                    }.bind(this));\n                });\n            };\n\n            if (!clientInstance) {\n                self.createClientInstance(setup3d);\n            } else {\n                setup3d(clientInstance);\n            }\n\n            return state.promise();\n        },\n\n        /**\n         * Create a Braintree client instance with simplified form.\n         *\n         * @param {Function} setupThreeDSecureCallback\n         * @return {*}\n         */\n        createClientInstance: function (setupThreeDSecureCallback) {\n            let self = this;\n\n            return require(['PayPal_Braintree/js/googlepay/implementations/shortcut/form'], function (c) {\n                c.defaults.clientConfig.clientToken = self.getClientToken();\n                c.defaults.clientConfig.environment = self.getEnvironment();\n                braintree.setConfig(c.defaults.clientConfig);\n                braintree.setup(setupThreeDSecureCallback);\n            });\n        }\n    };\n});\n","PayPal_Braintree/js/googlepay/implementations/shortcut/form.js":"/*browser:true*/\ndefine([\n    'underscore',\n    'jquery',\n    'uiComponent'\n], function (_, $, Component) {\n    'use strict';\n\n    return Component.extend({\n        defaults: {\n            braintreeClient: null,\n            code: 'braintree',\n            isProcessing: false,\n\n            /**\n             * Braintree client configuration\n             *\n             * {Object}\n             */\n            clientConfig: {\n                onReady: function () {},\n\n                /**\n                 * Triggers on payment nonce receive\n                 */\n                onPaymentMethodReceived: function () {\n                    this.isProcessing = false;\n                },\n\n                /**\n                 * Allow a new nonce to be generated\n                 */\n                onPaymentMethodError: function () {\n                    this.isProcessing = false;\n                },\n\n                /**\n                 * After Braintree instance initialization\n                 */\n                onInstanceReady: function () {},\n\n                /**\n                 * Triggers on any Braintree error\n                 * @param {Object} response\n                 */\n                onError: function (response) {\n                    this.isProcessing = false;\n                    throw response.message;\n                },\n\n                /**\n                 * Triggers when customer click \"Cancel\"\n                 */\n                onCancelled: function () {\n                    this.isProcessing = false;\n                }\n            }\n        },\n\n        /**\n         * Set list of observable attributes\n         *\n         * @returns {exports.initObservable}\n         */\n        initObservable: function () {\n            this._super();\n\n            this.initClientConfig();\n\n            return this;\n        },\n\n        /**\n         * Get payment name\n         *\n         * @returns {String}\n         */\n        getCode: function () {\n            return this.code;\n        },\n\n        /**\n         * Init config\n         */\n        initClientConfig: function () {\n            _.each(this.clientConfig, function (fn, name) {\n                if (typeof fn === 'function') {\n                    this.clientConfig[name] = fn.bind(this);\n                }\n            }, this);\n        }\n    });\n});\n","PayPal_Braintree/js/googlepay/implementations/shortcut/adapter.js":"/*browser:true*/\ndefine([\n    'underscore',\n    'jquery',\n    'mage/translate',\n    'braintree',\n    'PayPal_Braintree/js/model/full-screen-loader',\n    'Magento_Ui/js/model/messageList'\n], function (\n    _,\n    $,\n    $t,\n    client,\n    defaultFullScreenLoader,\n    globalMessageList\n) {\n    'use strict';\n\n    /**\n     * Braintree Client adapter implementation generic enough to be used for GooglePay button payments.\n     *\n     * This can be used in other pages along with the basket page, but not in the checkout page when placing an order.\n     */\n    return {\n        fullScreenLoader: defaultFullScreenLoader,\n        apiClient: null,\n        config: {},\n        checkout: null,\n        clientInstance: null,\n        code: 'braintree',\n\n        /**\n         * {Object}\n         */\n        events: {\n            onClick: null,\n            onCancel: null,\n            onError: null\n        },\n\n        /**\n         * Get Braintree api client.\n         *\n         * @returns {Object}\n         */\n        getApiClient: function () {\n            return this.clientInstance;\n        },\n\n        /**\n         * Set configuration.\n         *\n         * @param {Object} config\n         */\n        setConfig: function (config) {\n            this.config = config;\n\n            if (_.has(this.config, 'code')) {\n                this.code = this.config.code;\n            }\n        },\n\n        /**\n         * Get payment name.\n         *\n         * @returns {string}\n         */\n        getCode: function () {\n            return this.code;\n        },\n\n        /**\n         * Get client token\n         *\n         * @returns {string|*}\n         */\n        getClientToken: function () {\n            return this.config.hasOwnProperty('clientToken') ? this.config.clientToken : null;\n        },\n\n        /**\n         * @returns {string}\n         */\n        getEnvironment: function () {\n            return this.config.hasOwnProperty('environment') ? this.config.environment : null;\n        },\n\n        /**\n         * Set fullscreen loader implementation allowing to use custom.\n         *\n         * @param {Function} fullScreenLoader\n         */\n        setFullScreenLoader: function (fullScreenLoader) {\n            this.fullScreenLoader = fullScreenLoader;\n        },\n\n        /**\n         * Get the full screen loader implementation.\n         *\n         * @return {Object}\n         */\n        getFullScreenLoader: function () {\n            return this.fullScreenLoader;\n        },\n\n        /**\n         * Show error message\n         *\n         * @param {string} errorMessage\n         */\n        showError: function (errorMessage) {\n            globalMessageList.addErrorMessage({\n                message: errorMessage\n            });\n\n            this.getFullScreenLoader().stopLoader(true);\n        },\n\n        /**\n         * Setup Braintree SDK.\n         *\n         * @param {Function|null} callback\n         */\n        setup: function (callback = null) {\n            if (!this.getClientToken()) {\n                this.showError($t('Sorry, but something went wrong.'));\n                return;\n            }\n\n            if (this.clientInstance) {\n                if (typeof this.config.onReady === 'function') {\n                    this.config.onReady(this);\n                }\n\n                if (typeof callback === 'function') {\n                    callback(this.clientInstance);\n                }\n\n                return;\n            }\n\n            client.create({\n                authorization: this.getClientToken()\n            }, function (clientErr, clientInstance) {\n                if (clientErr) {\n                    console.error('Braintree Setup Error', clientErr);\n                    return this.showError('Sorry, but something went wrong. Please contact the store owner.');\n                }\n\n                this.clientInstance = clientInstance;\n\n                if (typeof this.config.onReady === 'function') {\n                    this.config.onReady(this);\n                }\n\n                if (typeof callback === 'function') {\n                    callback(this.clientInstance);\n                }\n            }.bind(this));\n        }\n    };\n});\n","PayPal_Braintree/js/googlepay/implementations/core-checkout/method-googlepay.js":"define([\n    'uiComponent',\n    'Magento_Checkout/js/model/payment/renderer-list'\n], function (Component, rendererList) {\n    'use strict';\n\n    let config = window.checkoutConfig.payment;\n\n    if (config['braintree_googlepay'].clientToken) {\n        rendererList.push({\n            type: 'braintree_googlepay',\n            component: 'PayPal_Braintree/js/googlepay/implementations/core-checkout/method-renderer/googlepay'\n        });\n    }\n\n    return Component.extend({});\n});\n","PayPal_Braintree/js/googlepay/implementations/core-checkout/method-renderer/googlepay.js":"/**\n * Braintree Google Pay payment method integration.\n **/\ndefine([\n    'underscore',\n    'Magento_Checkout/js/view/payment/default',\n    'Magento_Checkout/js/model/quote',\n    'Magento_Vault/js/view/payment/vault-enabler',\n    'PayPal_Braintree/js/googlepay/button',\n    'PayPal_Braintree/js/googlepay/model/parsed-response',\n    'PayPal_Braintree/js/view/payment/validator-handler'\n], function (\n    _,\n    Component,\n    quote,\n    VaultEnabler,\n    GooglePayButton,\n    parsedResponseModel,\n    validatorManager\n) {\n    'use strict';\n\n    return Component.extend({\n        defaults: {\n            template: 'PayPal_Braintree/googlepay/core-checkout',\n            validatorManager: validatorManager,\n            paymentMethodNonce: null,\n            creditCardBin: null,\n            deviceData: null,\n            grandTotalAmount: 0,\n            vaultEnabler: null,\n            additionalData: {}\n        },\n\n        /**\n         * @returns {exports.initialize}\n         */\n        initialize: function () {\n            this._super();\n            this.vaultEnabler = new VaultEnabler();\n            this.vaultEnabler.setPaymentCode(this.getVaultCode());\n\n            return this;\n        },\n\n        /**\n         * Inject the Google Pay button into the target element\n         */\n        getGooglePayBtn: function (id) {\n            GooglePayButton.init(\n                document.getElementById(id),\n                this\n            );\n        },\n\n        /**\n         * Subscribe to grand totals\n         */\n        initObservable: function () {\n            this._super();\n            this.vaultEnabler = new VaultEnabler();\n            this.vaultEnabler.setPaymentCode(this.getVaultCode());\n\n            this.validatorManager.initialize();\n\n            this.grandTotalAmount = parseFloat(quote.totals()['base_grand_total']).toFixed(2);\n            this.currencyCode = quote.totals()['base_currency_code'];\n\n            quote.totals.subscribe(function () {\n                if (this.grandTotalAmount !== quote.totals()['base_grand_total']) {\n                    this.grandTotalAmount = parseFloat(quote.totals()['base_grand_total']).toFixed(2);\n                }\n            }.bind(this));\n\n            return this;\n        },\n\n        /**\n         * Google Pay place order method\n         */\n        startPlaceOrder: function (device_data) {\n            let self = this;\n\n            /* Set the nonce & bin and trigger 3DS if card is not network tokenized */\n            self.paymentMethodNonce = parsedResponseModel.getNonce();\n            self.creditCardBin = parsedResponseModel.getBin();\n\n            if (parsedResponseModel.getIsNetworkTokenized() === false) {\n                // place order on success validation\n                self.validatorManager.validate(self, function () {\n                    self.setDeviceData(device_data);\n                    return self.placeOrder('parent');\n                }, function () {\n                    self.paymentMethodNonce = null;\n                    self.creditCardBin = null;\n                });\n            } else {\n                self.setDeviceData(device_data);\n                self.placeOrder();\n            }\n        },\n\n        /**\n         * Save device_data\n         */\n        setDeviceData: function (device_data) {\n            this.deviceData = device_data;\n        },\n\n        /**\n         * Retrieve the client token\n         * @returns null|string\n         */\n        getClientToken: function () {\n            return window.checkoutConfig.payment[this.getCode()].clientToken;\n        },\n\n        /**\n         * Payment request info\n         */\n        getPaymentRequest: function () {\n            let result = {\n                transactionInfo: {\n                    totalPriceStatus: 'FINAL',\n                    totalPrice: this.grandTotalAmount,\n                    currencyCode: this.currencyCode\n                },\n                allowedPaymentMethods: [\n                    {\n                        'type': 'CARD',\n                        'parameters': {\n                            'allowedCardNetworks': this.getCardTypes(),\n                            'billingAddressRequired': true,\n                            'billingAddressParameters': {\n                                format: 'FULL',\n                                phoneNumberRequired: true\n                            }\n                        }\n\n                    }\n                ],\n                shippingAddressRequired: false,\n                emailRequired: false\n            };\n\n            if (this.getEnvironment() !== 'TEST') {\n                result.merchantInfo = { merchantId: this.getMerchantId() };\n            }\n\n            return result;\n        },\n\n        /**\n         * Merchant display name\n         */\n        getMerchantId: function () {\n            return window.checkoutConfig.payment[this.getCode()].merchantId;\n        },\n\n        /**\n         * Environment\n         */\n        getEnvironment: function () {\n            return window.checkoutConfig.payment[this.getCode()].environment;\n        },\n\n        /**\n         * Card Types\n         */\n        getCardTypes: function () {\n            return window.checkoutConfig.payment[this.getCode()].cardTypes;\n        },\n\n        /**\n         * BTN Color\n         */\n        getBtnColor: function () {\n            return window.checkoutConfig.payment[this.getCode()].btnColor;\n        },\n\n        /**\n         * Get data\n         * @returns {Object}\n         */\n        getData: function () {\n            let data = {\n                'method': this.getCode(),\n                'additional_data': {\n                    'payment_method_nonce': this.paymentMethodNonce,\n                    'device_data': this.deviceData,\n                    'is_network_tokenized': parsedResponseModel.getIsNetworkTokenized()\n                }\n            };\n\n            if (parsedResponseModel.getIsNetworkTokenized() === false) {\n                data['additional_data'] = _.extend(data['additional_data'], this.additionalData);\n                this.vaultEnabler.visitAdditionalData(data);\n            }\n\n            return data;\n        },\n\n        /**\n         * Return image url for the Google Pay mark\n         */\n        getPaymentMarkSrc: function () {\n            return window.checkoutConfig.payment[this.getCode()].paymentMarkSrc;\n        },\n\n        /**\n         * @returns {Boolean}\n         */\n        isVaultEnabled: function () {\n            return this.vaultEnabler.isVaultEnabled();\n        },\n\n        /**\n         * @returns {String}\n         */\n        getVaultCode: function () {\n            return window.checkoutConfig.payment[this.getCode()].vaultCode;\n        }\n    });\n});\n","PayPal_Braintree/js/googlepay/model/parsed-response.js":"define([\n    'underscore',\n    'ko'\n], function (_, ko) {\n    'use strict';\n\n    let nonce = ko.observable(null),\n        isNetworkTokenized = ko.observable(false),\n        bin = ko.observable(null);\n\n    return {\n        nonce: nonce,\n        isNetworkTokenized: isNetworkTokenized,\n        bin: bin,\n\n        /**\n         * Get the payment nonce.\n         *\n         * @return {?string}\n         */\n        getNonce: function () {\n            return this.nonce();\n        },\n\n        /**\n         * Set the payment nonce.\n         *\n         * @param {?string} value\n         * @return {void}\n         */\n        setNonce: function (value) {\n            this.nonce(_.isString(value) ? value : null);\n        },\n\n        /**\n         * Get is network tokenized property for used card.\n         *\n         * @return {boolean}\n         */\n        getIsNetworkTokenized: function () {\n            return this.isNetworkTokenized();\n        },\n\n        /**\n         * Set is network tokenized property for used card.\n         *\n         * @param {boolean} value\n         * @return {void}\n         */\n        setIsNetworkTokenized: function (value) {\n            this.isNetworkTokenized(_.isBoolean(value) ? value : false);\n        },\n\n        /**\n         * Get card bin.\n         *\n         * @return {?string}\n         */\n        getBin: function () {\n            return this.bin();\n        },\n\n        /**\n         * Set the card bin.\n         *\n         * @param {?string} value\n         * @return {void}\n         */\n        setBin: function (value) {\n            this.bin(_.isString(value) ? value : null);\n        },\n\n        /**\n         * Reset data to default.\n         */\n        resetDefaultData: function () {\n            this.setNonce(null);\n            this.setIsNetworkTokenized(false);\n            this.setBin(null);\n        }\n    };\n});\n","PayPal_Braintree/js/googlepay/model/payment-data.js":"define([\n    'underscore',\n    'ko'\n], function (_, ko) {\n    'use strict';\n\n    let paymentMethodData = ko.observable(null),\n        email = ko.observable(null),\n        shippingAddress = ko.observable(null);\n\n    return {\n        paymentMethodData: paymentMethodData,\n        email: email,\n        shippingAddress: shippingAddress,\n\n        /**\n         * Get Google Pay payment method data details.\n         *\n         * @return {?Object}\n         */\n        getPaymentMethodData: function () {\n            return this.paymentMethodData();\n        },\n\n        /**\n         * Set Google Pay payment method data details.\n         *\n         * @param {?Object} value\n         * @return {void}\n         */\n        setPaymentMethodData: function (value) {\n            this.paymentMethodData(_.isObject(value) ? value : null);\n        },\n\n        /**\n         * Get Google Pay email.\n         *\n         * @return {?string}\n         */\n        getEmail: function () {\n            return this.email();\n        },\n\n        /**\n         * Set Google Pay email.\n         *\n         * @param {?string} value\n         * @return {void}\n         */\n        setEmail: function (value) {\n            this.email(_.isString(value) ? value : null);\n        },\n\n        /**\n         * Get Google Pay shipping address.\n         *\n         * @return {?Object}\n         */\n        getShippingAddress: function () {\n            return shippingAddress();\n        },\n\n        /**\n         * Set Google Pay shipping address.\n         *\n         * @param {?Object} value\n         * @return {void}\n         */\n        setShippingAddress: function (value) {\n            this.shippingAddress(_.isObject(value) ? value : null);\n        },\n\n        /**\n         * Reset data to default.\n         */\n        resetDefaultData: function () {\n            this.setPaymentMethodData(null);\n            this.setEmail(null);\n            this.setShippingAddress(null);\n        }\n    };\n});\n","PayPal_Braintree/js/view/product-page.js":"define(\n    ['uiComponent'],\n    function (Component) {\n        'use strict';\n\n        return Component.extend({\n\n        });\n    }\n);\n","PayPal_Braintree/js/view/payment/venmo.js":"define(\n    [\n        'uiComponent',\n        'Magento_Checkout/js/model/payment/renderer-list'\n    ],\n    function (\n        Component,\n        rendererList\n    ) {\n        'use strict';\n\n        rendererList.push(\n            {\n                type: 'braintree_venmo',\n                component: 'PayPal_Braintree/js/view/payment/method-renderer/venmo'\n            }\n        );\n\n        return Component.extend({});\n    }\n);\n","PayPal_Braintree/js/view/payment/validator-manager.js":"/**\n * Copyright \u00a9 Magento, Inc. All rights reserved.\n * See COPYING.txt for license details.\n */\n/*browser:true*/\n\ndefine([\n    'jquery',\n    'Magento_Ui/js/model/messageList',\n    'PayPal_Braintree/js/model/full-screen-loader'\n], function (\n    $,\n    globalMessageList,\n    defaultFullScreenLoader\n) {\n    'use strict';\n\n    /**\n     * New Validator handler implementation that can be used across website areas including checkout.\n     */\n    return {\n        fullScreenLoader: defaultFullScreenLoader,\n        validators: [],\n\n        /**\n         * Set the full screen loader implementation.\n         *\n         * @param fullScreenLoader\n         */\n        setFullScreenLoader: function (fullScreenLoader) {\n            this.fullScreenLoader = fullScreenLoader;\n        },\n\n        /**\n         * Get the full screen loader implementation.\n         */\n        getFullScreenLoader: function () {\n            return this.fullScreenLoader;\n        },\n\n        /**\n         * Add new validator if enabled.\n         *\n         * Always expect the validator to have the isEnabled method (property), if not skip.\n         *\n         * @param {Object} validator\n         */\n        add: function (validator) {\n            if (!validator.hasOwnProperty('isEnabled')\n                || typeof validator.isEnabled !== 'function'\n                || !validator.isEnabled()\n            ) {\n                return;\n            }\n\n            this.validators.push(validator);\n        },\n\n        /**\n         * Run pull of validators.\n         *\n         * @param {Object} context\n         * @param {Function} callback\n         * @param {Function} errorCallback\n         */\n        validate: function (context, callback, errorCallback) {\n            let self = this,\n                deferred;\n\n            // no available validators\n            if (!self.validators.length) {\n                callback();\n\n                return;\n            }\n\n            // get list of deferred validators\n            deferred = $.map(self.validators, function (current) {\n                return current.validate(context);\n            });\n\n            $.when.apply($, deferred)\n                .done(function () {\n                    callback();\n                }).fail(function (error) {\n                    errorCallback();\n                    self.showError(error);\n                });\n        },\n\n        /**\n         * Show error message.\n         *\n         * @param {string} errorMessage\n         */\n        showError: function (errorMessage) {\n            globalMessageList.addErrorMessage({\n                message: errorMessage\n            });\n\n            this.getFullScreenLoader().stopLoader(true);\n        }\n    };\n});\n","PayPal_Braintree/js/view/payment/3d-secure.js":"/**\n * Copyright \u00a9 Magento, Inc. All rights reserved.\n * See COPYING.txt for license details.\n */\n/*browser:true*/\n\ndefine([\n    'jquery',\n    'PayPal_Braintree/js/view/payment/adapter',\n    'Magento_Checkout/js/model/quote',\n    'mage/translate',\n    'braintreeThreeDSecure',\n    'Magento_Checkout/js/model/full-screen-loader',\n    'PayPal_Braintree/js/helper/remove-non-digit-characters',\n    'PayPal_Braintree/js/helper/escape-non-ascii-characters',\n    'PayPal_Braintree/js/model/vault-enabler'\n], function (\n    $,\n    braintree,\n    quote,\n    $t,\n    threeDSecure,\n    fullScreenLoader,\n    removeNonDigitCharacters,\n    escapeNonAsciiCharacters,\n    vaultEnablerModel\n) {\n    'use strict';\n\n    return {\n        config: null,\n\n        /**\n         * Set 3d secure config\n         * @param {Object} config\n         */\n        setConfig: function (config) {\n            this.config = config;\n            this.config.thresholdAmount = parseFloat(config.thresholdAmount);\n\n            // Initialize vault enabler to check is it actually enabled or passed\n            vaultEnablerModel.setPaymentCode(this.config.ccVaultCode);\n        },\n\n        /**\n         * Get code\n         * @returns {String}\n         */\n        getCode: function () {\n            return 'three_d_secure';\n        },\n\n        /**\n         * Check billing/shipping address line lengths\n         *\n         * @param errorMessage\n         * @param billingAddress\n         * @param shippingAddress\n         * @returns {*}\n         */\n        checkBillingLineLengths: function (errorMessage, billingAddress, shippingAddress) {\n            let lineError = null;\n\n            if (billingAddress.street[0].length > 50 ||\n                (shippingAddress.street !== undefined && shippingAddress.street[0].length > 50)) {\n                lineError = 'line1';\n            } else if (billingAddress.street[1].length > 50 ||\n                (shippingAddress.street !== undefined && shippingAddress.street[1].length > 50)) {\n                lineError = 'line2';\n            }\n\n            if (lineError) {\n                let error = `Billing/Shipping ${lineError} must be string and less than 50 characters.`;\n\n                return $t(`${error} Please update the address and try again.`);\n            }\n        },\n\n        /**\n         * Validate Braintree payment nonce\n         * @param {Object} context\n         * @returns {Object}\n         */\n        validate: function (context) {\n            let self = this,\n                clientInstance = braintree.getApiClient(),\n                state = $.Deferred(),\n                totalAmount = parseFloat(quote.totals()['base_grand_total']).toFixed(2),\n                billingAddress = quote.billingAddress(),\n                shippingAddress = quote.shippingAddress(),\n                setup3d;\n\n            // Handle billing address region code\n            if (billingAddress.regionCode == null) {\n                billingAddress.regionCode = undefined;\n            }\n            if (billingAddress.regionCode !== undefined && billingAddress.regionCode.length > 2) {\n                billingAddress.regionCode = undefined;\n            }\n\n            // Handle shipping address region code\n            if (!quote.isVirtual()) {\n                if (shippingAddress.regionCode == null) {\n                    shippingAddress.regionCode = undefined;\n                }\n                if (shippingAddress.regionCode !== undefined && shippingAddress.regionCode.length > 2) {\n                    shippingAddress.regionCode = undefined;\n                }\n            }\n\n            // No 3d secure if using CVV verification on vaulted cards\n            if (quote.paymentMethod().method.indexOf('braintree_cc_vault_') !== -1) {\n                if (this.config.useCvvVault === true) {\n                    state.resolve();\n                    return state.promise();\n                }\n            }\n\n            if (!this.isAmountAvailable(totalAmount) || !this.isCountryAvailable(billingAddress.countryId)) {\n                state.resolve();\n                return state.promise();\n            }\n\n            fullScreenLoader.startLoader();\n\n            setup3d = function (client) {\n                threeDSecure.create({\n                    version: 2,\n                    client: client\n                }, function (threeDSecureErr, threeDSecureInstance) {\n                    if (threeDSecureErr) {\n                        fullScreenLoader.stopLoader();\n                        return state.reject($t('Please try again with another form of payment.'));\n                    }\n\n                    let threeDSContainer = document.createElement('div'),\n                        tdMask = document.createElement('div'),\n                        tdFrame = document.createElement('div'),\n                        tdBody = document.createElement('div'),\n                        threeDSecureParameters;\n\n                    threeDSContainer.className = 'braintree-three-d-modal';\n                    tdMask.className = 'bt-mask';\n                    tdFrame.className = 'bt-modal-frame';\n                    tdBody.className = 'bt-modal-body';\n\n                    tdFrame.appendChild(tdBody);\n                    threeDSContainer.appendChild(tdMask);\n                    threeDSContainer.appendChild(tdFrame);\n\n                    threeDSecureParameters = {\n                        amount: totalAmount,\n                        nonce: context.paymentMethodNonce,\n                        bin: context.creditCardBin,\n                        collectDeviceData: true,\n                        challengeRequested: self.getChallengeRequested(),\n                        cardAddChallengeRequested: self.getCardAddChallengeRequested(),\n                        billingAddress: {\n                            givenName: escapeNonAsciiCharacters(billingAddress.firstname),\n                            surname: escapeNonAsciiCharacters(billingAddress.lastname),\n                            phoneNumber: billingAddress.telephone !== null\n                                ? removeNonDigitCharacters(billingAddress.telephone)\n                                : billingAddress.telephone,\n                            streetAddress: billingAddress.street[0],\n                            extendedAddress: billingAddress.street[1],\n                            locality: billingAddress.city,\n                            region: billingAddress.regionCode,\n                            postalCode: billingAddress.postcode,\n                            countryCodeAlpha2: billingAddress.countryId\n                        },\n                        additionalInformation: {\n                            ipAddress: self.getIpAddress()\n                        },\n                        onLookupComplete: function (data, next) {\n                            next();\n                        },\n                        addFrame: function (err, iframe) {\n                            fullScreenLoader.stopLoader();\n\n                            if (err) {\n                                console.log('Unable to verify card over 3D Secure', err);\n                                return state.reject($t('Please try again with another form of payment.'));\n                            }\n\n                            tdBody.appendChild(iframe);\n                            document.body.appendChild(threeDSContainer);\n                        },\n                        removeFrame: function () {\n                            fullScreenLoader.startLoader();\n                            document.body.removeChild(threeDSContainer);\n                        }\n                    };\n\n                    if (context.hasOwnProperty('email') && context.email !== null) {\n                        threeDSecureParameters.email = context.email;\n                    }\n\n                    if (!quote.isVirtual()) {\n                        threeDSecureParameters.additionalInformation = {\n                            shippingGivenName: escapeNonAsciiCharacters(shippingAddress.firstname),\n                            shippingSurname: escapeNonAsciiCharacters(shippingAddress.lastname),\n                            shippingAddress: {\n                                streetAddress: shippingAddress.street[0],\n                                extendedAddress: shippingAddress.street[1],\n                                locality: shippingAddress.city,\n                                region: shippingAddress.regionCode,\n                                postalCode: shippingAddress.postcode,\n                                countryCodeAlpha2: shippingAddress.countryId\n                            },\n                            shippingPhone: shippingAddress.telephone !== null\n                                ? removeNonDigitCharacters(shippingAddress.telephone)\n                                : shippingAddress.telephone,\n                            ipAddress: threeDSecureParameters.additionalInformation.ipAddress\n                        }\n                    }\n\n                    threeDSecureInstance.verifyCard(threeDSecureParameters, function (err, response) {\n                        fullScreenLoader.stopLoader();\n\n                        if (err) {\n                            console.error('3DSecure validation failed', err);\n                            if (err.code === 'THREEDS_LOOKUP_VALIDATION_ERROR') {\n                                let errorMessage = err.details.originalError.details.originalError.error.message,\n                                    error = self.checkBillingLineLengths(errorMessage, billingAddress, shippingAddress);\n\n                                return error ? state.reject(error) : state.reject($t(errorMessage));\n                            }\n\n                            return state.reject($t('Please try again with another form of payment.'));\n                        }\n\n                        let liability = {\n                            shifted: response.liabilityShifted,\n                            shiftPossible: response.liabilityShiftPossible\n                        };\n\n                        if (liability.shifted || !liability.shifted && !liability.shiftPossible) {\n                            context.paymentMethodNonce = response.nonce;\n                            state.resolve();\n                        } else {\n                            state.reject($t('Please try again with another form of payment.'));\n                        }\n                    });\n                });\n            };\n\n            if (!clientInstance) {\n                require(['PayPal_Braintree/js/view/payment/method-renderer/cc-form'], function (c) {\n                    let config = c.extend({\n                        defaults: {\n                            clientConfig: {\n                                onReady: function () {}\n                            }\n                        }\n                    });\n\n                    braintree.setConfig(config.defaults.clientConfig);\n                    braintree.setup(setup3d);\n                });\n            } else {\n                setup3d(clientInstance);\n            }\n\n            return state.promise();\n        },\n\n        /**\n         * Check minimal amount for 3d secure activation\n         * @param {Number} amount\n         * @returns {Boolean}\n         */\n        isAmountAvailable: function (amount) {\n            amount = parseFloat(amount.toString());\n\n            return amount >= this.config.thresholdAmount;\n        },\n\n        /**\n         * Check if current country is available for 3d secure\n         * @param {String} countryId\n         * @returns {Boolean}\n         */\n        isCountryAvailable: function (countryId) {\n            let key,\n                specificCountries = this.config.specificCountries;\n\n            // all countries are available\n            if (!specificCountries.length) {\n                return true;\n            }\n\n            for (key in specificCountries) {\n                if (countryId === specificCountries[key]) {\n                    return true;\n                }\n            }\n\n            return false;\n        },\n\n        /**\n         * Get the challenge requested config\n         * it will only be returned TRUE when Vault is disabled(FALSE)\n         * and 'PaymentTokenEnabler' is set to FALSE.\n         *\n         * @returns {Boolean}\n         */\n        getChallengeRequested: function () {\n            if (vaultEnablerModel.isVaultEnabled() && vaultEnablerModel.isActivePaymentTokenEnabler()) {\n                return false;\n            }\n            return this.config.challengeRequested;\n        },\n\n        /**\n         * This parameter will be passed as TRUE when\n         * Vault is enabled(TRUE) and 'PaymentTokenEnabler'\n         * is set to TRUE.\n         *\n         * @returns {boolean}\n         */\n        getCardAddChallengeRequested: function () {\n            if (vaultEnablerModel.isVaultEnabled() && vaultEnablerModel.isActivePaymentTokenEnabler()) {\n                return true;\n            }\n            return false;\n        },\n\n        /**\n         * Get the Customer's IP Address\n         *\n         * @returns {*}\n         */\n        getIpAddress: function () {\n            return this.config.ipAddress;\n        }\n    };\n});\n","PayPal_Braintree/js/view/payment/lpm.js":"define(\n    [\n        'uiComponent',\n        'Magento_Checkout/js/model/payment/renderer-list'\n    ],\n    function (\n        Component,\n        rendererList\n    ) {\n        'use strict';\n\n        rendererList.push(\n            {\n                type: 'braintree_local_payment',\n                component: 'PayPal_Braintree/js/view/payment/method-renderer/lpm'\n            }\n        );\n\n        return Component.extend({});\n    }\n);\n","PayPal_Braintree/js/view/payment/braintree.js":"/**\n * Copyright \u00a9 Magento, Inc. All rights reserved.\n * See COPYING.txt for license details.\n */\n/*browser:true*/\ndefine([\n    'uiComponent',\n    'Magento_Checkout/js/model/payment/renderer-list',\n    'Magento_Customer/js/customer-data',\n    'Magento_Ui/js/model/messageList'\n], function (Component, rendererList, customerData, globalMessageList) {\n    'use strict';\n\n    let config = window.checkoutConfig.payment,\n        braintreeType = 'braintree',\n        payPalType = 'braintree_paypal',\n        braintreeAchDirectDebit = 'braintree_ach_direct_debit',\n        braintreeVenmo = 'braintree_venmo',\n        braintreeLocalPayment = 'braintree_local_payment';\n\n    if (config[braintreeType] && config[braintreeType].isActive && config[braintreeType].clientToken) {\n        rendererList.push({\n            type: braintreeType,\n            component: 'PayPal_Braintree/js/view/payment/method-renderer/hosted-fields'\n        });\n    }\n\n    if (config[payPalType] && config[payPalType].isActive) {\n        rendererList.push({\n            type: payPalType,\n            component: 'PayPal_Braintree/js/view/payment/method-renderer/paypal'\n        });\n    }\n\n    if (config[braintreeVenmo] && config[braintreeVenmo].isAllowed && config[braintreeVenmo].clientToken) {\n        rendererList.push({\n            type: braintreeVenmo,\n            component: 'PayPal_Braintree/js/view/payment/method-renderer/venmo'\n        });\n    }\n\n    if (config[braintreeAchDirectDebit] && config[braintreeAchDirectDebit].isActive\n        && config[braintreeAchDirectDebit].clientToken) {\n        rendererList.push({\n            type: braintreeAchDirectDebit,\n            component: 'PayPal_Braintree/js/view/payment/method-renderer/ach'\n        });\n    }\n\n    if (config[braintreeLocalPayment] && config[braintreeLocalPayment].clientToken) {\n        rendererList.push({\n            type: braintreeLocalPayment,\n            component: 'PayPal_Braintree/js/view/payment/method-renderer/lpm'\n        });\n    }\n\n    /** Add view logic here if needed */\n    return Component.extend({\n        initialize: function () {\n            this._super();\n\n            let braintreeData = customerData.get('braintree')(),\n                errors = braintreeData.errors || [];\n\n            errors.forEach(function (error) {\n                globalMessageList.addErrorMessage({ 'message': error });\n            });\n\n            customerData.set('braintree', { errors: [] });\n\n            return this;\n        }\n    });\n});\n","PayPal_Braintree/js/view/payment/adapter.js":"/**\n * Copyright 2013-2017 Magento, Inc. All rights reserved.\n * See COPYING.txt for license details.\n */\n/*browser:true*/\ndefine([\n    'jquery',\n    'braintree',\n    'braintreeDataCollector',\n    'braintreeHostedFields',\n    'Magento_Checkout/js/model/full-screen-loader',\n    'Magento_Ui/js/model/messageList',\n    'mage/translate'\n], function ($, client, dataCollector, hostedFields, fullScreenLoader, globalMessageList, $t) {\n    'use strict';\n\n    return {\n        apiClient: null,\n        config: {},\n        checkout: null,\n        deviceData: null,\n        clientInstance: null,\n        hostedFieldsInstance: null,\n        paypalInstance: null,\n        code: 'braintree',\n\n        /**\n         * {Object}\n         */\n        events: {\n            onClick: null,\n            onCancel: null,\n            onError: null\n        },\n\n        /**\n         * Get Braintree api client\n         * @returns {Object}\n         */\n        getApiClient: function () {\n            return this.clientInstance;\n        },\n\n        /**\n         * Set configuration\n         * @param {Object} config\n         */\n        setConfig: function (config) {\n            this.config = config;\n        },\n\n        /**\n         * Get payment name\n         * @returns {String}\n         */\n        getCode: function () {\n            if (window.checkoutConfig.payment[this.code]) {\n                return this.code;\n            }\n            return 'braintree_paypal';\n\n        },\n\n        /**\n         * Get client token\n         * @returns {String|*}\n         */\n        getClientToken: function () {\n            return window.checkoutConfig.payment[this.getCode()].clientToken;\n        },\n\n        /**\n         * @returns {String}\n         */\n        getEnvironment: function () {\n            return window.checkoutConfig.payment[this.getCode()].environment;\n        },\n\n        getCurrentCode: function (paypalType = null) {\n            var code = 'braintree_paypal';\n\n            if (paypalType !== 'paypal') {\n                code = code + '_' + paypalType;\n            }\n            return code;\n        },\n\n        /**\n         * @returns {String}\n         */\n        getColor: function (paypalType = null) {\n            return window.checkoutConfig.payment[this.getCurrentCode(paypalType)].style.color;\n        },\n\n        /**\n         * @returns {String}\n         */\n        getShape: function (paypalType = null) {\n            return window.checkoutConfig.payment[this.getCurrentCode(paypalType)].style.shape;\n        },\n\n        /**\n         * @returns {String}\n         */\n        getLabel: function (paypalType = null) {\n            return window.checkoutConfig.payment[this.getCurrentCode(paypalType)].style.label;\n        },\n\n        /**\n         * @returns {String}\n         */\n        getBranding: function () {\n            return null;\n        },\n\n        /**\n         * @returns {String}\n         */\n        getFundingIcons: function () {\n            return null;\n        },\n\n        /**\n         * @returns {String}\n         */\n        getDisabledFunding: function () {\n            return window.checkoutConfig.payment[this.getCode()].disabledFunding;\n        },\n\n        /**\n         * Show error message\n         *\n         * @param {String} errorMessage\n         */\n        showError: function (errorMessage) {\n            globalMessageList.addErrorMessage({\n                message: errorMessage\n            });\n            fullScreenLoader.stopLoader(true);\n        },\n\n        /**\n         * Disable submit button\n         */\n        disableButton: function () {\n            // stop any previous shown loaders\n            fullScreenLoader.stopLoader(true);\n            fullScreenLoader.startLoader();\n            $('[data-button=\"place\"]').attr('disabled', 'disabled');\n        },\n\n        /**\n         * Enable submit button\n         */\n        enableButton: function () {\n            $('[data-button=\"place\"]').removeAttr('disabled');\n            fullScreenLoader.stopLoader();\n        },\n\n        /**\n         * Has PayPal been init'd already\n         */\n        getPayPalInstance: function () {\n            if (typeof this.config.paypalInstance !== 'undefined' && this.config.paypalInstance) {\n                return this.config.paypalInstance;\n            }\n\n            return null;\n        },\n\n        setPayPalInstance: function (val) {\n            this.config.paypalInstance = val;\n        },\n\n        /**\n         * Setup Braintree SDK\n         *\n         * @param {Function|null} callback\n         */\n        setup: function (callback = null) {\n            if (!this.getClientToken()) {\n                this.showError($t('Sorry, but something went wrong.'));\n                return;\n            }\n\n            if (this.clientInstance) {\n                if (typeof this.config.onReady === 'function') {\n                    this.config.onDeviceDataReceived(this.deviceData);\n                    this.config.onReady(this);\n                }\n\n                if (typeof callback === 'function') {\n                    callback(this.clientInstance);\n                }\n                return;\n            }\n\n            client.create({\n                authorization: this.getClientToken()\n            }, function (clientErr, clientInstance) {\n                if (clientErr) {\n                    console.error('Braintree Setup Error', clientErr);\n                    return this.showError('Sorry, but something went wrong. Please contact the store owner.');\n                }\n\n                let options = {\n                    client: clientInstance\n                };\n\n                if (typeof this.config.dataCollector === 'object'\n                    && typeof this.config.dataCollector.paypal === 'boolean'\n                ) {\n                    options.paypal = true;\n                }\n\n                this.clientInstance = clientInstance;\n\n                if (typeof this.config.onReady === 'function') {\n                    this.config.onReady(this);\n                }\n\n                dataCollector.create(options, function (err, dataCollectorInstance) {\n                    if (err) {\n                        return console.log(err);\n                    }\n\n                    this.deviceData = dataCollectorInstance.deviceData;\n                    this.config.onDeviceDataReceived(this.deviceData);\n\n                    if (typeof callback === 'function') {\n                        callback(this.clientInstance);\n                    }\n                }.bind(this));\n            }.bind(this));\n        },\n\n        /**\n         * Setup hosted fields instance\n         */\n        setupHostedFields: function () {\n            var self = this;\n\n            if (this.hostedFieldsInstance) {\n                this.hostedFieldsInstance.teardown(function () {\n                    this.hostedFieldsInstance = null;\n                    this.setupHostedFields();\n                }.bind(this));\n                return;\n            }\n\n            hostedFields.create({\n                client: this.clientInstance,\n                fields: this.config.hostedFields,\n                styles: this.config.styles\n            }, function (createErr, hostedFieldsInstance) {\n                if (createErr) {\n                    let error = 'Braintree hosted fields could not be initialized. Please contact the store owner.';\n\n                    self.showError($t(error));\n                    console.error('Braintree hosted fields error', createErr);\n                    return;\n                }\n\n                this.config.onInstanceReady(hostedFieldsInstance);\n                this.hostedFieldsInstance = hostedFieldsInstance;\n            }.bind(this));\n        },\n\n        tokenizeHostedFields: function () {\n            this.hostedFieldsInstance.tokenize({}, function (tokenizeErr, payload) {\n                if (tokenizeErr) {\n                    switch (tokenizeErr.code) {\n                    case 'HOSTED_FIELDS_FIELDS_EMPTY':\n                        // occurs when none of the fields are filled in\n                        console.error('All fields are empty! Please fill out the form.');\n                        break;\n                    case 'HOSTED_FIELDS_FIELDS_INVALID':\n                        // occurs when certain fields do not pass client side validation\n                        console.error('Some fields are invalid:', tokenizeErr.details.invalidFieldKeys);\n                        break;\n                    case 'HOSTED_FIELDS_TOKENIZATION_FAIL_ON_DUPLICATE':\n                        // occurs when:\n                        //   * the client token used for client authorization was generated\n                        //     with a customer ID and the fail on duplicate payment method\n                        //     option is set to true\n                        //   * the card being tokenized has previously been vaulted (with any customer)\n                        // eslint-disable-next-line\n                            // See: https://developers.braintreepayments.com/reference/request/client-token/generate/#options.fail_on_duplicate_payment_method\n                        console.error('This payment method already exists in your vault.');\n                        break;\n                    case 'HOSTED_FIELDS_TOKENIZATION_CVV_VERIFICATION_FAILED':\n                        // occurs when:\n                        //   * the client token used for client authorization was generated\n                        //     with a customer ID and the verify card option is set to true\n                        //     and you have credit card verification turned on in the Braintree\n                        //     control panel\n                        //   * the cvv does not pass verfication\n                        //   (developers.braintreepayments.com/reference/general/testing/#avs-and-cvv/cid-responses)\n                        // eslint-disable-next-line\n                            // See: developers.braintreepayments.com/reference/request/client-token/generate/#options.verify_card\n                        console.error('CVV did not pass verification');\n                        break;\n                    case 'HOSTED_FIELDS_FAILED_TOKENIZATION':\n                        // occurs for any other tokenization error on the server\n                        console.error('Tokenization failed server side. Is the card valid?');\n                        break;\n                    case 'HOSTED_FIELDS_TOKENIZATION_NETWORK_ERROR':\n                        // occurs when the Braintree gateway cannot be contacted\n                        console.error('Network error occurred when tokenizing.');\n                        break;\n                    default:\n                        console.error('Something bad happened!', tokenizeErr);\n                    }\n                } else {\n                    this.config.onPaymentMethodReceived(payload);\n                }\n            }.bind(this));\n        }\n    };\n});\n\n","PayPal_Braintree/js/view/payment/validator-handler.js":"/**\n * Copyright 2013-2017 Magento, Inc. All rights reserved.\n * See COPYING.txt for license details.\n */\n/*browser:true*/\n\ndefine([\n    'jquery',\n    'Magento_Ui/js/model/messageList',\n    'PayPal_Braintree/js/view/payment/3d-secure',\n    'Magento_Checkout/js/model/full-screen-loader'\n], function ($, globalMessageList, verify3DSecure, fullScreenLoader) {\n    'use strict';\n\n    return {\n        validators: [],\n\n        /**\n         * Get payment config\n         * @returns {Object}\n         */\n        getConfig: function () {\n            return window.checkoutConfig.payment;\n        },\n\n        /**\n         * Init list of validators\n         */\n        initialize: function () {\n            let config = this.getConfig();\n\n            if (config[verify3DSecure.getCode()].enabled) {\n                verify3DSecure.setConfig(config[verify3DSecure.getCode()]);\n                this.add(verify3DSecure);\n            }\n        },\n\n        /**\n         * Add new validator\n         * @param {Object} validator\n         */\n        add: function (validator) {\n            this.validators.push(validator);\n        },\n\n        /**\n         * Run pull of validators\n         * @param {Object} context\n         * @param {Function} callback\n         */\n        validate: function (context, callback, errorCallback) {\n            var self = this,\n                deferred;\n\n            // no available validators\n            if (!self.validators.length) {\n                callback();\n\n                return;\n            }\n\n            // get list of deferred validators\n            deferred = $.map(self.validators, function (current) {\n                return current.validate(context);\n            });\n\n            $.when.apply($, deferred)\n                .done(function () {\n                    callback();\n                }).fail(function (error) {\n                    errorCallback();\n                    self.showError(error);\n                });\n        },\n\n        /**\n         * Show error message\n         * @param {String} errorMessage\n         */\n        showError: function (errorMessage) {\n            globalMessageList.addErrorMessage({\n                message: errorMessage\n            });\n            fullScreenLoader.stopLoader(true);\n        }\n    };\n});\n","PayPal_Braintree/js/view/payment/ach.js":"define(\n    [\n        'uiComponent',\n        'Magento_Checkout/js/model/payment/renderer-list'\n    ],\n    function (\n        Component,\n        rendererList\n    ) {\n        'use strict';\n\n        rendererList.push(\n            {\n                type: 'braintree_ach_direct_debit',\n                component: 'PayPal_Braintree/js/view/payment/method-renderer/ach'\n            }\n        );\n\n        return Component.extend({});\n    }\n);\n","PayPal_Braintree/js/view/payment/method-renderer/venmo.js":"define(\n    [\n        'Magento_Checkout/js/view/payment/default',\n        'braintree',\n        'braintreeDataCollector',\n        'braintreeVenmo',\n        'PayPal_Braintree/js/form-builder',\n        'Magento_Ui/js/model/messageList',\n        'Magento_Checkout/js/model/full-screen-loader',\n        'Magento_Checkout/js/model/payment/additional-validators',\n        'mage/translate',\n        'Magento_Vault/js/view/payment/vault-enabler',\n        'underscore'\n    ],\n    function (\n        Component,\n        braintree,\n        dataCollector,\n        venmo,\n        formBuilder,\n        messageList,\n        fullScreenLoader,\n        additionalValidators,\n        $t,\n        VaultEnabler,\n        _\n    ) {\n        'use strict';\n\n        return Component.extend({\n            defaults: {\n                deviceData: null,\n                paymentMethodNonce: null,\n                template: 'PayPal_Braintree/payment/venmo',\n                venmoInstance: null,\n                vaultEnabler: null\n            },\n\n            clickVenmoBtn: function () {\n                var self = this;\n\n                if (!additionalValidators.validate()) {\n                    return false;\n                }\n\n                if (!this.venmoInstance) {\n                    this.setErrorMsg($t('Venmo not initialized, please try reloading.'));\n                    return;\n                }\n\n                this.venmoInstance.tokenize(function (tokenizeErr, payload) {\n                    if (tokenizeErr) {\n                        if (tokenizeErr.code === 'VENMO_CANCELED') {\n                            self.setErrorMsg($t('Venmo app is not available or the payment flow was cancelled.'));\n                        } else if (tokenizeErr.code === 'VENMO_APP_CANCELED') {\n                            self.setErrorMsg($t('Venmo payment flow cancelled.'));\n                        } else {\n                            self.setErrorMsg(tokenizeErr.message);\n                        }\n                    } else {\n                        self.handleVenmoSuccess(payload);\n                    }\n                });\n            },\n\n            collectDeviceData: function (clientInstance, callback) {\n                var self = this;\n\n                dataCollector.create({\n                    client: clientInstance,\n                    paypal: true\n                }, function (dataCollectorErr, dataCollectorInstance) {\n                    if (dataCollectorErr) {\n                        return;\n                    }\n                    self.deviceData = dataCollectorInstance.deviceData;\n                    callback();\n                });\n            },\n\n            getClientToken: function () {\n                return window.checkoutConfig.payment[this.getCode()].clientToken;\n            },\n\n            getCode: function () {\n                return 'braintree_venmo';\n            },\n\n            getData: function () {\n                let data = {\n                    'method': this.getCode(),\n                    'additional_data': {\n                        'payment_method_nonce': this.paymentMethodNonce,\n                        'device_data': this.deviceData\n                    }\n                };\n\n                data['additional_data'] = _.extend(data['additional_data'], this.additionalData);\n                this.vaultEnabler.visitAdditionalData(data);\n\n                return data;\n            },\n\n            getPaymentMarkSrc: function () {\n                return window.checkoutConfig.payment[this.getCode()].paymentMarkSrc;\n            },\n\n            getTitle: function () {\n                return 'Venmo';\n            },\n\n            handleVenmoSuccess: function (payload) {\n                this.setPaymentMethodNonce(payload.nonce);\n                this.placeOrder();\n            },\n\n            initialize: function () {\n                var self = this;\n\n                this._super();\n                this.vaultEnabler = new VaultEnabler();\n                this.vaultEnabler.setPaymentCode(this.getVaultCode());\n\n                this.vaultEnabler.isActivePaymentTokenEnabler.subscribe(function () {\n                    self.venmoInstance.teardown(function () {\n                        self.initVenmo();\n                    });\n\n                });\n                this.initVenmo();\n                return this;\n            },\n\n            isAllowed: function () {\n                return window.checkoutConfig.payment[this.getCode()].isAllowed;\n            },\n\n            setErrorMsg: function (message) {\n                messageList.addErrorMessage({\n                    message: message\n                });\n            },\n\n            setPaymentMethodNonce: function (nonce) {\n                this.paymentMethodNonce = nonce;\n            },\n\n            setVenmoInstance: function (instance) {\n                this.venmoInstance = instance;\n            },\n\n            isVaultEnabled: function () {\n                return this.vaultEnabler.isVaultEnabled();\n            },\n\n            /**\n             * @returns {String}\n             */\n            getVaultCode: function () {\n                return window.checkoutConfig.payment[this.getCode()].vaultCode;\n            },\n\n            getPaymentMethodUsage: function () {\n                return this.vaultEnabler.isActivePaymentTokenEnabler()\n                    ? 'multi_use'\n                    : 'single_use';\n            },\n\n            initVenmo: function () {\n                var self = this;\n\n                braintree.create({\n                    authorization: self.getClientToken()\n                }, function (clientError, clientInstance) {\n                    if (clientError) {\n                        this.setErrorMsg($t('Unable to initialize Braintree Client.'));\n                        return;\n                    }\n\n                    // Collect device data\n                    self.collectDeviceData(clientInstance, function () {\n                        // callback from collectDeviceData\n                        venmo.create({\n                            client: clientInstance,\n                            allowDesktop: true,\n                            allowDesktopWebLogin: true,\n                            mobileWebFallBack: true,\n                            paymentMethodUsage: self.getPaymentMethodUsage(),\n                            allowNewBrowserTab: false\n                        }, function (venmoErr, venmoInstance) {\n                            if (venmoErr) {\n                                self.setErrorMsg($t('Error initializing Venmo: %1').replace('%1', venmoErr));\n                                return;\n                            }\n\n                            if (!venmoInstance.isBrowserSupported()) {\n                                console.log('Browser does not support Venmo');\n                                return;\n                            }\n\n                            self.setVenmoInstance(venmoInstance);\n                        });\n                    });\n                });\n            }\n        });\n    }\n);\n","PayPal_Braintree/js/view/payment/method-renderer/hosted-fields.js":"/**\n * Copyright 2013-2017 Magento, Inc. All rights reserved.\n * See COPYING.txt for license details.\n */\n/*browser:true*/\n\ndefine([\n    'jquery',\n    'PayPal_Braintree/js/view/payment/method-renderer/cc-form',\n    'PayPal_Braintree/js/model/vault-enabler',\n    'PayPal_Braintree/js/validator',\n    'Magento_Checkout/js/model/payment/additional-validators',\n    'mage/translate'\n], function ($, Component, vaultEnablerModel, validator, additionalValidators, $t) {\n    'use strict';\n\n    return Component.extend({\n\n        defaults: {\n            template: 'PayPal_Braintree/payment/form',\n            clientConfig: {\n\n                /**\n                 * {String}\n                 */\n                id: 'co-transparent-form-braintree'\n            },\n            isValidCardNumber: false,\n            isValidExpirationDate: false,\n            isValidCvvNumber: false,\n\n            onInstanceReady: function (instance) {\n                instance.on('validityChange', this.onValidityChange.bind(this));\n                instance.on('cardTypeChange', this.onCardTypeChange.bind(this));\n            }\n        },\n\n        /**\n         * @returns {exports.initialize}\n         */\n        initialize: function () {\n            this._super();\n            this.vaultEnabler = vaultEnablerModel.getVaultEnabler();\n            vaultEnablerModel.setPaymentCode(this.getVaultCode());\n\n            return this;\n        },\n\n        /**\n         * Init config\n         */\n        initClientConfig: function () {\n            this._super();\n\n            this.clientConfig.hostedFields = this.getHostedFields();\n            this.clientConfig.styles = {\n                'input': {\n                    'font-size': '14pt',\n                    'color': '#3A3A3A'\n                },\n                ':focus': {\n                    'color': 'black'\n                },\n                '.valid': {\n                    'color': 'green'\n                },\n                '.invalid': {\n                    'color': 'red'\n                }\n            };\n            this.clientConfig.onInstanceReady = this.onInstanceReady.bind(this);\n        },\n\n        /**\n         * @returns {Object}\n         */\n        getData: function () {\n            var data = this._super();\n\n            vaultEnablerModel.visitAdditionalData(data);\n\n            return data;\n        },\n\n        /**\n         * @returns {Bool}\n         */\n        isVaultEnabled: function () {\n            return vaultEnablerModel.isVaultEnabled();\n        },\n\n        /**\n         * Get Braintree Hosted Fields\n         * @returns {Object}\n         */\n        getHostedFields: function () {\n            var self = this,\n                fields = {\n                    number: {\n                        selector: self.getSelector('cc_number'),\n                        placeholder: $t('4111 1111 1111 1111')\n                    },\n                    expirationDate: {\n                        selector: self.getSelector('expirationDate'),\n                        placeholder: $t('MM/YYYY')\n                    }\n                };\n\n            if (self.hasVerification()) {\n                fields.cvv = {\n                    selector: self.getSelector('cc_cid'),\n                    placeholder: $t('123')\n                };\n            }\n\n            return fields;\n        },\n\n        /**\n         * Triggers on Hosted Field changes\n         * @param {Object} event\n         * @returns {Boolean}\n         */\n        onValidityChange: function (event) {\n            // Handle a change in validation or card type\n            if (event.emittedBy === 'number') {\n                this.selectedCardType(null);\n\n                if (event.cards.length === 1) {\n                    this.isValidCardNumber = event.fields.number.isValid;\n                    this.selectedCardType(\n                        validator.getMageCardType(event.cards[0].type, this.getCcAvailableTypes())\n                    );\n                    this.validateCardType();\n                } else {\n                    this.isValidCardNumber = event.fields.number.isValid;\n                    this.validateCardType();\n                }\n            }\n\n            // Other field validations\n            if (event.emittedBy === 'expirationDate') {\n                this.isValidExpirationDate = event.fields.expirationDate.isValid;\n            }\n            if (event.emittedBy === 'cvv') {\n                this.isValidCvvNumber = event.fields.cvv.isValid;\n            }\n        },\n\n        /**\n         * Triggers on Hosted Field card type changes\n         * @param {Object} event\n         * @returns {Boolean}\n         */\n        onCardTypeChange: function (event) {\n            if (event.cards.length === 1) {\n                this.selectedCardType(\n                    validator.getMageCardType(event.cards[0].type, this.getCcAvailableTypes())\n                );\n            } else {\n                this.selectedCardType(null);\n            }\n        },\n\n        /**\n         * Toggle invalid class on selector\n         * @param selector\n         * @param state\n         * @returns {boolean}\n         */\n        validateField: function (selector, state) {\n            var $selector = $(this.getSelector(selector)),\n                invalidClass = 'braintree-hosted-fields-invalid';\n\n            if (state === true) {\n                $selector.removeClass(invalidClass);\n                return true;\n            }\n\n            $selector.addClass(invalidClass);\n            return false;\n        },\n\n        /**\n         * Validate current credit card type\n         * @returns {Boolean}\n         */\n        validateCardType: function () {\n            return this.validateField(\n                'cc_number',\n                this.isValidCardNumber\n            );\n        },\n\n        /**\n         * Validate current expiry date\n         * @returns {boolean}\n         */\n        validateExpirationDate: function () {\n            return this.validateField(\n                'expirationDate',\n                this.isValidExpirationDate === true\n            );\n        },\n\n        /**\n         * Validate current CVV field\n         * @returns {boolean}\n         */\n        validateCvvNumber: function () {\n            var self = this;\n\n            if (self.hasVerification() === false) {\n                return true;\n            }\n\n            return this.validateField(\n                'cc_cid',\n                this.isValidCvvNumber === true\n            );\n        },\n\n        /**\n         * Validate all fields\n         * @returns {boolean}\n         */\n        validateFormFields: function () {\n            return (this.validateCardType() && this.validateExpirationDate() && this.validateCvvNumber()) === true;\n        },\n\n        /**\n         * Trigger order placing\n         */\n        placeOrderClick: function () {\n            if (this.validateFormFields() && additionalValidators.validate()) {\n                this.placeOrder();\n            }\n        },\n\n        /**\n         * @returns {String}\n         */\n        getVaultCode: function () {\n            return window.checkoutConfig.payment[this.getCode()].ccVaultCode;\n        }\n    });\n});\n","PayPal_Braintree/js/view/payment/method-renderer/lpm.js":"define(\n    [\n        'Magento_Checkout/js/view/payment/default',\n        'ko',\n        'underscore',\n        'jquery',\n        'braintree',\n        'braintreeLpm',\n        'PayPal_Braintree/js/form-builder',\n        'Magento_Ui/js/model/messageList',\n        'Magento_Checkout/js/action/select-billing-address',\n        'PayPal_Braintree/js/helper/remove-non-digit-characters',\n        'Magento_Checkout/js/model/full-screen-loader',\n        'Magento_Checkout/js/model/quote',\n        'Magento_Checkout/js/model/payment/additional-validators',\n        'mage/url',\n        'mage/translate'\n    ],\n    function (\n        Component,\n        ko,\n        _,\n        $,\n        braintree,\n        lpm,\n        formBuilder,\n        messageList,\n        selectBillingAddress,\n        removeNonDigitCharacters,\n        fullScreenLoader,\n        quote,\n        additionalValidators,\n        url,\n        $t\n    ) {\n        'use strict';\n\n        return Component.extend({\n            defaults: {\n                code: 'braintree_local_payment',\n                paymentMethodsAvailable: ko.observable(false),\n                paymentMethodNonce: null,\n                template: 'PayPal_Braintree/payment/lpm'\n            },\n\n            clickPaymentBtn: function (method) {\n                let self = this;\n\n                if (additionalValidators.validate()) {\n                    fullScreenLoader.startLoader();\n\n                    braintree.create({\n                        authorization: self.getClientToken()\n                    }, function (clientError, clientInstance) {\n                        if (clientError) {\n                            self.setErrorMsg($t('Unable to initialize Braintree Client.'));\n                            fullScreenLoader.stopLoader();\n                            return;\n                        }\n\n                        lpm.create({\n                            client: clientInstance,\n                            merchantAccountId: self.getMerchantAccountId()\n                        }, function (lpmError, lpmInstance) {\n                            if (lpmError) {\n                                self.setErrorMsg(lpmError);\n                                fullScreenLoader.stopLoader();\n                                return;\n                            }\n\n                            lpmInstance.startPayment({\n                                amount: self.getAmount(),\n                                currencyCode: self.getCurrencyCode(),\n                                email: self.getCustomerDetails().email,\n                                phone: removeNonDigitCharacters(_.get(self.getCustomerDetails(), 'phone', '')),\n                                givenName: self.getCustomerDetails().firstName,\n                                surname: self.getCustomerDetails().lastName,\n                                shippingAddressRequired: !quote.isVirtual(),\n                                address: self.getAddress(),\n                                paymentType: method,\n                                onPaymentStart: function (data, start) {\n                                    start();\n                                },\n                                // This is a required option, however it will apparently never be used in the current\n                                // payment flow. Therefore, both values are set to allow the payment flow to continue,\n                                // rather than error out.\n                                fallback: {\n                                    url: self.getFallbackUrl(),\n                                    buttonText: self.getFallbackButtonText()\n                                }\n                            }, function (startPaymentError, payload) {\n                                fullScreenLoader.stopLoader();\n                                if (startPaymentError) {\n                                    switch (startPaymentError.code) {\n                                    case 'LOCAL_PAYMENT_POPUP_CLOSED':\n                                        self.setErrorMsg($t('Local Payment popup was closed unexpectedly.'));\n                                        break;\n                                    case 'LOCAL_PAYMENT_WINDOW_OPEN_FAILED':\n                                        self.setErrorMsg($t('Local Payment popup failed to open.'));\n                                        break;\n                                    case 'LOCAL_PAYMENT_WINDOW_CLOSED':\n                                        self.setErrorMsg($t('Local Payment popup was closed. Payment cancelled.'));\n                                        break;\n                                    default:\n                                        self.setErrorMsg('Error! ' + startPaymentError);\n                                        break;\n                                    }\n                                } else {\n                                    // Send the nonce to your server to create a transaction\n                                    self.setPaymentMethodNonce(payload.nonce);\n                                    self.placeOrder();\n                                }\n                            });\n                        });\n                    });\n                }\n            },\n\n            getAddress: function () {\n                let shippingAddress = quote.shippingAddress();\n\n                if (quote.isVirtual()) {\n                    return {\n                        countryCode: shippingAddress.countryId\n                    };\n                }\n\n                return {\n                    streetAddress: shippingAddress.street[0],\n                    extendedAddress: shippingAddress.street[1],\n                    locality: shippingAddress.city,\n                    postalCode: shippingAddress.postcode,\n                    region: shippingAddress.region,\n                    countryCode: shippingAddress.countryId\n                };\n            },\n\n            getAmount: function () {\n                return quote.totals()['base_grand_total'].toString();\n            },\n\n            getBillingAddress: function () {\n                return quote.billingAddress();\n            },\n\n            getClientToken: function () {\n                return window.checkoutConfig.payment[this.getCode()].clientToken;\n            },\n\n            getCode: function () {\n                return this.code;\n            },\n\n            getCurrencyCode: function () {\n                return quote.totals()['base_currency_code'];\n            },\n\n            getCustomerDetails: function () {\n                let billingAddress = quote.billingAddress();\n\n                return {\n                    firstName: billingAddress.firstname,\n                    lastName: billingAddress.lastname,\n                    phone: billingAddress.telephone !== null ? billingAddress.telephone : '',\n                    email: typeof quote.guestEmail === 'string'\n                        ? quote.guestEmail : window.checkoutConfig.customerData.email\n                };\n            },\n\n            getData: function () {\n                let data = {\n                    'method': this.getCode(),\n                    'additional_data': {\n                        'payment_method_nonce': this.paymentMethodNonce\n                    }\n                };\n\n                data['additional_data'] = _.extend(data['additional_data'], this.additionalData);\n\n                return data;\n            },\n\n            getMerchantAccountId: function () {\n                return window.checkoutConfig.payment[this.getCode()].merchantAccountId;\n            },\n\n            getPaymentMethod: function (method) {\n                let methods = this.getPaymentMethods();\n\n                for (let i = 0; i < methods.length; i++) {\n                    if (methods[i].method === method) {\n                        return methods[i];\n                    }\n                }\n            },\n\n            /**\n             * Get allowed local payment methods\n             *\n             * @returns {*}\n             */\n            getPaymentMethods: function () {\n                return window.checkoutConfig.payment[this.getCode()].allowedMethods;\n            },\n\n            /**\n             * Get payment icons\n             *\n             * @returns {*}\n             */\n            getPaymentMarkSrc: function () {\n                return window.checkoutConfig.payment[this.getCode()].paymentIcons;\n            },\n\n            /**\n             * Get title\n             *\n             * @returns {*}\n             */\n            getTitle: function () {\n                return window.checkoutConfig.payment[this.getCode()].title;\n            },\n\n            /**\n             * Get fallback url\n             *\n             * @returns {String}\n             */\n            getFallbackUrl: function () {\n                return window.checkoutConfig.payment[this.getCode()].fallbackUrl;\n            },\n\n            /**\n             * Get fallback button text\n             * @returns {String}\n             */\n            getFallbackButtonText: function () {\n                return window.checkoutConfig.payment[this.getCode()].fallbackButtonText;\n            },\n\n            /**\n             * Initialize\n             *\n             * @returns {*}\n             */\n            initialize: function () {\n                this._super();\n                return this;\n            },\n\n            /**\n             * Is payment method active?\n             *\n             * @returns {boolean}\n             */\n            isActive: function () {\n                let address = quote.billingAddress() || quote.shippingAddress(),\n                    methods = this.getPaymentMethods();\n\n                for (let i = 0; i < methods.length; i++) {\n                    if (methods[i].countries.includes(address.countryId)) {\n                        return true;\n                    }\n                }\n\n                return false;\n            },\n\n            /**\n             * Is country and currency valid?\n             *\n             * @param method\n             * @returns {boolean}\n             */\n            isValidCountryAndCurrency: function (method) {\n                let address = quote.billingAddress(),\n                    countryId = address.countryId,\n                    quoteCurrency = quote.totals()['base_currency_code'],\n                    paymentMethodDetails = this.getPaymentMethod(method);\n\n                if (!address) {\n                    this.paymentMethodsAvailable(false);\n                    return false;\n                }\n\n                if (countryId !== 'GB' && paymentMethodDetails.countries.includes(countryId)\n                    && (quoteCurrency === 'EUR' || quoteCurrency === 'PLN') || countryId === 'GB'\n                    && paymentMethodDetails.countries.includes(countryId) && quoteCurrency === 'GBP') {\n                    this.paymentMethodsAvailable(true);\n                    return true;\n                }\n\n                return false;\n            },\n\n            /**\n             * Set error message\n             *\n             * @param message\n             */\n            setErrorMsg: function (message) {\n                messageList.addErrorMessage({\n                    message: message\n                });\n            },\n\n            /**\n             * Set payment method nonce\n             *\n             * @param nonce\n             */\n            setPaymentMethodNonce: function (nonce) {\n                this.paymentMethodNonce = nonce;\n            },\n\n            /**\n             * Validate form\n             *\n             * @param form\n             * @returns {*|jQuery}\n             */\n            validateForm: function (form) {\n                return $(form).validation() && $(form).validation('isValid');\n            }\n        });\n    }\n);\n","PayPal_Braintree/js/view/payment/method-renderer/vault.js":"/**\n * Copyright \u00a9 Magento, Inc. All rights reserved.\n * See COPYING.txt for license details.\n */\n/*browser:true*/\ndefine([\n    'ko',\n    'jquery',\n    'Magento_Vault/js/view/payment/method-renderer/vault',\n    'PayPal_Braintree/js/view/payment/adapter',\n    'Magento_Ui/js/model/messageList',\n    'PayPal_Braintree/js/view/payment/validator-handler',\n    'Magento_Checkout/js/model/payment/additional-validators',\n    'Magento_Checkout/js/model/full-screen-loader',\n    'braintree',\n    'braintreeHostedFields',\n    'mage/url'\n], function (\n    ko,\n    $,\n    VaultComponent,\n    Braintree,\n    globalMessageList,\n    validatorManager,\n    additionalValidators,\n    fullScreenLoader,\n    client,\n    hostedFields,\n    url\n) {\n    'use strict';\n\n    return VaultComponent.extend({\n        defaults: {\n            active: false,\n            hostedFieldsInstance: null,\n            imports: {\n                onActiveChange: 'active'\n            },\n            modules: {\n                hostedFields: '${ $.parentName }.braintree'\n            },\n            template: 'PayPal_Braintree/payment/cc/vault',\n            updatePaymentUrl: url.build('braintree/payment/updatepaymentmethod'),\n            vaultedCVV: ko.observable(''),\n            validatorManager: validatorManager,\n            isValidCvv: false,\n            onInstanceReady: function (instance) {\n                instance.on('validityChange', this.onValidityChange.bind(this));\n            }\n        },\n\n        /**\n         * Event fired by Braintree SDK whenever input value length matches the validation length.\n         * In the case of a CVV, this is 3, or 4 for AMEX.\n         *\n         * @param event\n         */\n        onValidityChange: function (event) {\n            if (event.emittedBy === 'cvv') {\n                this.isValidCvv = event.fields.cvv.isValid;\n            }\n        },\n\n        /**\n         * @returns {exports}\n         */\n        initObservable: function () {\n            this._super().observe(['active']);\n            this.validatorManager.initialize();\n            return this;\n        },\n\n        /**\n         * Is payment option active?\n         *\n         * @returns {boolean}\n         */\n        isActive: function () {\n            let active = this.getId() === this.isChecked();\n\n            this.active(active);\n            return active;\n        },\n\n        /**\n         * Fired whenever a payment option is changed.\n         *\n         * @param isActive\n         */\n        onActiveChange: function (isActive) {\n            let self = this;\n\n            if (!isActive) {\n                return;\n            }\n\n            if (self.showCvvVerify()) {\n                if (self.hostedFieldsInstance) {\n                    self.hostedFieldsInstance.teardown(function (teardownError) {\n                        if (teardownError) {\n                            globalMessageList.addErrorMessage({\n                                message: teardownError.message\n                            });\n                        }\n                        self.hostedFieldsInstance = null;\n                        self.initHostedCvvField();\n                    });\n                    return;\n                }\n                self.initHostedCvvField();\n            }\n        },\n\n        /**\n         * Initialize the CVV input field with the Braintree Hosted Fields SDK.\n         */\n        initHostedCvvField: function () {\n            let self = this;\n\n            client.create({\n                authorization: Braintree.getClientToken()\n            }, function (clientError, clientInstance) {\n                if (clientError) {\n                    globalMessageList.addErrorMessage({\n                        message: clientError.message\n                    });\n                }\n                hostedFields.create({\n                    client: clientInstance,\n                    fields: {\n                        cvv: {\n                            selector: '#' + self.getId() + '_cid',\n                            placeholder: '123'\n                        }\n                    }\n                }, function (hostedError, hostedFieldsInstance) {\n                    if (hostedError) {\n                        globalMessageList.addErrorMessage({\n                            message: hostedError.message\n                        });\n                        return;\n                    }\n\n                    self.hostedFieldsInstance = hostedFieldsInstance;\n                    self.onInstanceReady(self.hostedFieldsInstance);\n                });\n            });\n        },\n\n        /**\n         * Return the payment method code.\n         *\n         * @returns {string}\n         */\n        getCode: function () {\n            return 'braintree_cc_vault';\n        },\n\n        /**\n         * Get last 4 digits of card\n         *\n         * @returns {String}\n         */\n        getMaskedCard: function () {\n            return this.details.maskedCC;\n        },\n\n        /**\n         * Get expiration date\n         *\n         * @returns {String}\n         */\n        getExpirationDate: function () {\n            return this.details.expirationDate;\n        },\n\n        /**\n         * Get card type\n         *\n         * @returns {String}\n         */\n        getCardType: function () {\n            return this.details.type;\n        },\n\n        /**\n         * Get card icons\n         *\n         * @param {String} type\n         * @returns {Boolean}\n         */\n        getIcons: function (type) {\n            return window.checkoutConfig.payment.braintree.icons.hasOwnProperty(type) ?\n                window.checkoutConfig.payment.braintree.icons[type]\n                : false;\n        },\n\n        /**\n         * Get show CVV Field\n         *\n         * @returns {Boolean}\n         */\n        showCvvVerify: function () {\n            return window.checkoutConfig.payment[this.code].cvvVerify;\n        },\n\n        /**\n         * Show or hide the error message.\n         *\n         * @param selector\n         * @param state\n         * @returns {boolean}\n         */\n        validateCvv: function (selector, state) {\n            let $selector = $(selector),\n                invalidClass = 'braintree-hosted-fields-invalid';\n\n            if (state === true) {\n                $selector.removeClass(invalidClass);\n                return true;\n            }\n\n            $selector.addClass(invalidClass);\n            return false;\n        },\n\n        /**\n         * Place order\n         */\n        placeOrder: function () {\n            let self = this;\n\n            if (self.showCvvVerify()) {\n                if (!self.validateCvv('#' + self.getId() + '_cid', self.isValidCvv)\n                    || !additionalValidators.validate()) {\n                    return;\n                }\n            } else if (!additionalValidators.validate()) {\n                return;\n            }\n\n            fullScreenLoader.startLoader();\n\n            if (self.showCvvVerify() && typeof self.hostedFieldsInstance !== 'undefined') {\n                self.hostedFieldsInstance.tokenize({}, function (error, payload) {\n                    if (error) {\n                        fullScreenLoader.stopLoader();\n                        globalMessageList.addErrorMessage({\n                            message: error.message\n                        });\n                        return;\n                    }\n                    $.getJSON(self.updatePaymentUrl, {\n                        'nonce': payload.nonce,\n                        'public_hash': self.publicHash\n                    }).done(function (response) {\n                        if (response.success === false) {\n                            fullScreenLoader.stopLoader();\n                            globalMessageList.addErrorMessage({\n                                message: 'CVV verification failed.'\n                            });\n                            return;\n                        }\n                        self.getPaymentMethodNonce();\n                    });\n                });\n            } else {\n                self.getPaymentMethodNonce();\n            }\n        },\n\n        /**\n         * Send request to get payment method nonce\n         */\n        getPaymentMethodNonce: function () {\n            let self = this;\n\n            fullScreenLoader.startLoader();\n            $.getJSON(self.nonceUrl, {\n                'public_hash': self.publicHash,\n                'cvv': self.vaultedCVV()\n            }).done(function (response) {\n                fullScreenLoader.stopLoader();\n                self.hostedFields(function (formComponent) {\n                    formComponent.setPaymentMethodNonce(response.paymentMethodNonce);\n                    formComponent.setCreditCardBin(response.details.bin);\n                    formComponent.additionalData['public_hash'] = self.publicHash;\n                    formComponent.code = self.code;\n                    if (self.vaultedCVV()) {\n                        formComponent.additionalData['cvv'] = self.vaultedCVV();\n                    }\n\n                    self.validatorManager.validate(formComponent, function () {\n                        fullScreenLoader.stopLoader();\n                        return formComponent.placeOrder('parent');\n                    }, function () {\n                        // No teardown actions required.\n                        fullScreenLoader.stopLoader();\n                        formComponent.setPaymentMethodNonce(null);\n                        formComponent.setCreditCardBin(null);\n                    });\n\n                });\n            }).fail(function (response) {\n                let error = JSON.parse(response.responseText);\n\n                fullScreenLoader.stopLoader();\n                globalMessageList.addErrorMessage({\n                    message: error.message\n                });\n            });\n        }\n    });\n});\n","PayPal_Braintree/js/view/payment/method-renderer/cc-form.js":"/**\n * Copyright 2013-2017 Magento, Inc. All rights reserved.\n * See COPYING.txt for license details.\n */\n/*browser:true*/\ndefine(\n    [\n        'underscore',\n        'jquery',\n        'Magento_Payment/js/view/payment/cc-form',\n        'Magento_Checkout/js/model/quote',\n        'PayPal_Braintree/js/view/payment/adapter',\n        'mage/translate',\n        'PayPal_Braintree/js/validator',\n        'PayPal_Braintree/js/view/payment/validator-handler',\n        'Magento_Checkout/js/model/full-screen-loader'\n    ],\n    function (\n        _,\n        $,\n        Component,\n        quote,\n        braintree,\n        $t,\n        validator,\n        validatorManager,\n        fullScreenLoader\n    ) {\n        'use strict';\n\n        return Component.extend({\n            defaults: {\n                active: false,\n                braintreeClient: null,\n                braintreeDeviceData: null,\n                paymentMethodNonce: null,\n                lastBillingAddress: null,\n                validatorManager: validatorManager,\n                code: 'braintree',\n                isProcessing: false,\n                creditCardBin: null,\n\n                /**\n                 * Additional payment data\n                 *\n                 * {Object}\n                 */\n                additionalData: {},\n\n                /**\n                 * Braintree client configuration\n                 *\n                 * {Object}\n                 */\n                clientConfig: {\n                    onReady: function (context) {\n                        context.setupHostedFields();\n                    },\n\n                    /**\n                     * Triggers on payment nonce receive\n                     * @param {Object} response\n                     */\n                    onPaymentMethodReceived: function (response) {\n                        this.handleNonce(response);\n                        this.isProcessing = false;\n                    },\n\n                    /**\n                     * Allow a new nonce to be generated\n                     */\n                    onPaymentMethodError: function () {\n                        this.isProcessing = false;\n                    },\n\n                    /**\n                     * Device data initialization\n                     * @param {String} deviceData\n                     */\n                    onDeviceDataReceived: function (deviceData) {\n                        if (this.additionalData === undefined) {\n                            this.additionalData = {};\n                        }\n                        this.additionalData['device_data'] = deviceData;\n                    },\n\n                    /**\n                     * After Braintree instance initialization\n                     */\n                    onInstanceReady: function () {},\n\n                    /**\n                     * Triggers on any Braintree error\n                     * @param {Object} response\n                     */\n                    onError: function (response) {\n                        this.isProcessing = false;\n                        braintree.showError($t('Payment ' + this.getTitle() + ' can\\'t be initialized'));\n                        throw response.message;\n                    },\n\n                    /**\n                     * Triggers when customer click \"Cancel\"\n                     */\n                    onCancelled: function () {\n                        this.paymentMethodNonce = null;\n                        this.isProcessing = false;\n                    }\n                },\n                imports: {\n                    onActiveChange: 'active'\n                }\n            },\n\n            /**\n             * Set list of observable attributes\n             *\n             * @returns {exports.initObservable}\n             */\n            initObservable: function () {\n                validator.setConfig(window.checkoutConfig.payment[this.getCode()]);\n                this._super()\n                    .observe(['active']);\n                this.validatorManager.initialize();\n                this.initClientConfig();\n\n                return this;\n            },\n\n            /**\n             * Get payment name\n             *\n             * @returns {String}\n             */\n            getCode: function () {\n                return this.code;\n            },\n\n            /**\n             * Check if payment is active\n             *\n             * @returns {Boolean}\n             */\n            isActive: function () {\n                let active = this.getCode() === this.isChecked();\n\n                this.active(active);\n\n                return active;\n            },\n\n            /**\n             * Triggers when payment method change\n             * @param {Boolean} isActive\n             */\n            onActiveChange: function (isActive) {\n                if (!isActive) {\n                    return;\n                }\n\n                this.initBraintree();\n            },\n\n            /**\n             * Init config\n             */\n            initClientConfig: function () {\n                _.each(this.clientConfig, function (fn, name) {\n                    if (typeof fn === 'function') {\n                        this.clientConfig[name] = fn.bind(this);\n                    }\n                }, this);\n            },\n\n            /**\n             * Init Braintree configuration\n             */\n            initBraintree: function () {\n                let intervalId = setInterval(function () {\n                    // stop loader when frame will be loaded\n                    if ($('#braintree-hosted-field-number').length) {\n                        clearInterval(intervalId);\n                        fullScreenLoader.stopLoader(true);\n                    }\n                }, 500);\n\n                if (braintree.checkout) {\n                    braintree.checkout.teardown(function () {\n                        braintree.checkout = null;\n                    });\n                }\n\n                fullScreenLoader.startLoader();\n                braintree.setConfig(this.clientConfig);\n                braintree.setup();\n            },\n\n            /**\n             * Get full selector name\n             *\n             * @param {String} field\n             * @returns {String}\n             */\n            getSelector: function (field) {\n                return '#' + this.getCode() + '_' + field;\n            },\n\n            /**\n             * Get list of available CC types\n             *\n             * @returns {Object}\n             */\n            getCcAvailableTypes: function () {\n                let availableTypes = validator.getAvailableCardTypes(),\n                    billingAddress = quote.billingAddress(),\n                    billingCountryId;\n\n                this.lastBillingAddress = quote.shippingAddress();\n\n                if (!billingAddress) {\n                    billingAddress = this.lastBillingAddress;\n                }\n\n                billingCountryId = billingAddress.countryId;\n\n                if (billingCountryId && validator.getCountrySpecificCardTypes(billingCountryId)) {\n                    return validator.collectTypes(\n                        availableTypes,\n                        validator.getCountrySpecificCardTypes(billingCountryId)\n                    );\n                }\n\n                return availableTypes;\n            },\n\n            /**\n             * @returns {String}\n             */\n            getEnvironment: function () {\n                return window.checkoutConfig.payment[this.getCode()].environment;\n            },\n\n            /**\n             * Get data\n             *\n             * @returns {Object}\n             */\n            getData: function () {\n                let data = {\n                    'method': this.getCode(),\n                    'additional_data': {\n                        'payment_method_nonce': this.paymentMethodNonce,\n                        'g-recaptcha-response' : $('#token-grecaptcha-braintree').val()\n                    }\n                };\n\n                data['additional_data'] = _.extend(data['additional_data'], this.additionalData);\n\n                return data;\n            },\n\n            /**\n             * Set payment nonce\n             * @param {String} paymentMethodNonce\n             */\n            setPaymentMethodNonce: function (paymentMethodNonce) {\n                this.paymentMethodNonce = paymentMethodNonce;\n            },\n\n            /**\n             * Set credit card bin\n             * @param creditCardBin\n             */\n            setCreditCardBin: function (creditCardBin) {\n                this.creditCardBin = creditCardBin;\n            },\n\n            /**\n             * Prepare payload to place order\n             * @param {Object} payload\n             */\n            handleNonce: function (payload) {\n                let self = this;\n\n                this.setPaymentMethodNonce(payload.nonce);\n                this.setCreditCardBin(payload.details.bin);\n\n                // place order on success validation\n                self.validatorManager.validate(self, function () {\n                    return self.placeOrder('parent');\n                }, function () {\n                    self.isProcessing = false;\n                    self.paymentMethodNonce = null;\n                    self.creditCardBin = null;\n                });\n            },\n\n            /**\n             * Action to place order\n             * @param {String} key\n             */\n            placeOrder: function (key) {\n                if (key) {\n                    return this._super();\n                }\n\n                if (this.isProcessing) {\n                    return false;\n                }\n                this.isProcessing = true;\n\n\n                braintree.tokenizeHostedFields();\n                return false;\n            },\n\n            /**\n             * Get payment icons\n             * @param {String} type\n             * @returns {Boolean}\n             */\n            getIcons: function (type) {\n                return window.checkoutConfig.payment.braintree.icons.hasOwnProperty(type) ?\n                    window.checkoutConfig.payment.braintree.icons[type]\n                    : false;\n            }\n        });\n    }\n);\n","PayPal_Braintree/js/view/payment/method-renderer/ach-vault.js":"/*browser:true*/\ndefine([\n    'ko',\n    'jquery',\n    'underscore',\n    'Magento_Vault/js/view/payment/method-renderer/vault',\n    'Magento_Ui/js/model/messageList',\n    'PayPal_Braintree/js/view/payment/validator-handler',\n    'Magento_Checkout/js/model/payment/additional-validators',\n    'Magento_Checkout/js/model/full-screen-loader'\n], function (\n    ko,\n    $,\n    _,\n    VaultComponent,\n    globalMessageList,\n    validatorManager,\n    additionalValidators,\n    fullScreenLoader\n) {\n    'use strict';\n\n    return VaultComponent.extend({\n        defaults: {\n            active: false,\n            imports: {\n                onActiveChange: 'active'\n            },\n            template: 'PayPal_Braintree/payment/ach/vault',\n            validatorManager: validatorManager,\n            additionalData: {}\n        },\n\n        /**\n         * @returns {exports}\n         */\n        initObservable: function () {\n            this._super().observe(['active']);\n            this.validatorManager.initialize();\n            return this;\n        },\n\n        /**\n         * Is payment option active?\n         *\n         * @returns {boolean}\n         */\n        isActive: function () {\n            let active = this.getId() === this.isChecked();\n\n            this.active(active);\n            return active;\n        },\n\n        /**\n         * Return the payment method code.\n         *\n         * @returns {String}\n         */\n        getCode: function () {\n            return 'braintree_ach_direct_debit_vault';\n        },\n\n        /**\n         * Get Bank Account last 4 digits.\n         *\n         * @returns {String}\n         */\n        getAccountNumberLastFourDigits: function () {\n            return this.details.last4;\n        },\n\n        /**\n         *\n         * Get bank's routing number\n         *\n         * @returns {String}\n         */\n        getRoutingNumber: function () {\n            return this.details.routingNumber;\n        },\n\n        /**\n         * Get the ACH icon.\n         *\n         * @return {String}\n         */\n        getPaymentIcon() {\n            return window.checkoutConfig.payment['braintree_ach_direct_debit'].paymentIcon;\n        },\n\n        /**\n         * Trigger Place order action.\n         *\n         * Set payment method nonce & place order.\n         */\n        triggerPlaceOrder: function () {\n            this.getPaymentMethodNonce();\n        },\n\n        /**\n         * Send request to get payment method nonce & places order.\n         */\n        getPaymentMethodNonce: function () {\n            let self = this;\n\n            fullScreenLoader.startLoader();\n            $.getJSON(self.nonceUrl, {\n                'public_hash': self.publicHash\n            }).done(function (response) {\n                fullScreenLoader.stopLoader();\n                self.additionalData['payment_method_nonce'] = response.paymentMethodNonce;\n                self.placeOrder();\n            }).fail(function (response) {\n                let error = JSON.parse(response.responseText);\n\n                fullScreenLoader.stopLoader();\n                globalMessageList.addErrorMessage({\n                    message: error.message\n                });\n            });\n        },\n\n        /**\n         * Get payment method data.\n         *\n         * @returns {Object}\n         */\n        getData: function () {\n            let data = {\n                'method': this.code,\n                'additional_data': {\n                    'public_hash': this.publicHash\n                }\n            };\n\n            data['additional_data'] = _.extend(data['additional_data'], this.additionalData);\n\n            return data;\n        }\n    });\n});\n","PayPal_Braintree/js/view/payment/method-renderer/venmo-vault.js":"/*browser:true*/\n\ndefine([\n    'ko',\n    'jquery',\n    'underscore',\n    'Magento_Vault/js/view/payment/method-renderer/vault',\n    'Magento_Ui/js/model/messageList',\n    'PayPal_Braintree/js/view/payment/validator-handler',\n    'Magento_Checkout/js/model/payment/additional-validators',\n    'Magento_Checkout/js/model/full-screen-loader'\n], function (\n    ko,\n    $,\n    _,\n    VaultComponent,\n    globalMessageList,\n    validatorManager,\n    additionalValidators,\n    fullScreenLoader\n) {\n    'use strict';\n\n    return VaultComponent.extend({\n        defaults: {\n            active: false,\n            imports: {\n                onActiveChange: 'active'\n            },\n            template: 'PayPal_Braintree/payment/venmo/vault',\n            validatorManager: validatorManager,\n            additionalData: {}\n        },\n\n        /**\n         * @returns {exports}\n         */\n        initObservable: function () {\n            this._super().observe(['active']);\n            this.validatorManager.initialize();\n            return this;\n        },\n\n        /**\n         * Is payment option active?\n         *\n         * @returns {boolean}\n         */\n        isActive: function () {\n            let active = this.getId() === this.isChecked();\n\n            this.active(active);\n            return active;\n        },\n\n        /**\n         * Return the payment method code.\n         *\n         * @returns {string}\n         */\n        getCode: function () {\n            return 'braintree_venmo_vault';\n        },\n\n        /**\n         * Get venmo username\n         *\n         * @returns {String}\n         */\n        getVenmoUsername: function () {\n            return this.details.username;\n        },\n\n        /**\n         * Get the Venmo icon\n         *\n         * @param type\n         * @return {*|boolean}\n         */\n        getVenmoIcon() {\n            return window.checkoutConfig.payment.braintree_venmo.paymentMarkSrc;\n        },\n\n        /**\n         * trigger Place order action.\n         *\n         * Set payment method nonce & place order.\n         */\n        triggerPlaceOrder: function () {\n            this.getPaymentMethodNonce();\n        },\n\n        /**\n         * Send request to get payment method nonce & places order.\n         */\n        getPaymentMethodNonce: function () {\n            let self = this;\n\n            fullScreenLoader.startLoader();\n            $.getJSON(self.nonceUrl, {\n                'public_hash': self.publicHash\n            }).done(function (response) {\n                fullScreenLoader.stopLoader();\n                self.additionalData['payment_method_nonce'] = response.paymentMethodNonce;\n                self.placeOrder();\n            }).fail(function (response) {\n                let error = JSON.parse(response.responseText);\n\n                fullScreenLoader.stopLoader();\n                globalMessageList.addErrorMessage({\n                    message: error.message\n                });\n            });\n        },\n\n        /**\n         * Get payment method data.\n         *\n         * @returns {Object}\n         */\n        getData: function () {\n            let data = {\n                'method': this.code,\n                'additional_data': {\n                    'public_hash': this.publicHash\n                }\n            };\n\n            data['additional_data'] = _.extend(data['additional_data'], this.additionalData);\n\n            return data;\n        }\n    });\n});\n","PayPal_Braintree/js/view/payment/method-renderer/paypal.js":"/**\n * Copyright \u00a9 Magento, Inc. All rights reserved.\n * See COPYING.txt for license details.\n */\n/*browser:true*/\ndefine([\n    'jquery',\n    'underscore',\n    'Magento_Checkout/js/view/payment/default',\n    'braintree',\n    'braintreeCheckoutPayPalAdapter',\n    'braintreePayPalCheckout',\n    'PayPal_Braintree/js/helper/format-amount',\n    'PayPal_Braintree/js/helper/remove-non-digit-characters',\n    'PayPal_Braintree/js/helper/replace-unsupported-characters',\n    'PayPal_Braintree/js/helper/get-cart-line-items-helper',\n    'Magento_Checkout/js/model/quote',\n    'Magento_Checkout/js/model/full-screen-loader',\n    'Magento_Checkout/js/model/payment/additional-validators',\n    'Magento_Checkout/js/model/step-navigator',\n    'Magento_Vault/js/view/payment/vault-enabler',\n    'Magento_Checkout/js/action/create-billing-address',\n    'Magento_Checkout/js/action/select-billing-address',\n    'Magento_CheckoutAgreements/js/view/checkout-agreements',\n    'mage/translate'\n], function (\n    $,\n    _,\n    Component,\n    braintree,\n    Braintree,\n    paypalCheckout,\n    formatAmount,\n    removeNonDigitCharacters,\n    replaceUnsupportedCharacters,\n    getCartLineItems,\n    quote,\n    fullScreenLoader,\n    additionalValidators,\n    stepNavigator,\n    VaultEnabler,\n    createBillingAddress,\n    selectBillingAddress,\n    checkoutAgreements,\n    $t\n) {\n    'use strict';\n\n    return Component.extend({\n        defaults: {\n            template: 'PayPal_Braintree/payment/paypal',\n            code: 'braintree_paypal',\n            active: false,\n            paypalInstance: null,\n            paymentMethodNonce: null,\n            grandTotalAmount: null,\n            isReviewRequired: false,\n            customerEmail: null,\n\n            /**\n             * Additional payment data\n             *\n             * {Object}\n             */\n            additionalData: {},\n\n            /**\n             * Line items array\n             *\n             * {Array}\n             */\n            lineItemsArray: [\n                'name',\n                'kind',\n                'quantity',\n                'unitAmount',\n                'productCode',\n                'description'\n            ],\n\n            /**\n             * PayPal client configuration\n             *\n             * {Object}\n             */\n            clientConfig: {\n                offerCredit: false,\n                offerCreditOnly: false,\n                dataCollector: {\n                    paypal: true\n                },\n\n                buttonPayPalId: 'braintree_paypal_placeholder',\n                buttonCreditId: 'braintree_paypal_credit_placeholder',\n                buttonPayLaterId: 'braintree_paypal_paylater_placeholder',\n\n                onDeviceDataReceived: function (deviceData) {\n                    this.additionalData['device_data'] = deviceData;\n                },\n\n                /**\n                 * Triggers when widget is loaded\n                 */\n                onReady: function () {\n                    this.setupPayPal();\n                },\n\n                /**\n                 * Triggers on payment nonce receive\n                 *\n                 * @param {Object} response\n                 */\n                onPaymentMethodReceived: function (response) {\n                    this.beforePlaceOrder(response);\n                }\n            },\n            imports: {\n                onActiveChange: 'active'\n            }\n        },\n\n        /**\n         * Set list of observable attributes\n         *\n         * @returns {exports.initObservable}\n         */\n        initObservable: function () {\n            let self = this;\n\n            this._super()\n                .observe(['active', 'isReviewRequired', 'customerEmail']);\n\n            window.addEventListener('hashchange', function (e) {\n                let methodCode = quote.paymentMethod();\n\n                if (methodCode === 'braintree_paypal' || methodCode === 'braintree_paypal_vault') {\n                    if (e.newURL.indexOf('payment') > 0 && self.grandTotalAmount !== null) {\n                        self.reInitPayPal();\n                    }\n                }\n            });\n\n            quote.paymentMethod.subscribe(function (value) {\n                let methodCode = value;\n\n                if (methodCode === 'braintree_paypal' || methodCode === 'braintree_paypal_vault') {\n                    self.reInitPayPal();\n                }\n            });\n\n            this.vaultEnabler = new VaultEnabler();\n            this.vaultEnabler.setPaymentCode(this.getVaultCode());\n            this.vaultEnabler.isActivePaymentTokenEnabler.subscribe(function () {\n                self.onVaultPaymentTokenEnablerChange();\n            });\n\n            this.grandTotalAmount = quote.totals()['base_grand_total'];\n\n            quote.totals.subscribe(function () {\n                if (self.grandTotalAmount !== quote.totals()['base_grand_total']) {\n                    self.grandTotalAmount = quote.totals()['base_grand_total'];\n                    let methodCode = quote.paymentMethod();\n\n                    if (methodCode &&\n                        (methodCode.method === 'braintree_paypal' || methodCode.method === 'braintree_paypal_vault')) {\n                        self.reInitPayPal();\n                    }\n                }\n            });\n\n            // for each component initialization need update property\n            this.isReviewRequired(false);\n            this.initClientConfig();\n\n            return this;\n        },\n\n        /**\n         * Get payment name\n         *\n         * @returns {String}\n         */\n        getCode: function () {\n            return this.code;\n        },\n\n        /**\n         * Get payment title\n         *\n         * @returns {String}\n         */\n        getTitle: function () {\n            return window.checkoutConfig.payment[this.getCode()].title;\n        },\n\n        /**\n         * Check if payment is active\n         *\n         * @returns {Boolean}\n         */\n        isActive: function () {\n            let active = this.getCode() === this.isChecked();\n\n            this.active(active);\n\n            return active;\n        },\n\n        /**\n         * Triggers when payment method change\n         *\n         * @param {Boolean} isActive\n         */\n        onActiveChange: function (isActive) {\n            if (!isActive) {\n                return;\n            }\n\n            // need always re-init Braintree with PayPal configuration\n            this.reInitPayPal();\n        },\n\n        /**\n         * Init config\n         */\n        initClientConfig: function () {\n            this.clientConfig = _.extend(this.clientConfig, this.getPayPalConfig());\n\n            _.each(this.clientConfig, function (fn, name) {\n                if (typeof fn === 'function') {\n                    this.clientConfig[name] = fn.bind(this);\n                }\n            }, this);\n        },\n\n        /**\n         * Set payment nonce\n         *\n         * @param {String} paymentMethodNonce\n         */\n        setPaymentMethodNonce: function (paymentMethodNonce) {\n            this.paymentMethodNonce = paymentMethodNonce;\n        },\n\n        /**\n         * Update quote billing address\n         *\n         * @param {Object}customer\n         * @param {Object}address\n         */\n        setBillingAddress: function (customer, address) {\n            let billingAddress = {\n                street: [address.line1],\n                city: address.city,\n                postcode: address.postalCode,\n                countryId: address.countryCode,\n                email: customer.email,\n                firstname: customer.firstName,\n                lastname: customer.lastName,\n                telephone: removeNonDigitCharacters(_.get(customer, 'phone', '00000000000'))\n            };\n\n            billingAddress['region_code'] = typeof address.state === 'string' ? address.state : '';\n            billingAddress = createBillingAddress(billingAddress);\n            quote.billingAddress(billingAddress);\n        },\n\n        /**\n         * Prepare data to place order\n         *\n         * @param {Object} data\n         */\n        beforePlaceOrder: function (data) {\n            this.setPaymentMethodNonce(data.nonce);\n            this.customerEmail(data.details.email);\n            if (quote.isVirtual()) {\n                this.isReviewRequired(true);\n            } else if (this.isRequiredBillingAddress() === '1' || quote.billingAddress() === null) {\n                if (typeof data.details.billingAddress !== 'undefined') {\n                    this.setBillingAddress(data.details, data.details.billingAddress);\n                } else {\n                    this.setBillingAddress(data.details, data.details.shippingAddress);\n                }\n            } else if (quote.shippingAddress() === quote.billingAddress()) {\n                selectBillingAddress(quote.shippingAddress());\n            } else {\n                selectBillingAddress(quote.billingAddress());\n            }\n            this.placeOrder();\n        },\n\n        /**\n         * Re-init PayPal Auth Flow\n         */\n        reInitPayPal: function () {\n            this.disableButton();\n            this.clientConfig.paypal.amount = formatAmount(this.grandTotalAmount);\n\n            if (!quote.isVirtual()) {\n                this.clientConfig.paypal.enableShippingAddress = true;\n                this.clientConfig.paypal.shippingAddressEditable = false;\n                this.clientConfig.paypal.shippingAddressOverride = this.getShippingAddress();\n            }\n            // Send Line Items\n            this.clientConfig.paypal.lineItems = getCartLineItems();\n\n            Braintree.setConfig(this.clientConfig);\n\n            if (Braintree.getPayPalInstance()) {\n                Braintree.getPayPalInstance().teardown(function () {\n                    Braintree.setup();\n                });\n                Braintree.setPayPalInstance(null);\n            } else {\n                Braintree.setup();\n                this.enableButton();\n            }\n        },\n\n        /**\n         * Setup PayPal instance\n         */\n        setupPayPal: function () {\n            if (Braintree.config.paypalInstance) {\n                fullScreenLoader.stopLoader(true);\n                return;\n            }\n\n            paypalCheckout.create({\n                client: Braintree.clientInstance\n            }, function (createErr, paypalCheckoutInstance) {\n                if (createErr) {\n                    Braintree.showError(\n                        $t('PayPal Checkout could not be initialized. Please contact the store owner.'));\n                    console.error('paypalCheckout error', createErr);\n                    return;\n                }\n                let quoteObj = quote.totals(),\n                    configSDK = {\n                        components: 'buttons,messages,funding-eligibility',\n                        'enable-funding': this.isCreditEnabled() ? 'credit' : 'paylater',\n                        currency: quoteObj['base_currency_code']\n                    },\n                    buyerCountry = this.getMerchantCountry();\n\n                if (Braintree.getEnvironment() === 'sandbox' && buyerCountry !== null) {\n                    configSDK['buyer-country'] = buyerCountry;\n                }\n                paypalCheckoutInstance.loadPayPalSDK(configSDK, function () {\n                    this.loadPayPalButton(paypalCheckoutInstance, 'paypal');\n                    if (this.isCreditEnabled()) {\n                        this.loadPayPalButton(paypalCheckoutInstance, 'credit');\n                    }\n                    if (this.isPayLaterEnabled()) {\n                        this.loadPayPalButton(paypalCheckoutInstance, 'paylater');\n                    }\n\n                }.bind(this));\n            }.bind(this));\n        },\n\n        loadPayPalButton: function (paypalCheckoutInstance, funding) {\n            let paypalPayment = Braintree.config.paypal,\n                onPaymentMethodReceived = Braintree.config.onPaymentMethodReceived,\n                style = {\n                    label: Braintree.getLabel(funding),\n                    color: Braintree.getColor(funding),\n                    shape: Braintree.getShape(funding)\n                },\n                button,\n                events = Braintree.events,\n                payPalButtonId,\n                payPalButtonElement;\n\n            if (funding === 'credit') {\n                Braintree.config.buttonId = this.getCreditButtonId();\n            } else if (funding === 'paylater') {\n                Braintree.config.buttonId = this.getPayLaterButtonId();\n            } else {\n                Braintree.config.buttonId = this.getPayPalButtonId();\n            }\n\n            payPalButtonId = Braintree.config.buttonId;\n            payPalButtonElement = $('#' + Braintree.config.buttonId);\n            payPalButtonElement.html('');\n\n            // Render\n            Braintree.config.paypalInstance = paypalCheckoutInstance;\n\n            button = window.paypal.Buttons({\n                fundingSource: funding,\n                env: Braintree.getEnvironment(),\n                style: style,\n                commit: true,\n                locale: Braintree.config.paypal.locale,\n\n                onInit: function (data, actions) {\n                    let agreements = checkoutAgreements().agreements,\n                        shouldDisableActions = false;\n\n                    actions.disable();\n\n                    _.each(agreements, function (item) {\n                        if (checkoutAgreements().isAgreementRequired(item)) {\n                            let paymentMethodCode = quote.paymentMethod().method,\n                                inputId = '#agreement_' + paymentMethodCode + '_' + item.agreementId,\n                                inputEl = document.querySelector(inputId);\n\n                            if (!inputEl.checked) {\n                                shouldDisableActions = true;\n                            }\n\n                            inputEl.addEventListener('change', function () {\n                                if (additionalValidators.validate()) {\n                                    actions.enable();\n                                } else {\n                                    actions.disable();\n                                }\n                            });\n                        }\n                    });\n\n                    if (!shouldDisableActions) {\n                        actions.enable();\n                    }\n                },\n\n                createOrder: function () {\n                    return paypalCheckoutInstance.createPayment(paypalPayment).catch(function (err) {\n                        throw err.details.originalError.details.originalError.paymentResource;\n                    });\n                },\n\n                onCancel: function (data) {\n                    console.log('checkout.js payment cancelled', JSON.stringify(data, 0, 2));\n\n                    if (typeof events.onCancel === 'function') {\n                        events.onCancel();\n                    }\n                },\n\n                onError: function (err) {\n                    if (err.errorName === 'VALIDATION_ERROR' && err.errorMessage.indexOf('Value is invalid') !== -1) {\n                        Braintree.showError(\n                            $t(\n                                'Address failed validation. Please check and confirm your City, State, and Postal Code'\n                            )\n                        );\n                    } else {\n                        Braintree.showError(\n                            $t('PayPal Checkout could not be initialized. Please contact the store owner.'));\n                    }\n                    Braintree.config.paypalInstance = null;\n                    console.error('Paypal checkout.js error', err);\n\n                    if (typeof events.onError === 'function') {\n                        events.onError(err);\n                    }\n                },\n\n                onClick: function (data) {\n                    if (!quote.isVirtual()) {\n                        this.clientConfig.paypal.enableShippingAddress = true;\n                        this.clientConfig.paypal.shippingAddressEditable = false;\n                        this.clientConfig.paypal.shippingAddressOverride = this.getShippingAddress();\n                    }\n\n                    // To check term & conditions input checked - validate additional validators.\n                    if (!additionalValidators.validate()) {\n                        return false;\n                    }\n\n                    if (typeof events.onClick === 'function') {\n                        events.onClick(data);\n                    }\n                }.bind(this),\n\n                onApprove: function (data) {\n                    return paypalCheckoutInstance.tokenizePayment(data)\n                        .then(function (payload) {\n                            onPaymentMethodReceived(payload);\n                        });\n                }\n            });\n\n            if (button.isEligible() && payPalButtonElement.length) {\n                button.render('#' + payPalButtonId).then(function () {\n                    Braintree.enableButton();\n                    if (typeof Braintree.config.onPaymentMethodError === 'function') {\n                        Braintree.config.onPaymentMethodError();\n                    }\n                }).then(function (data) {\n                    if (typeof events.onRender === 'function') {\n                        events.onRender(data);\n                    }\n                });\n            }\n        },\n\n        /**\n         * Get locale\n         *\n         * @returns {String}\n         */\n        getLocale: function () {\n            return window.checkoutConfig.payment[this.getCode()].locale;\n        },\n\n        /**\n         * Is Billing Address required from PayPal side\n         *\n         * @returns {exports.isRequiredBillingAddress|(function())|boolean}\n         */\n        isRequiredBillingAddress: function () {\n            return window.checkoutConfig.payment[this.getCode()].isRequiredBillingAddress;\n        },\n\n        /**\n         * Get configuration for PayPal\n         *\n         * @returns {Object}\n         */\n        getPayPalConfig: function () {\n            let totals = quote.totals(),\n                config = {},\n                isActiveVaultEnabler = this.isActiveVault();\n\n            config.paypal = {\n                flow: 'checkout',\n                amount: formatAmount(this.grandTotalAmount),\n                currency: totals['base_currency_code'],\n                locale: this.getLocale(),\n\n                /**\n                 * Triggers on any Braintree error\n                 */\n                onError: function () {\n                    this.paymentMethodNonce = null;\n                },\n\n                /**\n                 * Triggers if browser doesn't support PayPal Checkout\n                 */\n                onUnsupported: function () {\n                    this.paymentMethodNonce = null;\n                }\n            };\n\n            if (isActiveVaultEnabler) {\n                config.paypal.requestBillingAgreement = true;\n            }\n\n            if (!quote.isVirtual()) {\n                config.paypal.enableShippingAddress = true;\n                config.paypal.shippingAddressEditable = false;\n                config.paypal.shippingAddressOverride = this.getShippingAddress();\n            }\n\n            if (this.getMerchantName()) {\n                config.paypal.displayName = this.getMerchantName();\n            }\n\n            return config;\n        },\n\n        /**\n         * Get shipping address\n         *\n         * @returns {Object}\n         */\n        getShippingAddress: function () {\n            let address = quote.shippingAddress();\n\n            return {\n                recipientName: address.firstname + ' ' + address.lastname,\n                line1: address.street[0],\n                line2: typeof address.street[2] === 'undefined'\n                    ? address.street[1] : address.street[1] + ' ' + address.street[2],\n                city: address.city,\n                countryCode: address.countryId,\n                postalCode: address.postcode,\n                state: address.regionCode\n            };\n        },\n\n        /**\n         * Get merchant name\n         *\n         * @returns {String}\n         */\n        getMerchantName: function () {\n            return window.checkoutConfig.payment[this.getCode()]['merchantName'];\n        },\n\n        /**\n         * Get data\n         *\n         * @returns {Object}\n         */\n        getData: function () {\n            let data = {\n                'method': this.getCode(),\n                'additional_data': {\n                    'payment_method_nonce': this.paymentMethodNonce\n                }\n            };\n\n            data['additional_data'] = _.extend(data['additional_data'], this.additionalData);\n\n            this.vaultEnabler.visitAdditionalData(data);\n\n            return data;\n        },\n\n        /**\n         * Returns payment acceptance mark image path\n         *\n         * @returns {String}\n         */\n        getPaymentAcceptanceMarkSrc: function () {\n            return window.checkoutConfig.payment[this.getCode()]['paymentAcceptanceMarkSrc'];\n        },\n\n        /**\n         * Get paypal vault payment method code\n         *\n         * @returns {String}\n         */\n        getVaultCode: function () {\n            return window.checkoutConfig.payment[this.getCode()]['vaultCode'];\n        },\n\n        /**\n         * Check if vault is active\n         *\n         * @returns {Boolean}\n         */\n        isActiveVault: function () {\n            return this.vaultEnabler.isVaultEnabled() && this.vaultEnabler.isActivePaymentTokenEnabler();\n        },\n\n        /**\n         * Re-init PayPal Auth flow to use Vault\n         */\n        onVaultPaymentTokenEnablerChange: function () {\n            this.clientConfig.paypal.singleUse = !this.isActiveVault();\n            this.reInitPayPal();\n        },\n\n        /**\n         * Disable submit button\n         */\n        disableButton: function () {\n            // stop any previous shown loaders\n            fullScreenLoader.stopLoader(true);\n            fullScreenLoader.startLoader();\n            $('[data-button=\"place\"]').attr('disabled', 'disabled');\n        },\n\n        /**\n         * Enable submit button\n         */\n        enableButton: function () {\n            $('[data-button=\"place\"]').removeAttr('disabled');\n            fullScreenLoader.stopLoader(true);\n        },\n\n        /**\n         * Triggers when customer click \"Continue to PayPal\" button\n         */\n        payWithPayPal: function () {\n            if (additionalValidators.validate()) {\n                Braintree.checkout.paypal.initAuthFlow();\n            }\n        },\n\n        /**\n         * Get PayPal button id\n         *\n         * @returns {String}\n         */\n        getPayPalButtonId: function () {\n            return this.clientConfig.buttonPayPalId;\n        },\n\n        /**\n         * Get Credit button id\n         *\n         * @returns {String}\n         */\n        getCreditButtonId: function () {\n            return this.clientConfig.buttonCreditId;\n        },\n\n        /**\n         * Get Pay Later button id\n         *\n         * @returns {String}\n         */\n        getPayLaterButtonId: function () {\n            return this.clientConfig.buttonPayLaterId;\n        },\n\n        /**\n         * Check if Pay Later enabled\n         *\n         * @returns {*}\n         */\n        isPayLaterEnabled: function () {\n            return window.checkoutConfig.payment['braintree_paypal_paylater']['isActive'];\n        },\n\n        /**\n         * Check if Pay Later messaging enabled\n         *\n         * @returns {*}\n         */\n        isPayLaterMessageEnabled: function () {\n            return window.checkoutConfig.payment['braintree_paypal_paylater']['isMessageActive'];\n        },\n\n        /**\n         * Get grand total\n         *\n         * @returns {string}\n         */\n        getGrandTotalAmount: function () {\n            return formatAmount(this.grandTotalAmount);\n        },\n\n        /**\n         * Check if PayPal Credit enabled\n         *\n         * @returns {*}\n         */\n        isCreditEnabled: function () {\n            return window.checkoutConfig.payment['braintree_paypal_credit']['isActive'];\n        },\n\n        /**\n         * Get Message Layout\n         *\n         * @returns {string}\n         */\n        getMessagingLayout: function () {\n            return window.checkoutConfig.payment['braintree_paypal_paylater']['message']['layout'];\n        },\n\n        /**\n         * Get Message Logo\n         *\n         * @returns {string}\n         */\n        getMessagingLogo: function () {\n            return window.checkoutConfig.payment['braintree_paypal_paylater']['message']['logo'];\n        },\n\n        /**\n         * Get Message Logo position\n         *\n         * @returns {string}\n         */\n        getMessagingLogoPosition: function () {\n            return window.checkoutConfig.payment['braintree_paypal_paylater']['message']['logo_position'];\n        },\n\n        /**\n         * Get Message Text Color\n         *\n         * @returns {string}\n         */\n        getMessagingTextColor: function () {\n            return window.checkoutConfig.payment['braintree_paypal_paylater']['message']['text_color'];\n        },\n\n        /**\n         * Get merchant country\n         *\n         * @returns {*}\n         */\n        getMerchantCountry: function () {\n            return window.checkoutConfig.payment[this.getCode()]['merchantCountry'];\n        },\n\n        /**\n         * Regex to replace all unsupported characters.\n         *\n         * @param str\n         */\n        replaceUnsupportedCharacters: function (str) {\n            // eslint-disable-next-line no-useless-escape\n            str.replace('/[^a-zA-Z0-9\\s\\-.\\']/', '');\n            return str.substr(0, 127);\n        },\n\n        /**\n         * Can send line items\n         *\n         * @returns {Boolean}\n         */\n        canSendLineItems: function () {\n            return window.checkoutConfig.payment[this.getCode()].canSendLineItems;\n        }\n    });\n});\n","PayPal_Braintree/js/view/payment/method-renderer/googlepay-vault.js":"/**\n * Copyright \u00a9 Magento, Inc. All rights reserved.\n * See COPYING.txt for license details.\n */\n/*browser:true*/\ndefine([\n    'ko',\n    'jquery',\n    'underscore',\n    'Magento_Vault/js/view/payment/method-renderer/vault',\n    'Magento_Ui/js/model/messageList',\n    'PayPal_Braintree/js/view/payment/validator-handler',\n    'Magento_Checkout/js/model/payment/additional-validators',\n    'Magento_Checkout/js/model/full-screen-loader'\n], function (\n    ko,\n    $,\n    _,\n    VaultComponent,\n    globalMessageList,\n    validatorManager,\n    additionalValidators,\n    fullScreenLoader\n) {\n    'use strict';\n\n    return VaultComponent.extend({\n        defaults: {\n            active: false,\n            imports: {\n                onActiveChange: 'active'\n            },\n            template: 'PayPal_Braintree/googlepay/vault',\n            validatorManager: validatorManager,\n            additionalData: {}\n        },\n\n        /**\n         * @returns {exports}\n         */\n        initObservable: function () {\n            this._super().observe(['active']);\n            this.validatorManager.initialize();\n            return this;\n        },\n\n        /**\n         * Is payment option active?\n         *\n         * @returns {boolean}\n         */\n        isActive: function () {\n            let active = this.getId() === this.isChecked();\n\n            this.active(active);\n            return active;\n        },\n\n        /**\n         * Return the payment method code.\n         *\n         * @returns {string}\n         */\n        getCode: function () {\n            return this.code;\n        },\n\n        /**\n         * Get last 4 digits of card.\n         *\n         * @returns {String}\n         */\n        getMaskedCard: function () {\n            return this.details.maskedCC;\n        },\n\n        /**\n         * Get expiration date.\n         *\n         * @returns {String}\n         */\n        getExpirationDate: function () {\n            return this.details.expirationDate;\n        },\n\n        /**\n         * Get card type.\n         *\n         * @returns {String}\n         */\n        getCardType: function () {\n            return this.details.type;\n        },\n\n        /**\n         * Get the Google Pay Card icons.\n         *\n         * @param type\n         * @return {*|boolean}\n         */\n        getGooglePayIcons: function (type) {\n            let lowerCasedType = type.toLowerCase();\n\n            return window.checkoutConfig.payment.braintree_googlepay.icons.hasOwnProperty(lowerCasedType) ?\n                window.checkoutConfig.payment.braintree_googlepay.icons[lowerCasedType]\n                : false;\n        },\n\n        /**\n         * trigger Place order action.\n         *\n         * Set payment method nonce & place order.\n         */\n        triggerPlaceOrder: function () {\n            this.getPaymentMethodNonce();\n        },\n\n        /**\n         * Send request to get payment method nonce & places order.\n         */\n        getPaymentMethodNonce: function () {\n            let self = this;\n\n            fullScreenLoader.startLoader();\n            $.getJSON(self.nonceUrl, {\n                'public_hash': self.publicHash\n            }).done(function (response) {\n                fullScreenLoader.stopLoader();\n                self.additionalData['payment_method_nonce'] = response.paymentMethodNonce;\n                self.placeOrder();\n            }).fail(function (response) {\n                let error = JSON.parse(response.responseText);\n\n                fullScreenLoader.stopLoader();\n                globalMessageList.addErrorMessage({\n                    message: error.message\n                });\n            });\n        },\n\n        /**\n         * Get payment method data.\n         *\n         * @returns {Object}\n         */\n        getData: function () {\n            let data = {\n                'method': this.code,\n                'additional_data': {\n                    'public_hash': this.publicHash\n                }\n            };\n\n            data['additional_data'] = _.extend(data['additional_data'], this.additionalData);\n\n            return data;\n        }\n    });\n});\n","PayPal_Braintree/js/view/payment/method-renderer/paypal-vault.js":"/**\n * Copyright \u00a9 Magento, Inc. All rights reserved.\n * See COPYING.txt for license details.\n */\n/*browser:true*/\ndefine([\n    'jquery',\n    'underscore',\n    'Magento_Vault/js/view/payment/method-renderer/vault',\n    'Magento_Ui/js/model/messageList',\n    'Magento_Checkout/js/model/full-screen-loader'\n], function ($, _, VaultComponent, globalMessageList, fullScreenLoader) {\n    'use strict';\n\n    return VaultComponent.extend({\n        defaults: {\n            template: 'PayPal_Braintree/payment/paypal/vault',\n            additionalData: {}\n        },\n\n        /**\n         * Get PayPal payer email\n         * @returns {String}\n         */\n        getPayerEmail: function () {\n            return this.details.payerEmail;\n        },\n\n        /**\n         * Get type of payment\n         * @returns {String}\n         */\n        getPaymentIcon: function () {\n            return window.checkoutConfig.payment['braintree_paypal'].paymentIcon;\n        },\n\n        /**\n         * Place order\n         */\n        beforePlaceOrder: function () {\n            this.getPaymentMethodNonce();\n        },\n\n        /**\n         * Send request to get payment method nonce\n         */\n        getPaymentMethodNonce: function () {\n            var self = this;\n\n            fullScreenLoader.startLoader();\n            $.getJSON(self.nonceUrl, {\n                'public_hash': self.publicHash\n            })\n                .done(function (response) {\n                    fullScreenLoader.stopLoader();\n                    self.additionalData['payment_method_nonce'] = response.paymentMethodNonce;\n                    self.placeOrder();\n                })\n                .fail(function (response) {\n                    var error = JSON.parse(response.responseText);\n\n                    fullScreenLoader.stopLoader();\n                    globalMessageList.addErrorMessage({\n                        message: error.message\n                    });\n                });\n        },\n\n        /**\n         * Get payment method data\n         * @returns {Object}\n         */\n        getData: function () {\n            var data = {\n                'method': this.code,\n                'additional_data': {\n                    'public_hash': this.publicHash\n                }\n            };\n\n            data['additional_data'] = _.extend(data['additional_data'], this.additionalData);\n\n            return data;\n        }\n    });\n});\n","PayPal_Braintree/js/view/payment/method-renderer/applepay-vault.js":"/**\n * Copyright \u00a9 Magento, Inc. All rights reserved.\n * See COPYING.txt for license details.\n */\n/*browser:true*/\ndefine([\n    'ko',\n    'jquery',\n    'underscore',\n    'Magento_Vault/js/view/payment/method-renderer/vault',\n    'Magento_Ui/js/model/messageList',\n    'PayPal_Braintree/js/view/payment/validator-handler',\n    'Magento_Checkout/js/model/payment/additional-validators',\n    'Magento_Checkout/js/model/full-screen-loader'\n], function (\n    ko,\n    $,\n    _,\n    VaultComponent,\n    globalMessageList,\n    validatorManager,\n    additionalValidators,\n    fullScreenLoader\n) {\n    'use strict';\n\n    return VaultComponent.extend({\n        defaults: {\n            active: false,\n            imports: {\n                onActiveChange: 'active'\n            },\n            template: 'PayPal_Braintree/applepay/vault',\n            validatorManager: validatorManager,\n            additionalData: {}\n        },\n\n        /**\n         * @returns {exports}\n         */\n        initObservable: function () {\n            this._super().observe(['active']);\n            this.validatorManager.initialize();\n            return this;\n        },\n\n        /**\n         * Is payment option active?\n         *\n         * @returns {boolean}\n         */\n        isActive: function () {\n            let active = this.getId() === this.isChecked();\n\n            this.active(active);\n            return active;\n        },\n\n        /**\n         * Return the payment method code.\n         *\n         * @returns {string}\n         */\n        getCode: function () {\n            return 'braintree_applepay_vault';\n        },\n\n        /**\n         * Get last 4 digits of card.\n         *\n         * @returns {String}\n         */\n        getMaskedCard: function () {\n            return this.details.maskedCC;\n        },\n\n        /**\n         * Get expiration date.\n         *\n         * @returns {String}\n         */\n        getExpirationDate: function () {\n            return this.details.expirationDate;\n        },\n\n        /**\n         * Get card type.\n         *\n         * @returns {String}\n         */\n        getCardType: function () {\n            return this.details.type;\n        },\n\n        /**\n         * Get the ApplePay Card icons.\n         *\n         * @param type\n         * @return {*|boolean}\n         */\n        getApplePayIcons(type) {\n            let lowerCasedType = type.toLowerCase();\n\n            return window.checkoutConfig.payment.braintree_applepay.icons.hasOwnProperty(lowerCasedType) ?\n                window.checkoutConfig.payment.braintree_applepay.icons[lowerCasedType]\n                : false;\n        },\n\n        /**\n         * trigger Place order action.\n         *\n         * Set payment method nonce & place order.\n         */\n        triggerPlaceOrder: function () {\n            this.getPaymentMethodNonce();\n        },\n\n        /**\n         * Send request to get payment method nonce & places order.\n         */\n        getPaymentMethodNonce: function () {\n            let self = this;\n\n            fullScreenLoader.startLoader();\n            $.getJSON(self.nonceUrl, {\n                'public_hash': self.publicHash\n            }).done(function (response) {\n                fullScreenLoader.stopLoader();\n                self.additionalData['payment_method_nonce'] = response.paymentMethodNonce;\n                self.placeOrder();\n            }).fail(function (response) {\n                let error = JSON.parse(response.responseText);\n\n                fullScreenLoader.stopLoader();\n                globalMessageList.addErrorMessage({\n                    message: error.message\n                });\n            });\n        },\n\n        /**\n         * Get payment method data.\n         *\n         * @returns {Object}\n         */\n        getData: function () {\n            let data = {\n                'method': this.code,\n                'additional_data': {\n                    'public_hash': this.publicHash\n                }\n            };\n\n            data['additional_data'] = _.extend(data['additional_data'], this.additionalData);\n\n            return data;\n        }\n    });\n});\n","PayPal_Braintree/js/view/payment/method-renderer/ach.js":"define(\n    [\n        'Magento_Checkout/js/view/payment/default',\n        'ko',\n        'jquery',\n        'braintree',\n        'braintreeDataCollector',\n        'braintreeAch',\n        'PayPal_Braintree/js/form-builder',\n        'Magento_Ui/js/model/messageList',\n        'Magento_Checkout/js/action/select-billing-address',\n        'Magento_Checkout/js/model/full-screen-loader',\n        'Magento_Checkout/js/model/quote',\n        'mage/translate',\n        'Magento_Vault/js/view/payment/vault-enabler',\n        'underscore'\n    ],\n    function (\n        Component,\n        ko,\n        $,\n        braintree,\n        dataCollector,\n        ach,\n        formBuilder,\n        messageList,\n        selectBillingAddress,\n        fullScreenLoader,\n        quote,\n        $t,\n        VaultEnabler,\n        _\n    ) {\n        'use strict';\n\n        return Component.extend({\n            defaults: {\n                deviceData: null,\n                paymentMethodNonce: null,\n                template: 'PayPal_Braintree/payment/ach',\n                achInstance: null,\n                routingNumber: ko.observable(''),\n                accountNumber: ko.observable(''),\n                accountType: ko.observable('checking'),\n                ownershipType: ko.observable('personal'),\n                firstName: ko.observable(''),\n                lastName: ko.observable(''),\n                businessName: ko.observable(''),\n                hasAuthorization: ko.observable(false),\n                business: ko.observable(false), // for ownership type\n                personal: ko.observable(true), // for ownership type\n                vaultEnabler: null\n            },\n\n            clickAchBtn: function () {\n                if (!this.validateForm('#' + this.getCode() + '-form')) {\n                    return;\n                }\n\n                fullScreenLoader.startLoader();\n\n                let self = this,\n\n                    billingAddress = quote.billingAddress(),\n\n                    regionCode,\n\n                    bankDetails = {\n                        routingNumber: self.routingNumber(),\n                        accountNumber: self.accountNumber(),\n                        accountType: self.accountType(),\n                        ownershipType: self.ownershipType(),\n                        billingAddress: {\n                            streetAddress: billingAddress.street[0],\n                            extendedAddress: billingAddress.street[1],\n                            locality: billingAddress.city,\n                            region: billingAddress.regionCode,\n                            postalCode: billingAddress.postcode\n                        }\n                    },\n\n                    mandateText = document.getElementById(self.isVaultActive()\n                        ? 'braintree-ach-mandate-vault'\n                        : 'braintree-ach-mandate'\n                    ).textContent;\n\n                if (bankDetails.ownershipType === 'personal') {\n                    bankDetails.firstName = self.firstName();\n                    bankDetails.lastName = self.lastName();\n                } else {\n                    bankDetails.businessName = self.businessName();\n                }\n\n                // if no region code is available, lets find one!\n                if (typeof billingAddress.regionCode === 'undefined') {\n                    $.get('/rest/V1/directory/countries/' + billingAddress.countryId).done(function (data) {\n                        if (typeof data.available_regions !== 'undefined') {\n                            data.available_regions.forEach(function (availableRegion) {\n                                if (availableRegion.id === billingAddress.regionId) {\n                                    regionCode = availableRegion.code;\n                                    bankDetails.billingAddress.region = regionCode;\n                                    self.tokenizeAch(bankDetails, mandateText);\n                                }\n                            });\n                        } else {\n                            fullScreenLoader.stopLoader();\n                            self.tokenizeAch(bankDetails, mandateText);\n                        }\n                    }).fail(function () {\n                        fullScreenLoader.stopLoader();\n                    });\n                } else {\n                    self.tokenizeAch(bankDetails, mandateText);\n                }\n            },\n\n            tokenizeAch: function (bankDetails, mandateText) {\n                let self = this;\n\n                self.achInstance.tokenize({\n                    bankDetails: bankDetails,\n                    mandateText: mandateText\n                }, function (tokenizeErr, tokenizedPayload) {\n                    if (tokenizeErr) {\n                        let error = 'There was an error with the provided bank details. Please check and try again.';\n\n                        self.setErrorMsg($t(error));\n                        self.hasAuthorization(false);\n                        fullScreenLoader.stopLoader();\n                    } else {\n                        fullScreenLoader.stopLoader();\n                        self.handleAchSuccess(tokenizedPayload);\n                    }\n                });\n            },\n\n            getClientToken: function () {\n                return window.checkoutConfig.payment[this.getCode()].clientToken;\n            },\n\n            getCode: function () {\n                return 'braintree_ach_direct_debit';\n            },\n\n            getStoreName: function () {\n                return window.checkoutConfig.payment[this.getCode()].storeName;\n            },\n\n            getData: function () {\n                let data = {\n                    'method': this.getCode(),\n                    'additional_data': {\n                        'payment_method_nonce': this.paymentMethodNonce,\n                        'device_data': this.deviceData\n                    }\n                };\n\n                data['additional_data'] = _.extend(data['additional_data'], this.additionalData);\n                this.vaultEnabler.visitAdditionalData(data);\n\n                return data;\n            },\n\n            getTitle: function () {\n                return 'ACH Direct Debit';\n            },\n\n            handleAchSuccess: function (payload) {\n                this.setPaymentMethodNonce(payload.nonce);\n                this.placeOrder();\n            },\n\n            initialize: function () {\n                this._super();\n                this.vaultEnabler = new VaultEnabler();\n                this.vaultEnabler.setPaymentCode(this.getVaultCode());\n\n                let self = this;\n\n                this.vaultEnabler.isActivePaymentTokenEnabler.subscribe(function () {\n                    self.achInstance.teardown(function () {\n                        self.initAch();\n                    });\n                });\n\n                this.initAch();\n\n                return this;\n            },\n\n            isAllowed: function () {\n                return window.checkoutConfig.payment[this.getCode()].isAllowed;\n            },\n\n            /**\n             * Change the account type.\n             *\n             * @param data\n             * @param event\n             */\n            changeOwnershipType: function (data, event) {\n                let self = this;\n\n                if (event.currentTarget.value === 'business') {\n                    self.business(true);\n                    self.personal(false);\n                } else {\n                    self.business(false);\n                    self.personal(true);\n                }\n            },\n\n            /**\n             * Is Business type account.\n             *\n             * @returns {Boolean}\n             */\n            isBusiness: function () {\n                return this.business;\n            },\n\n            /**\n             * Is Personal type account.\n             *\n             * @returns {Boolean}\n             */\n            isPersonal: function () {\n                return this.personal;\n            },\n\n            /**\n             * Get the account holder name input.\n             *\n             * @returns {String}\n             */\n            getAccountHolderName: function () {\n                if (this.firstName() !== '' || this.lastName() !== '') {\n                    return this.firstName() + ' ' + this.lastName();\n                }\n\n                return 'XXXX';\n            },\n\n            /**\n             * Get the account number input.\n             *\n             * @returns {String}\n             */\n            getAccountNumber: function () {\n                return this.accountNumber() !== '' ? this.accountNumber() : 'XXXX';\n            },\n\n            /**\n             * Get the Bank Routing Number input.\n             *\n             * @returns {String}\n             */\n            getRoutingNumber: function () {\n                return this.routingNumber() !== '' ? this.routingNumber() : 'XXXX';\n            },\n\n            /**\n             * Get the quote totals value.\n             *\n             * @returns {String}\n             */\n            getGrandTotal: function () {\n                let totals = quote.getTotals()();\n\n                if (totals) {\n                    return totals['grand_total'];\n                }\n\n                return quote['grand_total'];\n            },\n\n            /**\n             * Get the current date in US format (ACH is US only).\n             *\n             * @returns {String}\n             */\n            getCurrentDate: function () {\n                const today = new Date();\n\n                return today.toLocaleDateString('en-US');\n            },\n\n            setErrorMsg: function (message) {\n                messageList.addErrorMessage({\n                    message: message\n                });\n            },\n\n            setPaymentMethodNonce: function (nonce) {\n                this.paymentMethodNonce = nonce;\n            },\n\n            /**\n             * Set the ACH instance.\n             *\n             * @param {*} instance\n             */\n            setAchInstance: function (instance) {\n                this.achInstance = instance;\n            },\n\n            /**\n             * Validate ACH form.\n             *\n             * @param {*} form\n             * @returns {*|jQuery}\n             */\n            validateForm: function (form) {\n                return $(form).validation() && $(form).validation('isValid');\n            },\n\n            /**\n             * Get ACH's should vault checkbox element ID.\n             *\n             * @returns {String}\n             */\n            getVaultCheckboxId: function () {\n                return this.getCode() + '_enable_vault';\n            },\n\n            /**\n             * Check whether Vault is enabled.\n             *\n             * @returns {Boolean}\n             */\n            isVaultEnabled: function () {\n                return this.vaultEnabler.isVaultEnabled();\n            },\n\n            /**\n             * Is Vault enabled & vaulting payment active (checked)\n             *\n             * @returns {Boolean}\n             */\n            isVaultActive: function () {\n                return this.isVaultEnabled() && this.vaultEnabler.isActivePaymentTokenEnabler();\n            },\n\n            /**\n             * Get ACH vault payment method code.\n             *\n             * @returns {String}\n             */\n            getVaultCode: function () {\n                return window.checkoutConfig.payment[this.getCode()]['vaultCode'];\n            },\n\n            /**\n             * Initialize ACH component.\n             *\n             * @returns {void}\n             */\n            initAch: function () {\n                let self = this;\n\n                braintree.create({\n                    authorization: self.getClientToken()\n                }, function (clientError, clientInstance) {\n                    if (clientError) {\n                        this.setErrorMsg($t('Unable to initialize Braintree Client.'));\n                        return;\n                    }\n\n                    /* Collect device data */\n                    self.collectDeviceData(clientInstance, function () {\n                        /* callback from collectDeviceData */\n                        ach.create({\n                            client: clientInstance\n                        }, function (achErr, achInstance) {\n                            if (achErr) {\n                                self.setErrorMsg($t('Error initializing ACH: %1').replace('%1', achErr));\n                                return;\n                            }\n\n                            self.setAchInstance(achInstance);\n                        });\n                    });\n                });\n            },\n\n            /**\n             * Collect device data.\n             *\n             * @param clientInstance\n             * @param {Function} callback\n             * @returns {void}\n             */\n            collectDeviceData: function (clientInstance, callback) {\n                let self = this;\n\n                dataCollector.create({\n                    client: clientInstance,\n                    paypal: true\n                }, function (dataCollectorErr, dataCollectorInstance) {\n                    if (dataCollectorErr) {\n                        return;\n                    }\n\n                    self.deviceData = dataCollectorInstance.deviceData;\n                    callback();\n                });\n            }\n        });\n    }\n);\n","PayPal_Braintree/js/view/payment/method-renderer/paypal-customer-vault.js":"/**\n * Copyright \u00a9 Magento, Inc. All rights reserved.\n * See COPYING.txt for license details.\n */\n/*browser:true*/\ndefine([\n    'jquery',\n    'underscore',\n    'mage/translate',\n    'braintree',\n    'braintreeDataCollector',\n    'braintreePayPalCheckout',\n    'PayPal_Braintree/js/helper/format-amount',\n    'PayPal_Braintree/js/helper/remove-non-digit-characters',\n    'PayPal_Braintree/js/helper/replace-unsupported-characters',\n    'Magento_Checkout/js/action/create-billing-address',\n    'Magento_Checkout/js/action/select-billing-address',\n    'Magento_Checkout/js/model/full-screen-loader',\n    'Magento_Checkout/js/model/quote',\n    'Magento_Checkout/js/model/payment/additional-validators',\n    'Magento_CheckoutAgreements/js/view/checkout-agreements',\n    'Magento_Vault/js/view/payment/method-renderer/vault',\n    'Magento_Ui/js/model/messageList'\n], function (\n    $,\n    _,\n    $t,\n    client,\n    dataCollector,\n    paypalCheckout,\n    formatAmount,\n    removeNonDigitCharacters,\n    replaceUnsupportedCharacters,\n    createBillingAddress,\n    selectBillingAddress,\n    fullScreenLoader,\n    quote,\n    additionalValidators,\n    checkoutAgreements,\n    VaultComponent,\n    globalMessageList\n) {\n    'use strict';\n\n    return VaultComponent.extend({\n        defaults: {\n            template: 'PayPal_Braintree/payment/paypal/customer-vault',\n\n            /**\n             * Component config set via provider.\n             */\n            code: null,\n            nonceUrl: null,\n            publicHash: null,\n            clientToken: null,\n            clientInstance: null,\n            checkout: null,\n            details: {},\n\n            /**\n             * {Object}\n             */\n            events: {\n                onClick: null,\n                onCancel: null,\n                onError: null,\n                onRender: null\n            },\n\n            /**\n             * Additional payment data\n             *\n             * {Object}\n             */\n            additionalData: {},\n\n            /**\n             * Placeholders for PayPal instance vaulted payment.\n             */\n            paypalInstance: null,\n            paymentMethodNonce: null,\n            grandTotalAmount: null,\n            isReviewRequired: false,\n            customerEmail: null,\n\n            /**\n             * {Array}\n             */\n            lineItemsArray: [\n                'name',\n                'kind',\n                'quantity',\n                'unitAmount',\n                'productCode',\n                'description'\n            ],\n\n            /**\n             * PayPal client configuration\n             *\n             * {Object}\n             */\n            clientConfig: {\n                dataCollector: {\n                    paypal: true\n                },\n\n                /**\n                 * Triggers when widget is loaded\n                 */\n                onReady: function () {\n                    this.setupPayPal();\n                },\n\n                /**\n                 * Triggers on payment nonce receive\n                 * @param {Object} response\n                 */\n                onPaymentMethodReceived: function (response) {\n                    this.beforePlaceOrder(response);\n                }\n            },\n\n            imports: {\n                onActiveChange: 'active'\n            }\n        },\n\n        /**\n         * Set list of observable attributes\n         *\n         * @returns {exports.initObservable}\n         */\n        initObservable: function () {\n            let self = this;\n\n            this._super().observe(['active', 'isReviewRequired', 'customerEmail']);\n\n            window.addEventListener('hashchange', function (e) {\n                let methodCode = quote.paymentMethod();\n\n                if (methodCode && methodCode.method === self.getId()) {\n                    if (e.newURL.indexOf('payment') > 0 && self.grandTotalAmount !== null) {\n                        self.reInitPayPalVault();\n                    }\n                }\n            });\n\n            quote.paymentMethod.subscribe(function (value) {\n                if (value.method && value.method === self.getId()) {\n                    self.reInitPayPalVault();\n                }\n            });\n\n            self.grandTotalAmount = quote.totals()['base_grand_total'];\n\n            quote.totals.subscribe(function () {\n                if (self.grandTotalAmount !== quote.totals()['base_grand_total']) {\n                    self.grandTotalAmount = quote.totals()['base_grand_total'];\n                    let methodCode = quote.paymentMethod();\n\n                    if (methodCode && methodCode.method === self.getId()) {\n                        self.reInitPayPalVault();\n                    }\n                }\n            });\n\n            self.isReviewRequired(false);\n            self.initClientConfig();\n\n            return this;\n        },\n\n        /**\n         * Triggers when payment method change\n         *\n         * @param {Boolean} isActive\n         */\n        onActiveChange: function (isActive) {\n            if (!isActive) {\n                return;\n            }\n\n            // need always re-init Braintree with PayPal configuration\n            this.reInitPayPalVault();\n        },\n\n        /**\n         * Init config\n         */\n        initClientConfig: function () {\n            this.clientConfig = _.extend(this.clientConfig, this.getPayPalConfig());\n\n            _.each(this.clientConfig, function (fn, name) {\n                if (typeof fn === 'function') {\n                    this.clientConfig[name] = fn.bind(this);\n                }\n            }, this);\n        },\n\n        /**\n         * Get configuration for PayPal\n         *\n         * @returns {Object}\n         */\n        getPayPalConfig: function () {\n            let totals = quote.totals(),\n                config = {};\n\n            config.paypal = {\n                flow: 'checkout',\n                amount: formatAmount(this.grandTotalAmount),\n                currency: totals['base_currency_code'],\n                locale: this.getLocale(),\n\n                /**\n                 * Triggers on any Braintree error\n                 */\n                onError: function () {\n                    this.paymentMethodNonce = null;\n                },\n\n                /**\n                 * Triggers if browser doesn't support PayPal Checkout\n                 */\n                onUnsupported: function () {\n                    this.paymentMethodNonce = null;\n                }\n            };\n\n            if (!quote.isVirtual()) {\n                config.paypal.enableShippingAddress = true;\n                config.paypal.shippingAddressEditable = false;\n                config.paypal.shippingAddressOverride = this.getShippingAddress();\n            }\n\n            if (this.getMerchantName()) {\n                config.paypal.displayName = this.getMerchantName();\n            }\n\n            return config;\n        },\n\n        /**\n         * Re-init PayPal Vault Auth Flow\n         */\n        reInitPayPalVault: function () {\n            this.disableButton();\n            this.clientConfig.paypal.amount = formatAmount(this.grandTotalAmount);\n\n            if (!quote.isVirtual()) {\n                this.clientConfig.paypal.enableShippingAddress = true;\n                this.clientConfig.paypal.shippingAddressEditable = false;\n                this.clientConfig.paypal.shippingAddressOverride = this.getShippingAddress();\n            }\n\n            // Send Line Items\n            this.clientConfig.paypal.lineItems = this.getLineItems();\n\n            if (this.getPayPalInstance()) {\n                this.getPayPalInstance().teardown(function () {\n                    this.setPayPalInstance(null);\n                    this.createClientInstance(null);\n                }.bind(this));\n            } else {\n                this.createClientInstance(null);\n                this.enableButton();\n            }\n        },\n\n        /**\n         * Get the current Braintree client instance.\n         *\n         * Null if not set.\n         *\n         * @return {*|null}\n         */\n        getClientInstance: function () {\n            if (typeof this.clientInstance !== 'undefined' && this.clientInstance) {\n                return this.clientInstance;\n            }\n\n            return null;\n        },\n\n        /**\n         * Set the Braintree client instance or null it.\n         *\n         * @param val\n         */\n        setClientInstance: function (val) {\n            this.clientInstance = val;\n        },\n\n        /**\n         * Get the PayPal instance if already instantiated, otherwise null.\n         *\n         * @return {*|null}\n         */\n        getPayPalInstance: function () {\n            if (typeof this.paypalInstance !== 'undefined' && this.paypalInstance) {\n                return this.paypalInstance;\n            }\n\n            return null;\n        },\n\n        /**\n         * Set the PayPal instance or null it by setting the value of the property.\n         *\n         * @param val\n         */\n        setPayPalInstance: function (val) {\n            this.paypalInstance = val;\n        },\n\n        /**\n         * Create the Braintree client instance.\n         *\n         * @param {Function|null} callback\n         */\n        createClientInstance: function (callback = null) {\n            if (this.getClientToken() === null) {\n                this.showError($t('Sorry, but something went wrong.'));\n                return;\n            }\n\n            if (this.getClientInstance()) {\n                if (typeof this.clientConfig.onReady === 'function') {\n                    this.clientConfig.onReady(this);\n                }\n\n                if (typeof callback === 'function') {\n                    callback(this.clientInstance);\n                }\n\n                return;\n            }\n\n            client.create({\n                authorization: this.getClientToken()\n            }, function (clientErr, clientInstance) {\n                if (clientErr) {\n                    console.error('Braintree Setup Error', clientErr);\n                    return this.showError('Sorry, but something went wrong. Please contact the store owner.');\n                }\n\n                let options = {\n                    client: clientInstance\n                };\n\n                if (typeof this.clientConfig.dataCollector === 'object'\n                    && typeof this.clientConfig.dataCollector.paypal === 'boolean')\n                {\n                    options.paypal = true;\n                }\n\n                dataCollector.create(options, function (err, dataCollectorInstance) {\n                    if (err) {\n                        return console.log(err);\n                    }\n                    this.additionalData['device_data'] = dataCollectorInstance.deviceData;\n                }.bind(this));\n\n                this.setClientInstance(clientInstance);\n\n                if (typeof this.clientConfig.onReady === 'function') {\n                    this.clientConfig.onReady(this);\n                }\n\n                if (typeof callback === 'function') {\n                    callback(this.getClientInstance());\n                }\n            }.bind(this));\n        },\n\n        /**\n         * Get Environment\n         *\n         * @returns {String}\n         */\n        getEnvironment: function () {\n            return window.checkoutConfig.payment['braintree_paypal'].environment;\n        },\n\n        /**\n         * Setup PayPal instance\n         */\n        setupPayPal: function () {\n            if (this.getPayPalInstance()) {\n                fullScreenLoader.stopLoader(true);\n                return;\n            }\n\n            paypalCheckout.create({\n                autoSetDataUserIdToken: true,\n                client: this.getClientInstance()\n            }, function (createErr, paypalCheckoutInstance) {\n                if (createErr) {\n                    this.showError(\n                        $t('PayPal Checkout could not be initialized. Please contact the store owner.')\n                    );\n                    console.error('paypalCheckout error', createErr);\n                    return;\n                }\n\n                let quoteObj = quote.totals(),\n\n                    configSDK = {\n                        components: 'buttons,messages,funding-eligibility',\n                        'enable-funding': 'paylater',\n                        currency: quoteObj['base_currency_code']\n                    },\n\n                    buyerCountry = this.getMerchantCountry();\n\n                if (this.getEnvironment() === 'sandbox' && buyerCountry !== null) {\n                    configSDK['buyer-country'] = buyerCountry;\n                }\n\n                paypalCheckoutInstance.loadPayPalSDK(configSDK, function () {\n                    this.loadPayPalButton(paypalCheckoutInstance, 'paypal');\n\n                    if (this.isPayLaterEnabled()) {\n                        this.loadPayPalButton(paypalCheckoutInstance, 'paylater');\n                    }\n                }.bind(this));\n            }.bind(this));\n        },\n\n        /**\n         * Load PayPal buttons\n         *\n         * @param paypalCheckoutInstance\n         * @param funding\n         */\n        loadPayPalButton: function (paypalCheckoutInstance, funding) {\n            let paypalPayment = this.clientConfig.paypal,\n                onPaymentMethodReceived = this.clientConfig.onPaymentMethodReceived,\n\n                style = {\n                    label: this.getLabelByFunding(funding),\n                    color: this.getColorByFunding(funding),\n                    shape: this.getShapeByFunding(funding)\n                },\n\n                payPalButtonId = this.getButtonIdByFunding(funding),\n                payPalButtonElement = $('#' + payPalButtonId),\n                button,\n                events = this.events;\n\n            payPalButtonElement.html('');\n\n            // Render\n            this.setPayPalInstance(paypalCheckoutInstance);\n\n            button = window.paypal.Buttons({\n                fundingSource: funding,\n                env: this.getEnvironment(),\n                style: style,\n                commit: true,\n                locale: this.clientConfig.paypal.locale,\n\n                onInit: function (data, actions) {\n                    let agreements = checkoutAgreements().agreements,\n                        shouldDisableActions = false;\n\n                    actions.disable();\n\n                    _.each(agreements, function (item) {\n                        if (checkoutAgreements().isAgreementRequired(item)) {\n                            let paymentMethodCode = quote.paymentMethod().method,\n                                inputId = '#agreement_' + paymentMethodCode + '_' + item.agreementId,\n                                inputEl = document.querySelector(inputId);\n\n                            if (!inputEl.checked) {\n                                shouldDisableActions = true;\n                            }\n\n                            inputEl.addEventListener('change', function () {\n                                if (additionalValidators.validate(false)) {\n                                    actions.enable();\n                                } else {\n                                    actions.disable();\n                                }\n                            });\n                        }\n                    });\n\n                    if (!shouldDisableActions) {\n                        actions.enable();\n                    }\n                },\n\n                createOrder: function () {\n                    return paypalCheckoutInstance.createPayment(paypalPayment).catch(function (err) {\n                        throw err.details.originalError.details.originalError.paymentResource;\n                    });\n                },\n\n                onCancel: function (data) {\n                    console.log('checkout.js payment cancelled', JSON.stringify(data, 0, 2));\n\n                    if (typeof events.onCancel === 'function') {\n                        events.onCancel();\n                    }\n                },\n\n                onError: function (err) {\n                    if (err.errorName === 'VALIDATION_ERROR'\n                        && err.errorMessage.indexOf('Value is invalid') !== -1\n                    ) {\n                        this.showError(\n                            $t('Address failed validation. Please check and confirm your City, State, and Postal Code')\n                        );\n                    } else {\n                        this.showError($t('PayPal Checkout could not be initialized. Please contact the store owner.'));\n                    }\n\n                    this.setPayPalInstance(null);\n                    console.error('Paypal checkout.js error', err);\n\n                    if (typeof events.onError === 'function') {\n                        events.onError(err);\n                    }\n                }.bind(this),\n\n                onClick: function (data) {\n                    if (!quote.isVirtual()) {\n                        this.clientConfig.paypal.enableShippingAddress = true;\n                        this.clientConfig.paypal.shippingAddressEditable = false;\n                        this.clientConfig.paypal.shippingAddressOverride = this.getShippingAddress();\n                    }\n\n                    // To check term & conditions input checked - validate additional validators.\n                    if (!additionalValidators.validate(false)) {\n                        return false;\n                    }\n\n                    if (typeof events.onClick === 'function') {\n                        events.onClick(data);\n                    }\n                }.bind(this),\n\n                onApprove: function (data) {\n                    return paypalCheckoutInstance.tokenizePayment(data)\n                        .then(function (payload) {\n                            onPaymentMethodReceived(payload);\n                        });\n                }\n\n            });\n\n            if (button.isEligible() && payPalButtonElement.length) {\n                button.render('#' + payPalButtonId).then(function () {\n                    this.enableButton();\n\n                    if (typeof this.clientConfig.onPaymentMethodError === 'function') {\n                        this.clientConfig.onPaymentMethodError();\n                    }\n                }.bind(this)).then(function (data) {\n                    if (typeof events.onRender === 'function') {\n                        events.onRender(data);\n                    }\n                });\n            }\n        },\n\n        /**\n         * Prepare data to place order\n         *\n         * @param {Object} data\n         */\n        beforePlaceOrder: function (data) {\n            this.setPaymentMethodNonce(data.nonce);\n            this.customerEmail(data.details.email);\n            if (quote.isVirtual()) {\n                this.isReviewRequired(true);\n            } else if (this.isRequiredBillingAddress() === '1' || quote.billingAddress() === null) {\n                if (typeof data.details.billingAddress !== 'undefined') {\n                    this.setBillingAddress(data.details, data.details.billingAddress);\n                } else {\n                    this.setBillingAddress(data.details, data.details.shippingAddress);\n                }\n            } else if (quote.shippingAddress() === quote.billingAddress()) {\n                selectBillingAddress(quote.shippingAddress());\n            } else {\n                selectBillingAddress(quote.billingAddress());\n            }\n            this.placeOrder();\n        },\n\n        /**\n         * Get the component's client token.\n         *\n         * @return {String}\n         */\n        getClientToken: function () {\n            return this.clientToken;\n        },\n\n        /**\n         * Get merchant country\n         *\n         * @returns {*}\n         */\n        getMerchantCountry: function () {\n            return _.get(window.checkoutConfig.payment, ['braintree_paypal', 'merchantCountry'], null);\n        },\n\n        /**\n         * Get PayPal payer email\n         *\n         * @returns {String}\n         */\n        getPayerEmail: function () {\n            return this.details.payerEmail;\n        },\n\n        /**\n         * Get type of payment\n         *\n         * @returns {String}\n         */\n        getPaymentIcon: function () {\n            return window.checkoutConfig.payment['braintree_paypal'].paymentIcon;\n        },\n\n        /**\n         * Get merchant name\n         *\n         * @returns {String}\n         */\n        getMerchantName: function () {\n            return window.checkoutConfig.payment['braintree_paypal'].merchantName;\n        },\n\n        /**\n         * Get payment method data\n         *\n         * @returns {Object}\n         */\n        getData: function () {\n            let data = {\n                'method': this.code,\n                'additional_data': {\n                    'public_hash': this.publicHash,\n                    'payment_method_nonce': this.paymentMethodNonce\n                }\n            };\n\n            data['additional_data'] = _.extend(data['additional_data'], this.additionalData);\n\n            return data;\n        },\n\n        /**\n         * Set payment nonce.\n         *\n         * @param {String} paymentMethodNonce\n         */\n        setPaymentMethodNonce: function (paymentMethodNonce) {\n            this.paymentMethodNonce = paymentMethodNonce;\n        },\n\n        /**\n         * Get shipping address\n         *\n         * @returns {Object}\n         */\n        getShippingAddress: function () {\n            let address = quote.shippingAddress();\n\n            return {\n                recipientName: address.firstname + ' ' + address.lastname,\n                line1: address.street[0],\n                line2: typeof address.street[2] === 'undefined'\n                    ? address.street[1]\n                    : address.street[1] + ' ' + address.street[2],\n                city: address.city,\n                countryCode: address.countryId,\n                postalCode: address.postcode,\n                state: address.regionCode\n            };\n        },\n\n        /**\n         * Update quote billing address\n         *\n         * @param {Object}customer\n         * @param {Object}address\n         */\n        setBillingAddress: function (customer, address) {\n            let billingAddress = {\n                street: [address.line1],\n                city: address.city,\n                postcode: address.postalCode,\n                countryId: address.countryCode,\n                email: customer.email,\n                firstname: customer.firstName,\n                lastname: customer.lastName,\n                telephone: removeNonDigitCharacters(_.get(customer, 'phone', '00000000000'))\n            };\n\n            billingAddress['region_code'] = typeof address.state === 'string' ? address.state : '';\n            billingAddress = createBillingAddress(billingAddress);\n            quote.billingAddress(billingAddress);\n        },\n\n        /**\n         * Disable submit button\n         */\n        disableButton: function () {\n            // stop any previous shown loaders\n            fullScreenLoader.stopLoader(true);\n            fullScreenLoader.startLoader();\n            $('[data-button=\"place\"]').attr('disabled', 'disabled');\n        },\n\n        /**\n         * Enable submit button\n         */\n        enableButton: function () {\n            $('[data-button=\"place\"]').removeAttr('disabled');\n            fullScreenLoader.stopLoader(true);\n        },\n\n        /**\n         * Triggers when customer click \"Continue to PayPal\" button\n         */\n        payWithPayPal: function () {\n            if (additionalValidators.validate(false)) {\n                this.checkout.paypal.initAuthFlow();\n            }\n        },\n\n        /**\n         * Get a kebab case formatted string of the component ID (normally with `_`).\n         *\n         * @return {String|null}\n         */\n        getKebabCaseId: function () {\n            if (this.getId() === null) {\n                return null;\n            }\n\n            return this.getId().replace('_', '-');\n        },\n\n        /**\n         * Get the PayPal button placeholder id.\n         *\n         * @returns {String}\n         */\n        getPayPalButtonId: function () {\n            return this.getId() + '_placeholder';\n        },\n\n        /**\n         * Get PayPal Pay Later button placeholder id.\n         *\n         * @returns {String}\n         */\n        getPayLaterButtonId: function () {\n            return this.getId() + '_paylater_placeholder';\n        },\n\n        /**\n         * Check if Pay Later enabled.\n         *\n         * @returns {boolean}\n         */\n        isPayLaterEnabled: function () {\n            return _.get(window.checkoutConfig.payment, ['braintree_paypal_paylater', 'isActive'], false);\n        },\n\n        /**\n         * Check if Pay Later messaging enabled.\n         *\n         * @returns {boolean}\n         */\n        isPayLaterMessageEnabled: function () {\n            return _.get(window.checkoutConfig.payment, ['braintree_paypal_paylater', 'isMessageActive'], false);\n        },\n\n        /**\n         * Get the formatted grand total.\n         *\n         * @return {string}\n         */\n        getGrandTotalAmount: function () {\n            return formatAmount(this.grandTotalAmount);\n        },\n\n        /**\n         * Get locale\n         *\n         * @returns {String}\n         */\n        getLocale: function () {\n            return _.get(window.checkoutConfig.payment, ['braintree_paypal', 'locale'], '');\n        },\n\n        /**\n         * Get PayPal Pay Later Message Layout.\n         *\n         * @returns {string}\n         */\n        getMessagingLayout: function () {\n            return _.get(window.checkoutConfig.payment, ['braintree_paypal_paylater', 'message', 'layout'], '');\n        },\n\n        /**\n         * Get PayPal Pay Later Message Logo.\n         *\n         * @returns {string}\n         */\n        getMessagingLogo: function () {\n            return _.get(window.checkoutConfig.payment, ['braintree_paypal_paylater', 'message', 'logo'], '');\n        },\n\n        /**\n         * Get PayPal Pay Later Message Logo position.\n         *\n         * @returns {string}\n         */\n        getMessagingLogoPosition: function () {\n            return _.get(window.checkoutConfig.payment, ['braintree_paypal_paylater', 'message', 'logo_position'], '');\n        },\n\n        /**\n         * Get PayPal Pay Later Message Text Color.\n         *\n         * @returns {string}\n         */\n        getMessagingTextColor: function () {\n            return _.get(window.checkoutConfig.payment, ['braintree_paypal_paylater', 'message', 'text_color'], '');\n        },\n\n        /**\n         * Is Billing Address required from PayPal side.\n         *\n         * @returns {exports.isRequiredBillingAddress|(function())|boolean|String}\n         */\n        isRequiredBillingAddress: function () {\n            return window.checkoutConfig.payment['braintree_paypal'].isRequiredBillingAddress;\n        },\n\n        /**\n         * Show error message\n         *\n         * @param {String} errorMessage\n         */\n        showError: function (errorMessage) {\n            globalMessageList.addErrorMessage({\n                message: errorMessage\n            });\n            fullScreenLoader.stopLoader(true);\n        },\n\n        /**\n         * Get line items\n         *\n         * @returns {Array}\n         */\n        getLineItems: function () {\n            let self = this,\n                lineItems = [];\n\n            if (this.canSendLineItems()) {\n                let giftWrappingItems = 0,\n                    giftWrappingOrder = 0,\n                    storeCredit = 0,\n                    giftCardAccount = 0,\n                    giftWrappingPrintedCard = 0,\n                    baseDiscountAmount,\n                    baseTaxAmount;\n\n                $.each(quote.totals()['total_segments'], function (segmentsKey, segmentsItem) {\n                    if (segmentsItem['code'] === 'customerbalance') {\n                        storeCredit = formatAmount(Math.abs(segmentsItem['value']).toString());\n                    }\n                    if (segmentsItem['code'] === 'giftcardaccount') {\n                        giftCardAccount = formatAmount(Math.abs(segmentsItem['value']).toString());\n                    }\n                    if (segmentsItem['code'] === 'giftwrapping') {\n                        let extensionAttributes = segmentsItem['extension_attributes'];\n\n                        giftWrappingOrder = extensionAttributes['gw_base_price'];\n                        giftWrappingItems = extensionAttributes['gw_items_base_price'];\n                        giftWrappingPrintedCard = extensionAttributes['gw_card_base_price'];\n                    }\n                });\n\n                $.each(quote.getItems(), function (quoteItemKey, quoteItem) {\n                    if (quoteItem.parent_item_id !== null || quoteItem.price === 0.0) {\n                        return true;\n                    }\n\n                    let itemName = replaceUnsupportedCharacters(quoteItem.name),\n                        itemSku = replaceUnsupportedCharacters(quoteItem.sku),\n\n                        description = '',\n                        itemQty = parseFloat(quoteItem.qty),\n                        itemUnitAmount = parseFloat(quoteItem.price),\n                        lineItemValues,\n                        mappedLineItems;\n\n                    if (itemQty > Math.floor(itemQty) && itemQty < Math.ceil(itemQty)) {\n                        description = 'Item quantity is ' + itemQty.toFixed(2)\n                            + ' and per unit amount is ' + itemUnitAmount.toFixed(2);\n                        itemUnitAmount = parseFloat(itemQty * itemUnitAmount);\n                        itemQty = parseFloat('1');\n                    }\n\n                    lineItemValues = [\n                        itemName,\n                        'debit',\n                        itemQty.toFixed(2),\n                        itemUnitAmount.toFixed(2),\n                        itemSku,\n                        description\n                    ],\n\n                    mappedLineItems = $.map(self.lineItemsArray, function (itemElement, itemIndex) {\n                        return [[\n                            self.lineItemsArray[itemIndex],\n                            lineItemValues[itemIndex]\n                        ]];\n                    });\n\n                    lineItems[quoteItemKey] = Object.fromEntries(mappedLineItems);\n                });\n\n                /**\n                 * Adds credit (refund or discount) kind as LineItems for the\n                 * PayPal transaction if discount amount is greater than 0(Zero)\n                 * as discountAmount lineItem field is not being used by PayPal.\n                 *\n                 * developer.paypal.com/braintree/docs/reference/response/transaction-line-item/php#discount_amount\n                 */\n                baseDiscountAmount = formatAmount(Math.abs(quote.totals()['base_discount_amount']).toString());\n\n                if (baseDiscountAmount > 0) {\n                    let discountLineItem = {\n                        'name': 'Discount',\n                        'kind': 'credit',\n                        'quantity': 1.00,\n                        'unitAmount': baseDiscountAmount\n                    };\n\n                    lineItems = $.merge(lineItems, [discountLineItem]);\n                }\n\n                /**\n                 * Adds shipping as LineItems for the PayPal transaction\n                 * if shipping amount is greater than 0(Zero) to manage\n                 * the totals with client-side implementation as there is\n                 * no any field exist in the client-side implementation\n                 * to send the shipping amount to the Braintree.\n                 */\n                if (quote.totals()['base_shipping_amount'] > 0) {\n                    let shippingLineItem = {\n                        'name': 'Shipping',\n                        'kind': 'debit',\n                        'quantity': 1.00,\n                        'unitAmount': quote.totals()['base_shipping_amount']\n                    };\n\n                    lineItems = $.merge(lineItems, [shippingLineItem]);\n                }\n\n                baseTaxAmount = formatAmount(quote.totals()['base_tax_amount']);\n\n                if (baseTaxAmount > 0) {\n                    let taxLineItem = {\n                        'name': 'Tax',\n                        'kind': 'debit',\n                        'quantity': 1.00,\n                        'unitAmount': baseTaxAmount\n                    };\n\n                    lineItems = $.merge(lineItems, [taxLineItem]);\n                }\n\n                /**\n                 * Adds credit (Store Credit) kind as LineItems for the\n                 * PayPal transaction if store credit is greater than 0(Zero)\n                 * to manage the totals with client-side implementation\n                 */\n                if (storeCredit > 0) {\n                    let storeCreditItem = {\n                        'name': 'Store Credit',\n                        'kind': 'credit',\n                        'quantity': 1.00,\n                        'unitAmount': storeCredit\n                    };\n\n                    lineItems = $.merge(lineItems, [storeCreditItem]);\n                }\n\n                /**\n                 * Adds Gift Wrapping for items as LineItems for the PayPal\n                 * transaction if it is greater than 0(Zero) to manage\n                 * the totals with client-side implementation\n                 */\n                if (giftWrappingItems > 0) {\n                    let gwItems = {\n                        'name': 'Gift Wrapping for Items',\n                        'kind': 'debit',\n                        'quantity': 1.00,\n                        'unitAmount': giftWrappingItems\n                    };\n\n                    lineItems = $.merge(lineItems, [gwItems]);\n                }\n\n                /**\n                 * Adds Gift Wrapping for order as LineItems for the PayPal\n                 * transaction if it is greater than 0(Zero) to manage\n                 * the totals with client-side implementation\n                 */\n                if (giftWrappingOrder > 0) {\n                    let gwOrderItem = {\n                        'name': 'Gift Wrapping for Order',\n                        'kind': 'debit',\n                        'quantity': 1.00,\n                        'unitAmount': giftWrappingOrder\n                    };\n\n                    lineItems = $.merge(lineItems, [gwOrderItem]);\n                }\n\n                /**\n                 * Adds Gift Wrapping Printed Card as LineItems for the PayPal\n                 * transaction if it is greater than 0(Zero) to manage\n                 * the totals with client-side implementation\n                 */\n                if (giftWrappingPrintedCard > 0) {\n                    let gwPrintedCard = {\n                        'name': 'Printed Card',\n                        'kind': 'debit',\n                        'quantity': 1.00,\n                        'unitAmount': giftWrappingPrintedCard\n                    };\n\n                    lineItems = $.merge(lineItems, [gwPrintedCard]);\n                }\n\n                /**\n                 * Adds Gift Cards as credit LineItems for the PayPal\n                 * transaction if it is greater than 0(Zero) to manage\n                 * the totals with client-side implementation\n                 */\n                if (giftCardAccount > 0) {\n                    let giftCardItem = {\n                        'name': 'Gift Cards',\n                        'kind': 'credit',\n                        'quantity': 1.00,\n                        'unitAmount': giftCardAccount\n                    };\n\n                    lineItems = $.merge(lineItems, [giftCardItem]);\n                }\n\n                if (lineItems.length >= 250) {\n                    lineItems = [];\n                }\n            }\n            return lineItems;\n        },\n\n        /**\n         * Can send line items\n         *\n         * @returns {Boolean}\n         */\n        canSendLineItems: function () {\n            return window.checkoutConfig.payment['braintree_paypal'].canSendLineItems;\n        },\n\n        /**\n         * Get the Button ID for the required funding\n         *\n         * @param {string} funding\n         * @return {string}\n         */\n        getButtonIdByFunding: function (funding) {\n            if (funding === 'paylater') {\n                return this.getPayLaterButtonId();\n            }\n\n            return this.getPayPalButtonId();\n        },\n\n        /**\n         * Get the label config associated to the PayPal funding source.\n         *\n         * @param {string} funding\n         * @return {string}\n         */\n        getLabelByFunding: function (funding) {\n            return _.get(\n                window.checkoutConfig.payment,\n                [this.getPaymentMethodCodeByFunding(funding), 'style', 'label'],\n                ''\n            );\n        },\n\n        /**\n         * Get the color config associated to the PayPal funding source.\n         *\n         * @param {string} funding\n         * @return {string}\n         */\n        getColorByFunding: function (funding) {\n            return _.get(\n                window.checkoutConfig.payment,\n                [this.getPaymentMethodCodeByFunding(funding), 'style', 'color'],\n                ''\n            );\n        },\n\n        /**\n         * Get the shape config associated to the PayPal funding source.\n         *\n         * @param {string} funding\n         * @return {string}\n         */\n        getShapeByFunding: function (funding) {\n            return _.get(\n                window.checkoutConfig.payment,\n                [this.getPaymentMethodCodeByFunding(funding), 'style', 'shape'],\n                ''\n            );\n        },\n\n        /**\n         * Get the payment method code related to the PayPal funding source.\n         *\n         * @param {string} funding\n         * @return {string}\n         */\n        getPaymentMethodCodeByFunding: function (funding) {\n            if (funding === 'paylater') {\n                return 'braintree_paypal_paylater';\n            }\n\n            return 'braintree_paypal';\n        }\n    });\n});\n","PayPal_Braintree/js/view/payment/method-renderer/multishipping/hosted-fields.js":"/**\n * Copyright \u00a9 Magento, Inc. All rights reserved.\n * See COPYING.txt for license details.\n */\n/*browser:true*/\n\ndefine([\n    'jquery',\n    'PayPal_Braintree/js/view/payment/method-renderer/hosted-fields',\n    'PayPal_Braintree/js/validator',\n    'Magento_Ui/js/model/messageList',\n    'mage/translate',\n    'Magento_Checkout/js/model/full-screen-loader',\n    'Magento_Checkout/js/action/set-payment-information',\n    'Magento_Checkout/js/model/payment/additional-validators',\n    'PayPal_Braintree/js/view/payment/adapter'\n], function (\n    $,\n    Component,\n    validator,\n    messageList,\n    $t,\n    fullScreenLoader,\n    setPaymentInformationAction,\n    additionalValidators,\n    braintree\n) {\n    'use strict';\n\n    return Component.extend({\n        defaults: {\n            template: 'PayPal_Braintree/payment/multishipping/form'\n        },\n\n        /**\n         * Get list of available CC types\n         *\n         * @returns {Object}\n         */\n        getCcAvailableTypes: function () {\n            let availableTypes = validator.getAvailableCardTypes(),\n                billingCountryId;\n\n            billingCountryId = $('#multishipping_billing_country_id').val();\n\n            if (billingCountryId && validator.getCountrySpecificCardTypes(billingCountryId)) {\n                return validator.collectTypes(\n                    availableTypes, validator.getCountrySpecificCardTypes(billingCountryId)\n                );\n            }\n\n            return availableTypes;\n        },\n\n        /**\n         * @override\n         */\n        handleNonce: function (payload) {\n            let self = this;\n\n            this.setPaymentMethodNonce(payload.nonce);\n            this.setCreditCardBin(payload.details.bin);\n\n            // place order on success validation\n            self.validatorManager.validate(self, function () {\n                return self.setPaymentInformation();\n            }, function () {\n                self.isProcessing = false;\n                self.paymentMethodNonce = null;\n                self.creditCardBin = null;\n            });\n        },\n\n        /**\n         * @override\n         */\n        placeOrder: function () {\n            if (this.isProcessing) {\n                return false;\n            }\n            this.isProcessing = true;\n\n\n            braintree.tokenizeHostedFields();\n            return false;\n        },\n\n        /**\n         * @override\n         */\n        getData: function () {\n            let data = this._super();\n\n            data['additional_data']['is_active_payment_token_enabler'] = true;\n\n            return data;\n        },\n\n        /**\n         * @override\n         */\n        setPaymentInformation: function () {\n            if (additionalValidators.validate()) {\n                fullScreenLoader.startLoader();\n                $.when(\n                    setPaymentInformationAction(\n                        this.messageContainer,\n                        this.getData()\n                    )\n                ).done(this.done.bind(this))\n                    .fail(this.fail.bind(this));\n            }\n        },\n\n        /**\n         * {Function}\n         */\n        fail: function () {\n            fullScreenLoader.stopLoader();\n\n            return this;\n        },\n\n        /**\n         * {Function}\n         */\n        done: function () {\n            fullScreenLoader.stopLoader();\n            $('#multishipping-billing-form').trigger('submit');\n\n            return this;\n        }\n    });\n});\n","PayPal_Braintree/js/view/payment/method-renderer/multishipping/paypal.js":"/**\n * Copyright \u00a9 Magento, Inc. All rights reserved.\n * See COPYING.txt for license details.\n */\n/*browser:true*/\ndefine([\n    'jquery',\n    'underscore',\n    'braintreeCheckoutPayPalAdapter',\n    'Magento_Checkout/js/model/quote',\n    'PayPal_Braintree/js/view/payment/method-renderer/paypal',\n    'PayPal_Braintree/js/helper/format-amount',\n    'Magento_Checkout/js/action/set-payment-information',\n    'Magento_Checkout/js/model/payment/additional-validators',\n    'Magento_Checkout/js/model/full-screen-loader',\n    'mage/translate'\n], function (\n    $,\n    _,\n    Braintree,\n    quote,\n    Component,\n    formatAmount,\n    setPaymentInformationAction,\n    additionalValidators,\n    fullScreenLoader,\n    $t\n) {\n    'use strict';\n\n    return Component.extend({\n        defaults: {\n            template: 'PayPal_Braintree/payment/multishipping/paypal',\n            submitButtonSelector: '[id=\"parent-payment-continue\"]',\n            reviewButtonHtml: ''\n        },\n\n        /**\n         * @override\n         */\n        initObservable: function () {\n            this.reviewButtonHtml = $(this.submitButtonSelector).html();\n            return this._super();\n        },\n\n        initClientConfig: function () {\n            this.clientConfig = _.extend(this.clientConfig, this.getPayPalConfig());\n            this.clientConfig.paypal.enableShippingAddress = false;\n\n            _.each(this.clientConfig, function (fn, name) {\n                if (typeof fn === 'function') {\n                    this.clientConfig[name] = fn.bind(this);\n                }\n            }, this);\n            this.clientConfig.buttonPayPalId = 'parent-payment-continue';\n        },\n\n        /**\n         * @override\n         */\n        onActiveChange: function (isActive) {\n            this.updateSubmitButtonHtml(isActive);\n            this._super(isActive);\n        },\n\n        /**\n         * @override\n         */\n        beforePlaceOrder: function (data) {\n            this._super(data);\n        },\n\n        /**\n         * Re-init PayPal Auth Flow\n         */\n        reInitPayPal: function () {\n            this.disableButton();\n            this.clientConfig.paypal.amount = formatAmount(this.grandTotalAmount);\n\n            if (!quote.isVirtual()) {\n                this.clientConfig.paypal.enableShippingAddress = false;\n                this.clientConfig.paypal.shippingAddressEditable = false;\n            }\n\n            Braintree.setConfig(this.clientConfig);\n\n            if (Braintree.getPayPalInstance()) {\n                Braintree.getPayPalInstance().teardown(function () {\n                    Braintree.setup();\n                });\n                Braintree.setPayPalInstance(null);\n            } else {\n                Braintree.setup();\n                this.enableButton();\n            }\n        },\n\n        loadPayPalButton: function (paypalCheckoutInstance, funding) {\n            if (funding === 'credit') {\n                Braintree.config.buttonId = this.getCreditButtonId();\n            } else if (funding === 'paylater') {\n                Braintree.config.buttonId = this.getPayLaterButtonId();\n            } else {\n                Braintree.config.buttonId = this.getPayPalButtonId();\n            }\n\n            let paypalPayment = Braintree.config.paypal,\n                onPaymentMethodReceived = Braintree.config.onPaymentMethodReceived,\n                style = {\n                    label: Braintree.getLabel(funding),\n                    color: Braintree.getColor(funding),\n                    shape: Braintree.getShape(funding)\n                },\n                payPalButtonId = Braintree.config.buttonId,\n                payPalButtonElement = $('#' + Braintree.config.buttonId),\n                events = Braintree.events,\n\n                button = window.paypal.Buttons({\n                    fundingSource: funding,\n                    env: Braintree.getEnvironment(),\n                    style: style,\n                    commit: true,\n                    locale: Braintree.config.paypal.locale,\n\n                    createOrder: function () {\n                        return paypalCheckoutInstance.createPayment(paypalPayment);\n                    },\n\n                    onCancel: function (data) {\n                        console.log('checkout.js payment cancelled', JSON.stringify(data, 0, 2));\n\n                        if (typeof events.onCancel === 'function') {\n                            events.onCancel();\n                        }\n                    },\n\n                    onError: function (err) {\n                        let error = 'PayPal Checkout could not be initialized. Please contact the store owner.';\n\n                        Braintree.showError($t(error));\n                        Braintree.config.paypalInstance = null;\n                        console.error('Paypal checkout.js error', err);\n\n                        if (typeof events.onError === 'function') {\n                            events.onError(err);\n                        }\n                    },\n\n                    onClick: function (data) {\n                    // To check term & conditions input checked - validate additional validators.\n                        if (!additionalValidators.validate()) {\n                            return false;\n                        }\n\n                        if (typeof events.onClick === 'function') {\n                            events.onClick(data);\n                        }\n                    },\n\n                    onApprove: function (data) {\n                        return paypalCheckoutInstance.tokenizePayment(data)\n                            .then(function (payload) {\n                                onPaymentMethodReceived(payload);\n                            });\n                    }\n                });\n\n            payPalButtonElement.html('');\n\n            // Render\n            Braintree.config.paypalInstance = paypalCheckoutInstance;\n\n            if (button.isEligible() && payPalButtonElement.length) {\n                button.render('#' + payPalButtonId).then(function () {\n                    Braintree.enableButton();\n                    if (typeof Braintree.config.onPaymentMethodError === 'function') {\n                        Braintree.config.onPaymentMethodError();\n                    }\n                }).then(function (data) {\n                    if (typeof events.onRender === 'function') {\n                        events.onRender(data);\n                    }\n                });\n            }\n        },\n\n        /**\n         * Get configuration for PayPal\n         *\n         * @returns {Object}\n         */\n        getPayPalConfig: function () {\n            let totals = quote.totals(),\n                config = {};\n\n            config.paypal = {\n                flow: 'checkout',\n                amount: formatAmount(this.grandTotalAmount),\n                currency: totals['base_currency_code'],\n                locale: this.getLocale(),\n                requestBillingAgreement: true,\n\n                /**\n                 * Triggers on any Braintree error\n                 */\n                onError: function () {\n                    this.paymentMethodNonce = null;\n                },\n\n                /**\n                 * Triggers if browser doesn't support PayPal Checkout\n                 */\n                onUnsupported: function () {\n                    this.paymentMethodNonce = null;\n                }\n            };\n\n            if (!quote.isVirtual()) {\n                config.paypal.enableShippingAddress = false;\n                config.paypal.shippingAddressEditable = false;\n            }\n\n            if (this.getMerchantName()) {\n                config.paypal.displayName = this.getMerchantName();\n            }\n\n            return config;\n        },\n\n        /**\n         * Get shipping address\n         *\n         * @returns {{}}\n         */\n        getShippingAddress: function () {\n            return {};\n        },\n\n        /**\n         * @override\n         */\n        getData: function () {\n            let data = this._super();\n\n            data['additional_data']['is_active_payment_token_enabler'] = true;\n\n            return data;\n        },\n\n        /**\n         * @override\n         */\n        isActiveVault: function () {\n            return true;\n        },\n\n        /**\n         * Checks if payment method nonce is already received.\n         *\n         * @returns {Boolean}\n         */\n        isPaymentMethodNonceReceived: function () {\n            return this.paymentMethodNonce !== null;\n        },\n\n        /**\n         * Update submit button on multi-addresses checkout billing form.\n         *\n         * @param {Boolean} isActive\n         */\n        updateSubmitButtonHtml: function (isActive) {\n            $(this.submitButtonSelector).removeClass('primary');\n            if (this.isPaymentMethodNonceReceived() || !isActive) {\n                $(this.submitButtonSelector).addClass('primary');\n                $(this.submitButtonSelector).html(this.reviewButtonHtml);\n            }\n        },\n\n        /**\n         * @override\n         */\n        placeOrder: function () {\n            if (!this.isPaymentMethodNonceReceived()) {\n                this.payWithPayPal();\n            } else {\n                fullScreenLoader.startLoader();\n\n                $.when(\n                    setPaymentInformationAction(\n                        this.messageContainer,\n                        this.getData()\n                    )\n                ).done(this.done.bind(this))\n                    .fail(this.fail.bind(this));\n            }\n        },\n\n        /**\n         * {Function}\n         */\n        fail: function () {\n            fullScreenLoader.stopLoader();\n\n            return this;\n        },\n\n        /**\n         * {Function}\n         */\n        done: function () {\n            fullScreenLoader.stopLoader();\n            $('#multishipping-billing-form').trigger('submit');\n\n            return this;\n        }\n    });\n});\n","PayPal_Braintree/js/view/payment/express/express-payment.js":"/**\n * General express payment component that initializes braintree payment buttons\n */\ndefine([\n    'jquery',\n    'uiComponent',\n    'domReady!'\n], function ($, Component) {\n    'use strict';\n\n    return Component.extend({\n        defaults: {\n            template: 'PayPal_Braintree/express/express-payment'\n        },\n\n        /**\n         * Initializes regular properties of instance.\n         *\n         * @returns {Object} Chainable.\n         */\n        initConfig: function () {\n            this._super();\n\n            return this;\n        }\n    });\n});\n","PayPal_Braintree/js/view/payment/express/express-paypal.js":"/**\n * Express Paypal button component\n */\n\ndefine([\n    'jquery',\n    'underscore',\n    'uiComponent',\n    'mage/url',\n    'PayPal_Braintree/js/paypal/button',\n    'PayPal_Braintree/js/helper/get-cart-line-items-helper',\n    'domReady!'\n], function ($, _, Component, url, paypalButton, getCartLineItems) {\n    'use strict';\n\n    const config = _.get(window.checkoutConfig.payment, 'braintree_paypal', {});\n\n    return Component.extend({\n        defaults: {\n            template: 'PayPal_Braintree/express/express-paypal',\n            isActive: _.get(config, 'isActive', false),\n            clientToken: _.get(config, 'clientToken', null),\n            checkoutCurrency: window.checkoutConfig.quoteData.base_currency_code,\n            checkoutAmount: window.checkoutConfig.quoteData.base_grand_total,\n            checkoutLocale: _.get(config, 'locale', null),\n            buttonLabel: _.get(config, ['style', 'label'], null),\n            buttonColor: _.get(config, ['style', 'color'], null),\n            buttonShape: _.get(config, ['style', 'shape'], null),\n            actionSuccess: url.build('braintree/paypal/review/')\n        },\n\n        /**\n         * Initializes regular properties of instance.\n         *\n         * @returns {Object} Chainable.\n         */\n        initConfig: function () {\n            this._super();\n\n            return this;\n        },\n\n        /**\n         * Is the payment method active.\n         *\n         * @return {boolean}\n         */\n        isMethodActive: function () {\n            return this.isActive;\n        },\n\n        /**\n         * Is Billing address required.\n         *\n         * @return {string}\n         */\n        getIsRequiredBillingAddress: function () {\n            return _.get(config, 'isRequiredBillingAddress', '0') === '0' ? '' : 'true';\n        },\n\n        /**\n         * Get the merchant's name config.\n         *\n         * @return {string}\n         */\n        getMerchantName: function () {\n            return _.get(config, 'merchantName', '');\n        },\n\n        /**\n         * Initialize Braintree PayPal buttons.\n         *\n         * PayPal Credit & PayPal Pay Later & PayPal Pay Later Messaging rely on PayPal to be enabled.\n         */\n        initPayPalButtons: function () {\n            if (!this.isMethodActive() || !this.clientToken) {\n                return;\n            }\n\n            let buttonConfig = {\n                    'clientToken': this.clientToken,\n                    'currency': this.checkoutCurrency,\n                    'environment': config.environment,\n                    'merchantCountry': config.merchantCountry,\n                    'isCreditActive': _.get(window.checkoutConfig.payment,\n                        ['braintree_paypal_credit', 'isActive'], false)\n                },\n\n                cartLineItems = getCartLineItems();\n\n            paypalButton.init(\n                buttonConfig,\n                JSON.stringify(cartLineItems)\n            );\n        }\n    });\n});\n","PayPal_Braintree/js/view/payment/express/express-paypal-paylater.js":"/**\n * Express PayLater button component\n */\ndefine([\n    'jquery',\n    'underscore',\n    'uiComponent',\n    'mage/url',\n    'domReady!'\n], function ($, _, Component, url) {\n    'use strict';\n\n    const config = _.get(window.checkoutConfig.payment, 'braintree_paypal_paylater', {});\n\n    return Component.extend({\n        defaults: {\n            template: 'PayPal_Braintree/express/express-paypal-paylater',\n            isActive: _.get(config, 'isActive', false),\n            checkoutCurrency: window.checkoutConfig.quoteData.base_currency_code,\n            checkoutAmount: window.checkoutConfig.quoteData.base_grand_total,\n            checkoutLocale: _.get(config, 'locale', null),\n            buttonLabel: _.get(config, ['style', 'label'], null),\n            buttonColor: _.get(config, ['style', 'color'], null),\n            buttonShape: _.get(config, ['style', 'shape'], null),\n            actionSuccess: url.build('braintree/paypal/review/'),\n            isMessageActive: _.get(config, 'isMessageActive', false),\n            messageTextColor: _.get(config ,['message', 'text_color'], null),\n            messageLayout: _.get(config ,['message', 'layout'], null),\n            messageLogoPosition: _.get(config ,['message', 'logo_position'], null),\n            messageLogo: _.get(config ,['message', 'logo'], null)\n        },\n\n        /**\n         * Initializes regular properties of instance.\n         *\n         * @returns {Object} Chainable.\n         */\n        initConfig: function () {\n            this._super();\n\n            return this;\n        },\n\n        /**\n         * Is the payment method active.\n         *\n         * @return {boolean}\n         */\n        isMethodActive: function () {\n            return this.isActive;\n        },\n\n        /**\n         * Is the payment method message active.\n         *\n         * @return {boolean}\n         */\n        isMethodMessageActive: function () {\n            return this.isMessageActive;\n        },\n\n        /**\n         * Is Billing address required.\n         *\n         * @return {string}\n         */\n        getIsRequiredBillingAddress: function () {\n            return _.get(config, 'isRequiredBillingAddress', '0') === '0' ? '' : 'true';\n        },\n\n        /**\n         * Get the merchant's name config.\n         *\n         * @return {string}\n         */\n        getMerchantName: function () {\n            return _.get(config, 'merchantName', '');\n        }\n    });\n});\n","PayPal_Braintree/js/view/payment/express/express-googlepay.js":"/**\n * Express GooglePay button component\n */\n\ndefine([\n    'jquery',\n    'underscore',\n    'uiComponent',\n    'mage/url',\n    'PayPal_Braintree/js/googlepay/button',\n    'PayPal_Braintree/js/googlepay/api',\n    'domReady!'\n], function ($, _, Component, url, button, buttonApi) {\n    'use strict';\n\n    const config = _.get(window.checkoutConfig.payment, 'braintree_googlepay', {});\n\n    return Component.extend({\n\n        defaults: {\n            template: 'PayPal_Braintree/express/express-googlepay',\n            id: 'braintree-googlepay-express-payment',\n            isActive: !_.isEmpty(config),\n            clientToken: _.get(config, 'clientToken', null),\n            merchantId: _.get(config, 'merchantId', null),\n            currencyCode: window.checkoutConfig.quoteData.base_currency_code,\n            actionSuccess: url.build('braintree/googlepay/review/'),\n            amount: window.checkoutConfig.quoteData.base_grand_total,\n            environment: _.get(config, 'environment', 'TEST'),\n            cardTypes: _.get(config, 'cardTypes', []),\n            btnColor: _.get(config, 'btnColor', ''),\n            threeDSecure: null\n        },\n\n        /**\n         * Is the payment method active.\n         *\n         * @return {boolean}\n         */\n        isMethodActive: function () {\n            return this.isActive;\n        },\n\n        /**\n         * Get the 3D Secure config object.\n         *\n         * @return {\n        *   {\n        *      thresholdAmount: (number|*),\n        *      specificCountries: ([]|*),\n        *      challengeRequested: (boolean|*),\n        *      enabled: boolean\n        *   } ||\n        *   {\n        *      thresholdAmount: number,\n        *      specificCountries: *[],\n        *      challengeRequested: boolean,\n        *      enabled: boolean\n        *   }\n        * }\n         */\n        get3DSecureConfig: function () {\n            let secureConfig = _.get(window.checkoutConfig.payment, 'three_d_secure', {});\n\n            if (_.isEmpty(secureConfig)) {\n                return {\n                    'enabled': false,\n                    'challengeRequested': false,\n                    'thresholdAmount': 0.0,\n                    'specificCountries': [],\n                    'ipAddress': ''\n                };\n            }\n\n            return {\n                'enabled': true,\n                'challengeRequested': secureConfig.challengeRequested ,\n                'thresholdAmount': secureConfig.thresholdAmount,\n                'specificCountries': secureConfig.specificCountries,\n                'ipAddress': secureConfig.ipAddress\n            };\n        },\n\n        /**\n         * Initialize Google Pay express.\n         */\n        initGooglePayExpress: function () {\n            if (!this.isMethodActive()) {\n                return;\n            }\n\n            this.threeDSecure = this.get3DSecureConfig();\n\n            /* Add client token & environment to 3DS Config */\n            this.threeDSecure.clientToken = this.clientToken;\n            this.threeDSecure.environment = this.environment;\n\n            let api = new buttonApi();\n\n            api.setEnvironment(this.environment);\n            api.setCurrencyCode(this.currencyCode);\n            api.setClientToken(this.clientToken);\n            api.setMerchantId(this.merchantId);\n            api.setActionSuccess(this.actionSuccess);\n            api.setAmount(this.amount);\n            api.setCardTypes(this.cardTypes);\n            api.setBtnColor(this.btnColor);\n            api.setThreeDSecureValidatorConfig(this.threeDSecure);\n\n            // Attach the button\n            button.init(\n                document.getElementById(this.id),\n                api\n            );\n        },\n\n        /**\n         * @returns {Object}\n         */\n        initialize: function () {\n            this._super();\n\n            return this;\n        }\n    });\n});\n","PayPal_Braintree/js/view/payment/express/express-applepay.js":"/**\n * Braintree Apple Pay express payment method integration.\n **/\ndefine([\n    'underscore',\n    'uiComponent',\n    'PayPal_Braintree/js/applepay/button',\n    'PayPal_Braintree/js/applepay/api',\n    'PayPal_Braintree/js/helper/format-amount',\n    'mage/translate',\n    'mage/url',\n    'domReady!'\n], function (\n    _,\n    Component,\n    button,\n    buttonApi,\n    formatAmount,\n    $t,\n    url\n) {\n    'use strict';\n\n    const config = _.get(window.checkoutConfig.payment, 'braintree_applepay', {});\n\n    return Component.extend({\n\n        defaults: {\n            template: 'PayPal_Braintree/express/express-applepay',\n            id: 'braintree-applepay-express-payment',\n            isActive: !_.isEmpty(config),\n            clientToken: _.get(config, 'clientToken', null),\n            quoteId: window.checkoutConfig.quoteId,\n            displayName: _.get(config, 'merchantName', null),\n            actionSuccess: url.build('checkout/onepage/success'),\n            grandTotalAmount: window.checkoutConfig.quoteData.base_grand_total,\n            isLoggedIn: false,\n            storeCode: window.checkoutConfig.storeCode\n        },\n\n        /**\n         * Is the payment method active.\n         *\n         * @return {boolean}\n         */\n        isMethodActive: function () {\n            return this.isActive;\n        },\n\n        /**\n         * Initialize Apple Pay express.\n         */\n        initApplePayExpress: function () {\n            if (!this.isMethodActive() || !this.clientToken) {\n                return;\n            }\n\n            if (!this.displayName) {\n                this.displayName = $t('Store');\n            }\n\n            this.isLoggedIn = window.checkoutConfig.customer_is_guest === '1' ? 'true' : 'false';\n\n            let api = new buttonApi();\n\n            api.setGrandTotalAmount(formatAmount(this.grandTotalAmount));\n            api.setClientToken(this.clientToken);\n            api.setDisplayName(this.displayName);\n            api.setQuoteId(this.quoteId);\n            api.setActionSuccess(this.actionSuccess);\n            api.setIsLoggedIn(this.isLoggedIn);\n            api.setStoreCode(this.storeCode);\n\n            // Attach the button\n            button.init(\n                document.getElementById(this.id),\n                api\n            );\n        },\n\n        /**\n         * @returns {Object}\n         */\n        initialize: function () {\n            this._super();\n\n            return this;\n        }\n    });\n});\n","PayPal_Braintree/js/view/payment/express/express-paypal-credit.js":"/**\n * Express Paypal Credit button component\n */\ndefine([\n    'jquery',\n    'underscore',\n    'uiComponent',\n    'mage/url',\n    'domReady!'\n], function ($, _, Component, url) {\n    'use strict';\n\n    const config = _.get(window.checkoutConfig.payment, 'braintree_paypal_credit', {});\n\n    return Component.extend({\n        defaults: {\n            template: 'PayPal_Braintree/express/express-paypal-credit',\n            isActive: _.get(config, 'isActive', false),\n            checkoutCurrency: window.checkoutConfig.quoteData.base_currency_code,\n            checkoutAmount: window.checkoutConfig.quoteData.base_grand_total,\n            checkoutLocale: _.get(config, 'locale', null),\n            buttonLabel: _.get(config, ['style', 'label'], null),\n            buttonColor: _.get(config, ['style', 'color'], null),\n            buttonShape: _.get(config, ['style', 'shape'], null),\n            actionSuccess: url.build('braintree/paypal/review/')\n        },\n\n        /**\n         * Initializes regular properties of instance.\n         *\n         * @returns {Object} Chainable.\n         */\n        initConfig: function () {\n            this._super();\n\n            return this;\n        },\n\n        /**\n         * Is the payment method active.\n         *\n         * @return {boolean}\n         */\n        isMethodActive: function () {\n            return this.isActive;\n        },\n\n        /**\n         * Is Billing address required.\n         *\n         * @return {string}\n         */\n        getIsRequiredBillingAddress: function () {\n            return _.get(config, 'isRequiredBillingAddress', '0') === '0' ? '' : 'true';\n        },\n\n        /**\n         * Get the merchant's name config.\n         *\n         * @return {string}\n         */\n        getMerchantName: function () {\n            return _.get(config, 'merchantName', '');\n        }\n    });\n});\n","PayPal_Braintree/js/paypal/button.js":"/**\n * Copyright \u00a9 Magento, Inc. All rights reserved.\n * See COPYING.txt for license details.\n */\ndefine(\n    [\n        'rjsResolver',\n        'uiRegistry',\n        'uiComponent',\n        'underscore',\n        'jquery',\n        'Magento_Customer/js/customer-data',\n        'mage/translate',\n        'braintree',\n        'braintreeCheckoutPayPalAdapter',\n        'braintreeDataCollector',\n        'braintreePayPalCheckout',\n        'PayPal_Braintree/js/form-builder',\n        'PayPal_Braintree/js/helper/remove-non-digit-characters',\n        'PayPal_Braintree/js/helper/replace-single-quote-character',\n        'domReady!'\n    ],\n    function (\n        resolver,\n        registry,\n        Component,\n        _,\n        $,\n        customerData,\n        $t,\n        braintree,\n        Braintree,\n        dataCollector,\n        paypalCheckout,\n        formBuilder,\n        removeNonDigitCharacters,\n        replaceSingleQuoteCharacter\n    ) {\n        'use strict';\n\n        return {\n            events: {\n                onClick: null,\n                onCancel: null,\n                onError: null\n            },\n\n            /**\n             * Initialize button\n             *\n             * @param buttonConfig\n             * @param lineItems\n             */\n            init: function (buttonConfig, lineItems) {\n                if ($('.action-braintree-paypal-message').length) {\n                    $('.product-add-form form').on('keyup change paste', 'input, select, textarea', function () {\n                        let currentPrice, currencySymbol;\n\n                        currentPrice = $('.product-info-main span').find('[data-price-type=\\'finalPrice\\']').text();\n                        currencySymbol = $('.action-braintree-paypal-message[data-pp-type=\"product\"]')\n                            .data('currency-symbol');\n                        $('.action-braintree-paypal-message[data-pp-type=\"product\"]')\n                            .attr('data-pp-amount', currentPrice.replace(currencySymbol,''));\n                    });\n                }\n\n                this.loadSDK(buttonConfig, lineItems);\n\n                window.addEventListener('hashchange', function () {\n                    const step = window.location.hash.replace('#', '');\n\n                    if (step === 'shipping') {\n                        Braintree.getPayPalInstance().teardown(function () {\n                            this.loadSDK(buttonConfig, lineItems);\n                        }.bind(this));\n                    }\n\n                }.bind(this));\n\n                window.addEventListener('paypal:reinit-express', function () {\n                    this.loadSDK(buttonConfig, lineItems);\n                }.bind(this));\n            },\n\n            /**\n             * Load Braintree PayPal SDK\n             *\n             * @param buttonConfig\n             * @param lineItems\n             */\n            loadSDK: function (buttonConfig, lineItems) {\n                braintree.create({\n                    authorization: buttonConfig.clientToken\n                }, function (clientErr, clientInstance) {\n                    if (clientErr) {\n                        console.error('paypalCheckout error', clientErr);\n                        let error = 'PayPal Checkout could not be initialized. Please contact the store owner.';\n\n                        return this.showError(error);\n                    }\n                    dataCollector.create({\n                        client: clientInstance,\n                        paypal: true\n                    }, function (err) {\n                        if (err) {\n                            return console.log(err);\n                        }\n                    });\n                    paypalCheckout.create({\n                        client: clientInstance\n                    }, function (err, paypalCheckoutInstance) {\n                        Braintree.setPayPalInstance(paypalCheckoutInstance);\n                        let configSDK = {\n                                components: 'buttons,messages,funding-eligibility',\n                                'enable-funding': this.isCreditActive(buttonConfig) ? 'credit' : 'paylater',\n                                currency: buttonConfig.currency\n                            },\n\n                            buyerCountry = this.getMerchantCountry(buttonConfig);\n\n                        if (buttonConfig.environment === 'sandbox'\n                            && (buyerCountry !== '' || buyerCountry !== 'undefined'))\n                        {\n                            configSDK['buyer-country'] = buyerCountry;\n                        }\n                        paypalCheckoutInstance.loadPayPalSDK(configSDK, function () {\n                            this.renderPayPalButtons(paypalCheckoutInstance, lineItems);\n                            this.renderPayPalMessages();\n                        }.bind(this));\n                    }.bind(this));\n                }.bind(this));\n            },\n\n            /**\n             * Is Credit enabled\n             *\n             * @param buttonConfig\n             * @returns {boolean}\n             */\n            isCreditActive: function (buttonConfig) {\n                return buttonConfig.isCreditActive;\n            },\n\n            /**\n             * Get merchant country\n             *\n             * @param buttonConfig\n             * @returns {string}\n             */\n            getMerchantCountry: function (buttonConfig) {\n                return buttonConfig.merchantCountry;\n            },\n\n            /**\n             * Render PayPal buttons\n             *\n             * @param paypalCheckoutInstance\n             * @param lineItems\n             */\n            renderPayPalButtons: function (paypalCheckoutInstance, lineItems) {\n                this.payPalButton(paypalCheckoutInstance, lineItems);\n            },\n\n            /**\n             * Render PayPal messages\n             */\n            renderPayPalMessages: function () {\n                $('.action-braintree-paypal-message').each(function () {\n                    window.paypal.Messages({\n                        amount: $(this).data('pp-amount'),\n                        pageType: $(this).data('pp-type'),\n                        style: {\n                            layout: $(this).data('messaging-layout'),\n                            text: {\n                                color:   $(this).data('messaging-text-color')\n                            },\n                            logo: {\n                                type: $(this).data('messaging-logo'),\n                                position: $(this).data('messaging-logo-position')\n                            }\n                        }\n                    }).render('#' + $(this).attr('id'));\n\n\n                });\n            },\n\n            /**\n             * @param paypalCheckoutInstance\n             * @param lineItems\n             */\n            payPalButton: function (paypalCheckoutInstance, lineItems) {\n                $('.action-braintree-paypal-logo').each(function () {\n                    let currentElement = $(this),\n                        style = {\n                            label: currentElement.data('label'),\n                            color: currentElement.data('color'),\n                            shape: currentElement.data('shape')\n                        },\n                        button;\n\n                    if (currentElement.data('fundingicons')) {\n                        style.fundingicons = currentElement.data('fundingicons');\n                    }\n\n                    // Render\n                    button = window.paypal.Buttons({\n                        fundingSource: currentElement.data('funding'),\n                        style: style,\n                        createOrder: function () {\n                            return paypalCheckoutInstance.createPayment({\n                                amount: currentElement.data('amount'),\n                                locale: currentElement.data('locale'),\n                                currency: currentElement.data('currency'),\n                                flow: 'checkout',\n                                enableShippingAddress: true,\n                                displayName: currentElement.data('displayname'),\n                                lineItems: JSON.parse(lineItems)\n                            });\n                        },\n                        validate: function (actions) {\n                            let cart = customerData.get('cart'),\n                                customer = customerData.get('customer'),\n                                declinePayment = false,\n                                isGuestCheckoutAllowed;\n\n                            isGuestCheckoutAllowed = cart().isGuestCheckoutAllowed;\n                            declinePayment = !customer().firstname && !isGuestCheckoutAllowed\n                                && typeof isGuestCheckoutAllowed !== 'undefined';\n\n                            if (declinePayment) {\n                                actions.disable();\n                            }\n                        },\n\n                        onCancel: function () {\n                            jQuery('#maincontent').trigger('processStop');\n                        },\n\n                        onError: function (errorData) {\n                            console.error('paypalCheckout button render error', errorData);\n                            jQuery('#maincontent').trigger('processStop');\n                        },\n\n                        onClick: function () {\n                            if (currentElement.data('location') === 'productpage') {\n                                let form = $('#product_addtocart_form');\n\n                                if (!(form.validation() && form.validation('isValid'))) {\n                                    return false;\n                                }\n                            }\n\n                            let cart = customerData.get('cart'),\n                                customer = customerData.get('customer'),\n                                declinePayment = false,\n                                isGuestCheckoutAllowed;\n\n                            isGuestCheckoutAllowed = cart().isGuestCheckoutAllowed;\n                            declinePayment = !customer().firstname && !isGuestCheckoutAllowed\n                                && typeof isGuestCheckoutAllowed !== 'undefined';\n                            if (declinePayment) {\n                                // eslint-disable-next-line\n                                alert($t('To check out, please sign in with your email address.'));\n                            }\n                        },\n\n                        onApprove: function (approveData) {\n                            return paypalCheckoutInstance.tokenizePayment(approveData, function (err, payload) {\n                                jQuery('#maincontent').trigger('processStart');\n\n                                /* Set variables & default values for shipping/recipient name to billing */\n                                let accountFirstName = replaceSingleQuoteCharacter(payload.details.firstName),\n                                    accountLastName = replaceSingleQuoteCharacter(payload.details.lastName),\n                                    accountEmail = replaceSingleQuoteCharacter(payload.details.email),\n                                    recipientFirstName = accountFirstName,\n                                    recipientLastName = accountLastName,\n                                    address = payload.details.shippingAddress,\n                                    recipientName = null,\n                                    actionSuccess,\n                                    isRequiredBillingAddress,\n                                    phone = _.get(payload, ['details', 'phone'], '');\n\n                                // Map the shipping address correctly\n                                if (!_.isUndefined(address.recipientName) && _.isString(address.recipientName)) {\n                                    /*\n                                         * Trim leading/ending spaces before splitting,\n                                         * filter to remove array keys with empty values\n                                         * & set to variable.\n                                         */\n                                    recipientName = address.recipientName.trim().split(' ').filter(n => n);\n                                }\n\n                                /*\n                                     * If the recipientName is not null, and it is an array with\n                                     * first/last name, use it. Otherwise, keep the default billing first/last name.\n                                     * This is to avoid cases of old accounts where spaces were allowed to first or\n                                     * last name in PayPal and the result was an array with empty fields\n                                     * resulting in empty names in the system.\n                                     */\n                                if (!_.isNull(recipientName) && !_.isUndefined(recipientName[1])) {\n                                    recipientFirstName = replaceSingleQuoteCharacter(recipientName[0]);\n                                    recipientLastName = replaceSingleQuoteCharacter(recipientName[1]);\n                                }\n\n                                payload.details.shippingAddress = {\n                                    streetAddress: typeof address.line2 !== 'undefined' && _.isString(address.line2)\n                                        ? replaceSingleQuoteCharacter(address.line1)\n                                                + ' ' + replaceSingleQuoteCharacter(address.line2)\n                                        : replaceSingleQuoteCharacter(address.line1),\n                                    locality: replaceSingleQuoteCharacter(address.city),\n                                    postalCode: address.postalCode,\n                                    countryCodeAlpha2: address.countryCode,\n                                    email: accountEmail,\n                                    recipientFirstName: recipientFirstName,\n                                    recipientLastName: recipientLastName,\n                                    telephone: removeNonDigitCharacters(phone),\n                                    region: typeof address.state !== 'undefined'\n                                        ? replaceSingleQuoteCharacter(address.state)\n                                        : ''\n                                };\n\n                                payload.details.email = accountEmail;\n                                payload.details.firstName = accountFirstName;\n                                payload.details.lastName = accountLastName;\n                                if (typeof payload.details.businessName !== 'undefined'\n                                        && _.isString(payload.details.businessName)) {\n                                    payload.details.businessName\n                                            = replaceSingleQuoteCharacter(payload.details.businessName);\n                                }\n\n                                // Map the billing address correctly\n                                isRequiredBillingAddress = currentElement.data('requiredbillingaddress');\n\n                                if (isRequiredBillingAddress === 1\n                                            && typeof payload.details.billingAddress !== 'undefined') {\n                                    let billingAddress = payload.details.billingAddress;\n\n                                    payload.details.billingAddress = {\n                                        streetAddress: typeof billingAddress.line2 !== 'undefined'\n                                                && _.isString(billingAddress.line2)\n                                            ? replaceSingleQuoteCharacter(billingAddress.line1)\n                                                    + ' ' + replaceSingleQuoteCharacter(billingAddress.line2)\n                                            : replaceSingleQuoteCharacter(billingAddress.line1),\n                                        locality: replaceSingleQuoteCharacter(billingAddress.city),\n                                        postalCode: billingAddress.postalCode,\n                                        countryCodeAlpha2: billingAddress.countryCode,\n                                        telephone: removeNonDigitCharacters(phone),\n                                        region: typeof billingAddress.state !== 'undefined'\n                                            ? replaceSingleQuoteCharacter(billingAddress.state)\n                                            : ''\n                                    };\n                                }\n\n                                if (currentElement.data('location') === 'productpage') {\n                                    let form = $('#product_addtocart_form');\n\n                                    payload.additionalData = form.serialize();\n                                }\n\n                                actionSuccess = currentElement.data('actionsuccess');\n\n                                formBuilder.build(\n                                    {\n                                        action: actionSuccess,\n                                        fields: {\n                                            result: JSON.stringify(payload)\n                                        }\n                                    }\n                                ).submit();\n                            });\n                        }\n                    });\n\n                    if (!button.isEligible()) {\n                        console.log('PayPal button is not elligible');\n                        currentElement.parent().remove();\n                        return;\n                    }\n                    if (button.isEligible() && $('#' + currentElement.attr('id')).length) {\n                        button.render('#' + currentElement.attr('id'));\n                    }\n                });\n            }\n        };\n    }\n);\n","PayPal_Braintree/js/paypal/form-builder.js":"/**\n * Copyright \u00a9 Magento, Inc. All rights reserved.\n * See COPYING.txt for license details.\n */\ndefine(\n    [\n        'jquery',\n        'underscore',\n        'mage/template'\n    ],\n    function ($, _, mageTemplate) {\n        'use strict';\n\n        return {\n\n            /**\n             * @param {Object} formData\n             * @returns {*|jQuery}\n             */\n            build: function (formData) {\n                var formTmpl = mageTemplate('<form action=\"<%= data.action %>\"' +\n                    ' method=\"POST\" hidden enctype=\"application/x-www-form-urlencoded\">' +\n                        '<% _.each(data.fields, function(val, key){ %>' +\n                            '<input value=\\'<%= val %>\\' name=\"<%= key %>\" type=\"hidden\">' +\n                        '<% }); %>' +\n                    '</form>');\n\n                return $(formTmpl({\n                    data: {\n                        action: formData.action,\n                        fields: formData.fields\n                    }\n                })).appendTo($('[data-container=\"body\"]'));\n            }\n        };\n    }\n);\n","PayPal_Braintree/js/paypal/product-page.js":"define(\n    ['PayPal_Braintree/js/paypal/button', 'jquery'],\n    function (button, $) {\n        'use strict';\n\n        return button.extend({\n\n            defaults: {\n                label: 'buynow',\n                branding: true\n            },\n\n            /**\n             * The validation on the add-to-cart form is done after the PayPal window has opened.\n             * This is because the validate method exposed by the PP Button requires an event to\n             * disable/enable the button.\n             * We can't fire an event due to the way the mage.validation widget works and we can't\n             * do something gross like an interval because the validation() method shows the error\n             * messages and focuses the user's input on the first erroring input field.\n             * @param payload\n             * @returns {*}\n             */\n            beforeSubmit: function (payload) {\n                var form = $('#product_addtocart_form');\n\n                if (!(form.validation() && form.validation('isValid'))) {\n                    return false;\n                }\n\n                payload.additionalData = form.serialize();\n\n                return payload;\n            }\n        });\n    }\n);\n","PayPal_Braintree/js/paypal/credit/calculator.js":"define([\n    'underscore',\n    'uiComponent'\n], function (_, Component) {\n    'use strict';\n\n    return Component.extend({\n        defaults: {\n            template: 'PayPal_Braintree/credit/calculator',\n            displaySummary: true, // \"From X per month\"\n            displayInterestDetails: false, // Display the more in-depth summary of interest rates\n            instalmentsFrom: 0,\n            currentInstalment: {\n                term: 0,\n                monthlyPayment: 0,\n                apr: 0,\n                cost: 0,\n                costIncInterest: 0\n            },\n            endpoint: null,\n            instalments: [],\n            visible: false,\n            merchantName: ''\n        },\n\n        /**\n         * initialize and observe the default variables\n         *\n         * @returns {*}\n         */\n        initObservable: function () {\n            this._super();\n            if (this.instalments.length > 0) {\n                this.currentInstalment = this.instalments[0];\n                this.instalmentsFrom = this.instalments[this.instalments.length - 1].monthlyPayment;\n                this.visible = true;\n            } else {\n                this.loadInstalments();\n            }\n\n            this.observe(['instalments', 'currentInstalment', 'instalmentsFrom', 'visible']);\n            return this;\n        },\n\n        /**\n         * check current instalment\n         *\n         * @param term\n         * @returns {boolean}\n         */\n        isCurrentInstalment: function (term) {\n            return this.currentInstalment().term === term;\n        },\n\n        /**\n         * set current instalment\n         *\n         * @param instalment\n         */\n        setCurrentInstalment: function (instalment) {\n            this.currentInstalment(instalment);\n        },\n\n        /**\n         * load instalments\n         *\n         * @returns {boolean}\n         */\n        loadInstalments: function () {\n            if (!this.endpoint) {\n                return false;\n            }\n\n            let self = this;\n\n            require(['Magento_Checkout/js/model/quote', 'jquery'], function (quote, $) {\n                if (typeof quote.totals()['base_grand_total'] === 'undefined') {\n                    return false;\n                }\n\n                $.getJSON(self.endpoint, {amount: quote.totals()['base_grand_total']}, function (response) {\n                    self.instalments(response);\n                    self.setCurrentInstalment(response[0]);\n                    self.visible(true);\n                });\n            });\n        }\n    });\n});\n","PayPal_Braintree/js/applepay/api.js":"/**\n * Braintree Apple Pay button API\n *\n **/\ndefine(\n    [\n        'jquery',\n        'underscore',\n        'uiComponent',\n        'mage/translate',\n        'mage/storage',\n        'Magento_Customer/js/customer-data',\n        'PayPal_Braintree/js/helper/remove-non-digit-characters'\n    ],\n    function (\n        $,\n        _,\n        Component,\n        $t,\n        storage,\n        customerData,\n        removeNonDigitCharacters\n    ) {\n        'use strict';\n\n        return Component.extend({\n            defaults: {\n                clientToken: null,\n                quoteId: 0,\n                displayName: null,\n                actionSuccess: null,\n                grandTotalAmount: 0,\n                isLoggedIn: false,\n                storeCode: 'default',\n                shippingAddress: {},\n                countryDirectory: null,\n                shippingMethods: {}\n            },\n\n            initialize: function () {\n                this._super();\n                if (!this.countryDirectory) {\n                    storage.get('rest/V1/directory/countries').done(function (result) {\n                        this.countryDirectory = {};\n                        let i, data, x, region, name;\n\n                        for (i = 0; i < result.length; ++i) {\n                            data = result[i];\n                            this.countryDirectory[data.two_letter_abbreviation] = {};\n                            if (typeof data.available_regions === 'undefined') {\n                                continue;\n                            }\n\n                            for (x = 0; x < data.available_regions.length; ++x) {\n                                region = data.available_regions[x];\n                                name = region.name.toLowerCase().replace(/[^A-Z0-9]/ig, '');\n                                this.countryDirectory[data.two_letter_abbreviation][name] = region.id;\n                            }\n                        }\n                    }.bind(this));\n                }\n            },\n\n            /**\n             * Get region ID\n             */\n            getRegionId: function (countryCode, regionName) {\n                if (typeof regionName !== 'string') {\n                    return null;\n                }\n\n                regionName = regionName.toLowerCase().replace(/[^A-Z0-9]/ig, '');\n\n                if (typeof this.countryDirectory[countryCode] !== 'undefined'\n                    && typeof this.countryDirectory[countryCode][regionName] !== 'undefined') {\n                    return this.countryDirectory[countryCode][regionName];\n                }\n\n                return 0;\n            },\n\n            /**\n             * Set & get api token\n             */\n            setClientToken: function (value) {\n                this.clientToken = value;\n            },\n            getClientToken: function () {\n                return this.clientToken;\n            },\n\n            /**\n             * Set and get quote id\n             */\n            setQuoteId: function (value) {\n                this.quoteId = value;\n            },\n            getQuoteId: function () {\n                return this.quoteId;\n            },\n\n            /**\n             * Set and get display name\n             */\n            setDisplayName: function (value) {\n                this.displayName = value;\n            },\n            getDisplayName: function () {\n                return this.displayName;\n            },\n\n            /**\n             * Set and get success redirection url\n             */\n            setActionSuccess: function (value) {\n                this.actionSuccess = value;\n            },\n            getActionSuccess: function () {\n                return this.actionSuccess;\n            },\n\n            /**\n             * Set and get grand total\n             */\n            setGrandTotalAmount: function (value) {\n                this.grandTotalAmount = parseFloat(value).toFixed(2);\n            },\n            getGrandTotalAmount: function () {\n                return parseFloat(this.grandTotalAmount);\n            },\n\n            /**\n             * Set and get is logged in\n             */\n            setIsLoggedIn: function (value) {\n                this.isLoggedIn = value;\n            },\n            getIsLoggedIn: function () {\n                return this.isLoggedIn;\n            },\n\n            /**\n             * Set and get store code\n             */\n            setStoreCode: function (value) {\n                this.storeCode = value;\n            },\n            getStoreCode: function () {\n                return this.storeCode;\n            },\n\n            /**\n             * API Urls for logged in / guest\n             */\n            getApiUrl: function (uri) {\n                if (this.getIsLoggedIn() === true) {\n                    return 'rest/' + this.getStoreCode() + '/V1/carts/mine/' + uri;\n                }\n                return 'rest/' + this.getStoreCode() + '/V1/guest-carts/' + this.getQuoteId() + '/' + uri;\n\n            },\n\n            /**\n             * Payment request info\n             */\n            getPaymentRequest: function () {\n                return {\n                    total: {\n                        label: this.getDisplayName(),\n                        amount: this.getGrandTotalAmount()\n                    },\n                    requiredShippingContactFields: ['postalAddress', 'name', 'email', 'phone'],\n                    requiredBillingContactFields: ['postalAddress', 'name']\n                };\n            },\n\n            /**\n             * Retrieve shipping methods based on address\n             */\n            onShippingContactSelect: function (event, session) {\n                // Get the address.\n                let address = event.shippingContact,\n\n                    // Create a payload.\n                    payload = {\n                        address: {\n                            city: address.locality,\n                            region: address.administrativeArea,\n                            country_id: address.countryCode.toUpperCase(),\n                            postcode: address.postalCode,\n                            save_in_address_book: 0\n                        }\n                    };\n\n                this.shippingAddress = payload.address;\n\n                // POST to endpoint for shipping methods.\n                storage.post(\n                    this.getApiUrl('estimate-shipping-methods'),\n                    JSON.stringify(payload)\n                ).done(function (result) {\n                    // Stop if no shipping methods.\n                    let virtualFlag = false,\n                        shippingMethods = [],\n                        totalsPayload = {};\n\n                    if (result.length === 0) {\n                        let productItems = customerData.get('cart')().items;\n\n                        _.each(productItems,\n                            function (item) {\n                                if (item.is_virtual || item.product_type === 'bundle') {\n                                    virtualFlag = true;\n                                } else {\n                                    virtualFlag = false;\n                                }\n                            }\n                        );\n                        if (!virtualFlag) {\n                            session.abort();\n                            // eslint-disable-next-line\n                            alert($t('There are no shipping methods available for you right now. Please try again or use an alternative payment method.'));\n                            return false;\n                        }\n                    }\n\n                    this.shippingMethods = {};\n\n                    // Format shipping methods array.\n                    for (let i = 0; i < result.length; i++) {\n                        if (typeof result[i].method_code !== 'string') {\n                            continue;\n                        }\n\n                        let method = {\n                            identifier: result[i].method_code,\n                            label: result[i].method_title,\n                            detail: result[i].carrier_title ? result[i].carrier_title : '',\n                            amount: parseFloat(result[i].amount).toFixed(2)\n                        };\n\n                        // Add method object to array.\n                        shippingMethods.push(method);\n\n                        this.shippingMethods[result[i].method_code] = result[i];\n\n                        if (!this.shippingMethod) {\n                            this.shippingMethod = result[i].method_code;\n                        }\n                    }\n\n                    // Create payload to get totals\n                    totalsPayload = {\n                        'addressInformation': {\n                            'address': {\n                                'countryId': this.shippingAddress.country_id,\n                                'region': this.shippingAddress.region,\n                                'regionId': this.getRegionId(\n                                    this.shippingAddress.country_id, this.shippingAddress.region),\n                                'postcode': this.shippingAddress.postcode\n                            },\n                            'shipping_method_code': virtualFlag\n                                ? null : this.shippingMethods[shippingMethods[0].identifier].method_code,\n                            'shipping_carrier_code': virtualFlag\n                                ? null : this.shippingMethods[shippingMethods[0].identifier].carrier_code\n                        }\n                    };\n\n                    // POST to endpoint to get totals, using 1st shipping method\n                    storage.post(\n                        this.getApiUrl('totals-information'),\n                        JSON.stringify(totalsPayload)\n                    ).done(function (totals) {\n                        // Set total\n                        this.setGrandTotalAmount(totals.base_grand_total);\n\n                        // Pass shipping methods back\n                        session.completeShippingContactSelection(\n                            window.ApplePaySession.STATUS_SUCCESS,\n                            shippingMethods,\n                            {\n                                label: this.getDisplayName(),\n                                amount: this.getGrandTotalAmount()\n                            },\n                            [{\n                                type: 'final',\n                                label: $t('Shipping'),\n                                amount: virtualFlag ? 0 : shippingMethods[0].amount\n                            }]\n                        );\n                    }.bind(this)).fail(function (error) {\n                        session.abort();\n                        // eslint-disable-next-line\n                        alert($t('We\\'re unable to fetch the cart totals for you. Please try an alternative payment method.'));\n                        console.error('Braintree ApplePay: Unable to get totals', error);\n                        return false;\n                    });\n\n                }.bind(this)).fail(function (result) {\n                    session.abort();\n                    // eslint-disable-next-line\n                    alert($t('We\\'re unable to find any shipping methods for you. Please try an alternative payment method.'));\n                    // eslint-disable-next-line\n                    console.error('Braintree ApplePay: Unable to find shipping methods for estimate-shipping-methods', result);\n                    return false;\n                });\n            },\n\n            /**\n             * Record which shipping method has been selected & Updated totals\n             */\n            onShippingMethodSelect: function (event, session) {\n                let shippingMethod = event.shippingMethod,\n                    payload = {\n                        'addressInformation': {\n                            'address': {\n                                'countryId': this.shippingAddress.country_id,\n                                'region': this.shippingAddress.region,\n                                'regionId': this.getRegionId(this.shippingAddress.country_id,\n                                    this.shippingAddress.region),\n                                'postcode': this.shippingAddress.postcode\n                            },\n                            'shipping_method_code': this.shippingMethods[shippingMethod.identifier].method_code,\n                            'shipping_carrier_code': this.shippingMethods[shippingMethod.identifier].carrier_code\n                        }\n                    };\n\n                this.shippingMethod = shippingMethod.identifier;\n\n\n                storage.post(\n                    this.getApiUrl('totals-information'),\n                    JSON.stringify(payload)\n                ).done(function (r) {\n                    this.setGrandTotalAmount(r.base_grand_total);\n\n                    session.completeShippingMethodSelection(\n                        window.ApplePaySession.STATUS_SUCCESS,\n                        {\n                            label: this.getDisplayName(),\n                            amount: this.getGrandTotalAmount()\n                        },\n                        [{\n                            type: 'final',\n                            label: $t('Shipping'),\n                            amount: shippingMethod.amount\n                        }]\n                    );\n                }.bind(this));\n            },\n\n            /**\n             * Place the order\n             */\n            startPlaceOrder: function (nonce, event, session, device_data) {\n                let shippingContact = event.payment.shippingContact,\n                    billingContact = event.payment.billingContact,\n                    payload = {\n                        'addressInformation': {\n                            'shipping_address': {\n                                'email': shippingContact.emailAddress,\n                                'telephone': removeNonDigitCharacters(_.get(shippingContact, 'phoneNumber', '')),\n                                'firstname': shippingContact.givenName,\n                                'lastname': shippingContact.familyName,\n                                'street': shippingContact.addressLines,\n                                'city': shippingContact.locality,\n                                'region': shippingContact.administrativeArea,\n                                'region_id': this.getRegionId(\n                                    shippingContact.countryCode.toUpperCase(), shippingContact.administrativeArea),\n                                'region_code': null,\n                                'country_id': shippingContact.countryCode.toUpperCase(),\n                                'postcode': shippingContact.postalCode,\n                                'same_as_billing': 0,\n                                'customer_address_id': 0,\n                                'save_in_address_book': 0\n                            },\n                            'billing_address': {\n                                'email': shippingContact.emailAddress,\n                                'telephone': removeNonDigitCharacters(_.get(shippingContact, 'phoneNumber', '')),\n                                'firstname': billingContact.givenName,\n                                'lastname': billingContact.familyName,\n                                'street': billingContact.addressLines,\n                                'city': billingContact.locality,\n                                'region': billingContact.administrativeArea,\n                                'region_id': this.getRegionId(\n                                    billingContact.countryCode.toUpperCase(), billingContact.administrativeArea),\n                                'region_code': null,\n                                'country_id': billingContact.countryCode.toUpperCase(),\n                                'postcode': billingContact.postalCode,\n                                'same_as_billing': 0,\n                                'customer_address_id': 0,\n                                'save_in_address_book': 0\n                            },\n                            'shipping_method_code': this.shippingMethod\n                                ? this.shippingMethods[this.shippingMethod].method_code : '' ,\n                            'shipping_carrier_code': this.shippingMethod\n                                ? this.shippingMethods[this.shippingMethod].carrier_code : ''\n                        }\n                    };\n\n                // Set addresses\n                storage.post(\n                    this.getApiUrl('shipping-information'),\n                    JSON.stringify(payload)\n                ).done(function () {\n                    // Submit payment information\n                    let paymentInformation = {\n                        'email': shippingContact.emailAddress,\n                        'paymentMethod': {\n                            'method': 'braintree_applepay',\n                            'additional_data': {\n                                'payment_method_nonce': nonce,\n                                'device_data': device_data\n                            }\n                        }\n                    };\n\n                    if (window.checkout && window.checkout.agreementIds) {\n                        paymentInformation.paymentMethod.extension_attributes = {\n                            'agreement_ids': window.checkout.agreementIds\n                        };\n                    }\n                    storage.post(\n                        this.getApiUrl('payment-information'),\n                        JSON.stringify(paymentInformation)\n                    ).done(function () {\n                        document.location = this.getActionSuccess();\n                        session.completePayment(window.ApplePaySession.STATUS_SUCCESS);\n                    }.bind(this)).fail(function (r) {\n                        session.completePayment(window.ApplePaySession.STATUS_FAILURE);\n                        session.abort();\n                        // eslint-disable-next-line\n                        alert($t('We\\'re unable to take your payment through Apple Pay. Please try an again or use an alternative payment method.'));\n                        console.error('Braintree ApplePay Unable to take payment', r);\n                        return false;\n                    });\n\n                }.bind(this)).fail(function (r) {\n                    console.error('Braintree ApplePay Unable to set shipping information', r);\n                    session.completePayment(window.ApplePaySession.STATUS_INVALID_BILLING_POSTAL_ADDRESS);\n                });\n            }\n        });\n    });\n","PayPal_Braintree/js/applepay/button.js":"/**\n * Braintree Apple Pay button\n **/\ndefine(\n    [\n        'uiComponent',\n        'knockout',\n        'jquery',\n        'braintree',\n        'braintreeDataCollector',\n        'braintreeApplePay',\n        'mage/translate',\n        'Magento_Checkout/js/model/payment/additional-validators'\n    ],\n    function (\n        Component,\n        ko,\n        $,\n        braintree,\n        dataCollector,\n        applePay,\n        $t,\n        additionalValidators\n    ) {\n        'use strict';\n\n        return {\n            init: function (element, context) {\n                // No element or context\n                if (!element || !context) {\n                    return;\n                }\n\n                // Context must implement these methods\n                if (typeof context.getClientToken !== 'function') {\n                    console.error(\n                        'Braintree ApplePay Context passed does not provide a getClientToken method',\n                        context\n                    );\n                    return;\n                }\n                if (typeof context.getPaymentRequest !== 'function') {\n                    console.error(\n                        'Braintree ApplePay Context passed does not provide a getPaymentRequest method',\n                        context\n                    );\n                    return;\n                }\n                if (typeof context.startPlaceOrder !== 'function') {\n                    console.error(\n                        'Braintree ApplePay Context passed does not provide a startPlaceOrder method',\n                        context\n                    );\n                    return;\n                }\n\n                if (this.deviceSupported() === false) {\n                    return;\n                }\n\n                // init braintree api\n                braintree.create({\n                    authorization: context.getClientToken()\n                }, function (clientErr, clientInstance) {\n                    this.initApplePay(clientErr, clientInstance, element, context);\n                }.bind(this));\n            },\n\n            /**\n             * Check the site is using HTTPS & apple pay is supported on this device.\n             * @return boolean\n             */\n            deviceSupported: function () {\n                if (location.protocol !== 'https:') {\n                    console.warn('Braintree Apple Pay requires your checkout be served over HTTPS');\n                    return false;\n                }\n\n                if ((window.ApplePaySession && window.ApplePaySession.canMakePayments()) !== true) {\n                    console.warn('Braintree Apple Pay is not supported on this device/browser');\n                    return false;\n                }\n\n                return true;\n            },\n\n            initApplePay: function (clientErr, clientInstance, element, context) {\n                if (clientErr) {\n                    console.error('Error creating client:', clientErr);\n                    return;\n                }\n\n                dataCollector.create({\n                    client: clientInstance\n                }, function (dataCollectorErr, dataCollectorInstance) {\n                    if (dataCollectorErr) {\n                        return;\n                    }\n\n                    applePay.create({\n                        client: clientInstance\n                    }, function (applePayErr, applePayInstance) {\n                        this.render(applePayErr, applePayInstance, dataCollectorInstance, element, context);\n                    }.bind(this));\n                }.bind(this));\n            },\n\n            render: function (applePayErr, applePayInstance, dataCollectorInstance, element, context) {\n                // No instance\n                if (applePayErr) {\n                    console.error('Braintree ApplePay Error creating applePayInstance:', applePayErr);\n                    return;\n                }\n\n                // Create a button within the KO element, as apple pay can only be instantiated through\n                // a valid on click event (ko onclick bind interferes with this).\n                let el = document.createElement('div');\n\n                el.className = 'braintree-apple-pay-button';\n                el.title = $t('Pay with Apple Pay');\n                el.alt = $t('Pay with Apple Pay');\n                el.addEventListener('click', function (e) {\n                    e.preventDefault();\n\n                    if ($(el).parents('#braintree-applepay-express-payment').length === 0\n                        && !additionalValidators.validate()) {\n                        return false;\n                    }\n\n                    // Payment request object\n                    let paymentRequest = applePayInstance.createPaymentRequest(context.getPaymentRequest());\n\n                    if (!paymentRequest) {\n                        console.error('Braintree ApplePay Unable to create paymentRequest', paymentRequest);\n                        this.showError();\n                        return;\n                    }\n\n                    // Show the loader\n                    $('body').loader('show');\n\n                    // Init apple pay session\n                    try {\n                        let session = new window.ApplePaySession(1, paymentRequest);\n\n                        // Handle invalid merchant\n                        session.onvalidatemerchant = function (event) {\n                            applePayInstance.performValidation({\n                                validationURL: event.validationURL,\n                                displayName: context.getDisplayName()\n                            }, function (validationErr, merchantSession) {\n                                if (validationErr) {\n                                    session.abort();\n                                    console.error('Braintree ApplePay Error validating merchant:', validationErr);\n                                    this.showError();\n                                    return;\n                                }\n\n                                session.completeMerchantValidation(merchantSession);\n                            });\n                        };\n\n                        // Attach payment auth event\n                        session.onpaymentauthorized = function (event) {\n                            applePayInstance.tokenize({\n                                token: event.payment.token\n                            }, function (tokenizeErr, payload) {\n                                if (tokenizeErr) {\n                                    console.error('Error tokenizing Apple Pay:', tokenizeErr);\n                                    session.completePayment(window.ApplePaySession.STATUS_FAILURE);\n                                    return;\n                                }\n\n                                let nonce = payload.nonce;\n\n                                // Pass the nonce back to the payment method\n                                context.startPlaceOrder(nonce, event, session, dataCollectorInstance.deviceData);\n                            });\n                        };\n\n                        // Attach onShippingContactSelect method\n                        if (typeof context.onShippingContactSelect === 'function') {\n                            session.onshippingcontactselected = function (event) {\n                                return context.onShippingContactSelect(event, session);\n                            };\n                        }\n\n                        // Attach onShippingMethodSelect method\n                        if (typeof context.onShippingMethodSelect === 'function') {\n                            session.onshippingmethodselected = function (event) {\n                                return context.onShippingMethodSelect(event, session);\n                            };\n                        }\n\n                        // Hook\n                        if (typeof context.onButtonClick === 'function') {\n                            context.onButtonClick(session, this, e);\n                        } else {\n                            $('body').loader('hide');\n                            session.begin();\n                        }\n                    } catch (err) {\n                        $('body').loader('hide');\n                        console.error('Braintree ApplePay Unable to create ApplePaySession', err);\n                        this.showError();\n                        return false;\n                    }\n                }.bind(this));\n\n                element.appendChild(el);\n            },\n\n            showError() {\n                // eslint-disable-next-line\n                alert($t('We\\'re unable to take payments through Apple Pay at the moment. Please try an alternative payment method.'));\n            }\n        };\n    }\n);\n","PayPal_Braintree/js/applepay/implementations/shortcut.js":"/**\n * Braintree Apple Pay mini cart payment method integration.\n **/\ndefine(\n    [\n        'uiComponent',\n        'PayPal_Braintree/js/applepay/button',\n        'PayPal_Braintree/js/applepay/api',\n        'mage/translate',\n        'domReady!'\n    ],\n    function (\n        Component,\n        button,\n        buttonApi,\n        $t\n    ) {\n        'use strict';\n\n        return Component.extend({\n\n            defaults: {\n                id: null,\n                clientToken: null,\n                quoteId: 0,\n                displayName: null,\n                actionSuccess: null,\n                grandTotalAmount: 0,\n                isLoggedIn: false,\n                storeCode: 'default'\n            },\n\n            /**\n             * @returns {Object}\n             */\n            initialize: function () {\n                this._super();\n                if (!this.displayName) {\n                    this.displayName = $t('Store');\n                }\n\n                let api = new buttonApi();\n\n                api.setGrandTotalAmount(parseFloat(this.grandTotalAmount).toFixed(2));\n                api.setClientToken(this.clientToken);\n                api.setDisplayName(this.displayName);\n                api.setQuoteId(this.quoteId);\n                api.setActionSuccess(this.actionSuccess);\n                api.setIsLoggedIn(this.isLoggedIn);\n                api.setStoreCode(this.storeCode);\n\n                // Attach the button\n                button.init(\n                    document.getElementById(this.id),\n                    api\n                );\n\n                return this;\n            }\n        });\n    }\n);\n","PayPal_Braintree/js/applepay/implementations/core-checkout/method-applepay.js":"define([\n    'uiComponent',\n    'Magento_Checkout/js/model/payment/renderer-list'\n], function (Component, rendererList) {\n    'use strict';\n\n    let config = window.checkoutConfig.payment;\n\n    if (config['braintree_applepay'].clientToken) {\n        rendererList.push({\n            type: 'braintree_applepay',\n            component: 'PayPal_Braintree/js/applepay/implementations/core-checkout/method-renderer/applepay'\n        });\n    }\n\n    return Component.extend({});\n});\n","PayPal_Braintree/js/applepay/implementations/core-checkout/method-renderer/applepay.js":"/**\n * Braintree Apple Pay payment method integration.\n **/\ndefine([\n    'underscore',\n    'Magento_Checkout/js/view/payment/default',\n    'Magento_Checkout/js/model/quote',\n    'Magento_Vault/js/view/payment/vault-enabler',\n    'PayPal_Braintree/js/applepay/button'\n], function (\n    _,\n    Component,\n    quote,\n    VaultEnabler,\n    button\n) {\n    'use strict';\n\n    return Component.extend({\n        defaults: {\n            template: 'PayPal_Braintree/applepay/core-checkout',\n            paymentMethodNonce: null,\n            deviceData: null,\n            grandTotalAmount: 0,\n            deviceSupported: button.deviceSupported(),\n            vaultEnabler: null,\n            additionalData: {}\n        },\n\n        /**\n         * @returns {exports.initialize}\n         */\n        initialize: function () {\n            this._super();\n            this.vaultEnabler = new VaultEnabler();\n            this.vaultEnabler.setPaymentCode(this.getVaultCode());\n\n            return this;\n        },\n\n        /**\n         * Inject the apple pay button into the target element\n         */\n        getApplePayBtn: function (id) {\n            button.init(\n                document.getElementById(id),\n                this\n            );\n        },\n\n        /**\n         * Subscribe to grand totals\n         */\n        initObservable: function () {\n            this._super();\n\n            this.vaultEnabler = new VaultEnabler();\n            this.vaultEnabler.setPaymentCode(this.getVaultCode());\n\n            this.grandTotalAmount = parseFloat(quote.totals()['base_grand_total']).toFixed(2);\n\n            quote.totals.subscribe(function () {\n                if (this.grandTotalAmount !== quote.totals()['base_grand_total']) {\n                    this.grandTotalAmount = parseFloat(quote.totals()['base_grand_total']).toFixed(2);\n                }\n            }.bind(this));\n\n            return this;\n        },\n\n        /**\n         * Apple pay place order method\n         */\n        startPlaceOrder: function (nonce, event, session, device_data) {\n            this.setPaymentMethodNonce(nonce);\n            this.setDeviceData(device_data);\n            this.placeOrder();\n\n            session.completePayment(window.ApplePaySession.STATUS_SUCCESS);\n        },\n\n        /**\n         * Save nonce\n         */\n        setPaymentMethodNonce: function (nonce) {\n            this.paymentMethodNonce = nonce;\n        },\n\n        /**\n         * Save nonce\n         */\n        setDeviceData: function (device_data) {\n            this.deviceData = device_data;\n        },\n\n        /**\n         * Retrieve the client token\n         * @returns null|string\n         */\n        getClientToken: function () {\n            return window.checkoutConfig.payment[this.getCode()].clientToken;\n        },\n\n        /**\n         * Payment request data\n         */\n        getPaymentRequest: function () {\n            return {\n                total: {\n                    label: this.getDisplayName(),\n                    amount: this.grandTotalAmount\n                }\n            };\n        },\n\n        /**\n         * Merchant display name\n         */\n        getDisplayName: function () {\n            return window.checkoutConfig.payment[this.getCode()].merchantName;\n        },\n\n        /**\n         * Get data\n         * @returns {Object}\n         */\n        getData: function () {\n            var data = {\n                'method': this.getCode(),\n                'additional_data': {\n                    'payment_method_nonce': this.paymentMethodNonce,\n                    'device_data': this.deviceData\n                }\n            };\n\n            data['additional_data'] = _.extend(data['additional_data'], this.additionalData);\n\n            this.vaultEnabler.visitAdditionalData(data);\n\n            return data;\n        },\n\n        /**\n         * Return image url for the apple pay mark\n         */\n        getPaymentMarkSrc: function () {\n            return window.checkoutConfig.payment[this.getCode()].paymentMarkSrc;\n        },\n\n        /**\n         * @returns {Boolean}\n         */\n        isVaultEnabled: function () {\n            return this.vaultEnabler.isVaultEnabled();\n        },\n\n        /**\n         * @returns {String}\n         */\n        getVaultCode: function () {\n            return window.checkoutConfig.payment[this.getCode()].vaultCode;\n        }\n    });\n});\n","PayPal_Braintree/js/model/full-screen-loader.js":"define([\n    'jquery',\n    'rjsResolver'\n], function ($, resolver) {\n    'use strict';\n\n    /**\n     * New full screen loader (spinner) implementation with configurable container.\n     * It can be used across website areas including checkout.\n     */\n    return {\n        container: 'body',\n\n        /**\n         * Set the container element with its ID to replace default container.\n         *\n         * Only allow to set elements by ID (as expected to be unique.\n         * If the container has already been changed, do not allow changing again as this be set once per component.\n         *\n         * @param {string} value\n         */\n        setContainer: function (value) {\n            if (this.container !== 'body' || !value.startsWith('#')) {\n                return;\n            }\n\n            this.container = value;\n        },\n\n        /**\n         * Get the container element.\n         *\n         * @return {string}\n         */\n        getContainer: function () {\n            return this.container;\n        },\n\n        /**\n         * Start full page loader action\n         */\n        startLoader: function () {\n            $(this.getContainer()).trigger('processStart');\n        },\n\n        /**\n         * Stop full page loader action\n         *\n         * @param {Boolean} [forceStop]\n         */\n        stopLoader: function (forceStop) {\n            let $elem = $(this.getContainer()),\n                stop = $elem.trigger.bind($elem, 'processStop'); //eslint-disable-line jquery-no-bind-unbind\n\n            forceStop ? stop() : resolver(stop);\n        }\n    };\n});\n","PayPal_Braintree/js/model/vault-enabler.js":"define([\n    'Magento_Vault/js/view/payment/vault-enabler'\n], function (VaultEnabler) {\n    'use strict';\n\n    return {\n        // Initialise a single VaultEnabler instance.\n        vaultEnabler: new VaultEnabler(),\n\n        /**\n         * @returns {VaultEnabler}\n         */\n        getVaultEnabler() {\n            return this.vaultEnabler;\n        },\n\n        /**\n         * Set the payment code against the vault enabler.\n         *\n         * @param {string} code\n         */\n        setPaymentCode(code) {\n            this.vaultEnabler.setPaymentCode(code);\n        },\n\n        /**\n         * Returns the vault enabled state.\n         *\n         * @returns {boolean}\n         */\n        isVaultEnabled() {\n            return this.vaultEnabler.isVaultEnabled();\n        },\n\n        /**\n         * Returns the active payment token enabler state.\n         *\n         * @returns {boolean}\n         */\n        isActivePaymentTokenEnabler() {\n            return this.vaultEnabler.isActivePaymentTokenEnabler();\n        },\n\n        /**\n         * @param {Object} data\n         */\n        visitAdditionalData(data) {\n            this.vaultEnabler.visitAdditionalData(data);\n        }\n    };\n});\n","PayPal_Braintree/js/model/place-order-mixin.js":"/**\n * Copyright \u00a9 Magento, Inc. All rights reserved.\n * See COPYING.txt for license details.\n */\n\n/* eslint-disable max-nested-callbacks */\n\ndefine([\n    'jquery',\n    'mage/utils/wrapper',\n    'Magento_ReCaptchaWebapiUi/js/webapiReCaptchaRegistry'\n], function ($, wrapper, recaptchaRegistry) {\n    'use strict';\n\n    return function (placeOrder) {\n        return wrapper.wrap(placeOrder, function (originalAction, serviceUrl, payload, messageContainer) {\n            var recaptchaDeferred;\n\n            if (recaptchaRegistry.triggers.hasOwnProperty('recaptcha-checkout-braintree')) {\n                //ReCaptcha is present for checkout\n                recaptchaDeferred = $.Deferred();\n                recaptchaRegistry.addListener('recaptcha-checkout-braintree', function (token) {\n                    //Add reCaptcha value to place-order request and resolve deferred with the API call results\n                    payload.xReCaptchaValue = token;\n                    originalAction(serviceUrl, payload, messageContainer).done(function () {\n                        recaptchaDeferred.resolve.apply(recaptchaDeferred, arguments);\n                    }).fail(function () {\n                        recaptchaDeferred.reject.apply(recaptchaDeferred, arguments);\n                    });\n                });\n                //Trigger ReCaptcha validation\n                recaptchaRegistry.triggers['recaptcha-checkout-braintree']();\n\n                if (!recaptchaRegistry._isInvisibleType.hasOwnProperty('recaptcha-checkout-braintree') ||\n                    recaptchaRegistry._isInvisibleType['recaptcha-checkout-braintree'] === false\n                ) {\n                    //remove listener so that place order action is only triggered by the 'Place Order' button\n                    recaptchaRegistry.removeListener('recaptcha-checkout-braintree');\n                }\n                return recaptchaDeferred;\n            }\n\n            //No ReCaptcha, just sending the request\n            return originalAction(serviceUrl, payload, messageContainer);\n        });\n    };\n});\n","PayPal_Braintree/js/model/step-navigator-mixin.js":"define([\n    'mage/utils/wrapper'\n], function (wrapper) {\n    'use strict';\n\n    let mixin = {\n        handleHash: function (originalFn) {\n            var hashString = window.location.hash.replace('#', '');\n\n            if (hashString.indexOf('venmo') > -1) {\n                return false;\n            }\n\n            return originalFn();\n        }\n    };\n\n    return function (target) {\n        return wrapper.extend(target, mixin);\n    };\n});\n","PayPal_Braintree/js/reCaptcha/webapiReCaptchaRegistry-mixin.js":"/**\n * Copyright \u00a9 Magento, Inc. All rights reserved.\n * See COPYING.txt for license details.\n */\n\ndefine([], function () {\n    'use strict';\n\n    return function (originalFunction) {\n        /**\n         * {@inheritDoc}\n         */\n        originalFunction.addListener = function (id , func) {\n            this._listeners[id] = func;\n        };\n\n        return originalFunction;\n    };\n});\n","Magento_Cookie/js/require-cookie.js":"/**\n * Copyright \u00a9 Magento, Inc. All rights reserved.\n * See COPYING.txt for license details.\n */\n\n/**\n * @api\n */\ndefine([\n    'jquery',\n    'Magento_Ui/js/modal/alert',\n    'jquery-ui-modules/widget',\n    'mage/mage',\n    'mage/translate'\n], function ($, alert) {\n    'use strict';\n\n    $.widget('mage.requireCookie', {\n        options: {\n            event: 'click',\n            noCookieUrl: 'enable-cookies',\n            triggers: ['.action.login', '.action.submit'],\n            isRedirectCmsPage: true\n        },\n\n        /**\n         * Constructor\n         * @private\n         */\n        _create: function () {\n            this._bind();\n        },\n\n        /**\n         * This method binds elements found in this widget.\n         * @private\n         */\n        _bind: function () {\n            var events = {};\n\n            $.each(this.options.triggers, function (index, value) {\n                events['click ' + value] = '_checkCookie';\n            });\n            this._on(events);\n        },\n\n        /**\n         * This method set the url for the redirect.\n         * @param {jQuery.Event} event\n         * @private\n         */\n        _checkCookie: function (event) {\n            if (navigator.cookieEnabled) {\n                return;\n            }\n\n            event.preventDefault();\n\n            if (this.options.isRedirectCmsPage) {\n                window.location = this.options.noCookieUrl;\n            } else {\n                alert({\n                    content: $.mage.__('Cookies are disabled in your browser.')\n                });\n            }\n        }\n    });\n\n    return $.mage.requireCookie;\n});\n","Magento_Cookie/js/notices.js":"/**\n * Copyright \u00a9 Magento, Inc. All rights reserved.\n * See COPYING.txt for license details.\n */\n\n/**\n * @api\n */\ndefine([\n    'jquery',\n    'jquery-ui-modules/widget',\n    'mage/cookies'\n], function ($) {\n    'use strict';\n\n    $.widget('mage.cookieNotices', {\n        /** @inheritdoc */\n        _create: function () {\n            if ($.mage.cookies.get(this.options.cookieName)) {\n                this.element.hide();\n            } else {\n                this.element.show();\n            }\n            $(this.options.cookieAllowButtonSelector).on('click', $.proxy(function () {\n                var cookieExpires = new Date(new Date().getTime() + this.options.cookieLifetime * 1000);\n\n                $.mage.cookies.set(this.options.cookieName, JSON.stringify(this.options.cookieValue), {\n                    expires: cookieExpires\n                });\n\n                if ($.mage.cookies.get(this.options.cookieName)) {\n                    this.element.hide();\n                    $(document).trigger('user:allowed:save:cookie');\n                } else {\n                    window.location.href = this.options.noCookiesUrl;\n                }\n            }, this));\n        }\n    });\n\n    return $.mage.cookieNotices;\n});\n","Webkul_BuyButton/js/tabs.js":"define(\n    [\n        'jquery'\n    ],\n    function($) {\n        $.widget('webkul.collapsible',{\n        options: {\n\n        },\n\n        _create: function() {\n            var self = this;\n            $(\"body\").on('click', self.options.element, function() {\n                if ($(this).hasClass(\"no-tab\")) {\n                    return false;\n                }\n                var id = $(this).attr(\"id\");\n                if ($(\".\"+id).hasClass(\"active\")) {\n                    $(\".\"+id).removeClass(\"active\");\n                    $(\".\"+id).slideUp(\"2000\");\n                } else {\n                    if ($(\".bb-tab-content.active\").length > 0) {\n                        $(\".bb-tab-content.active\").slideUp(\"2000\", function() {\n                            $(\".\"+id).addClass(\"active\");\n                            $(\".\"+id).slideDown(\"2000\");\n                        });\n                        $(\".bb-tab-content.active\").removeClass(\"active\");\n                    } else {\n                        $(\".\"+id).addClass(\"active\");\n                        $(\".\"+id).slideDown(\"2000\");\n                    }\n                }\n            });\n        \n        }   \n    });\n\n    return $.webkul.collapsible;\n});\n","Webkul_BuyButton/js/start.js":"define([\n    'uiComponent',\n    'uiLayout',\n    'uiRegistry',\n    'mage/translate',\n    'mage/template',\n    'jquery',\n    'ko',\n    'Magento_Ui/js/modal/modal'\n], function(\n    Component,\n    layout,\n    registry,\n    $t,\n    mageTemplate,\n    $,\n    ko,\n    modal\n) {\n    'use strict';\n    return Component.extend({\n        defaults: {\n            template: \"Webkul_BuyButton/start.html\",\n            inputType: false,\n            productIds: ''\n        },\n\n        /**\n         * @extends\n         */\n        initialize: function () {\n            var self = this;\n            this._super();\n        },\n\n        /**\n         * initialize observers\n         */\n        initObservable: function () {\n            this._super().observe('inputType productIds');\n            return this;\n        },\n\n        initProductButton: function() {\n            var self = this;\n            self.inputType(arguments[0].productInputType?arguments[0].productInputType:false);\n            var options = {\n                autoOpen: true,\n                modalClass: 'bb-modal-products',\n                buttons: [{\n                    text: $t(\"Create Button\"),\n                    class: 'button primary',\n                    click: function() {\n                        let productIds = $(\"input[name=productIds]\").val();\n                        let storeId = $(\".front-store\").val();\n                        let currency = $(\".allowed-currecny\").val();\n                        if (productIds) {\n                           window.location.href = ajaxCreateUrl+\"?productIds=\"+productIds+\"&store=\"+storeId+\"&currency=\"+currency;\n                        }\n                    } \n                }],\n                closed: function() {\n                        \n                    //$(\"body\").find(\".bb-modal-products\").remove();\n                },\n                clickableOverlay: false,\n                title: $t(\"Select Product\"),\n                type: \"slide\"\n            };\n            if ($(\"body\").find(\".bb-modal-products\").length == 0) {\n               \n                var gridComponentParams = {\n                    parent: this.name,\n                    name: this.name + '-product-grid',\n                    displayArea: 'products-grid',\n                    component: 'Webkul_BuyButton/js/grid-popup',\n                    provider:this,\n                    config: {\n                        productData: {}\n                    }\n                };\n\n                $.ajax({\n                    url: window.ajaxProductListUrl,\n                    type: 'GET',\n                    dataType: 'json',\n                    showLoader: true,\n                    headers: {\n                        \"Content-Type\": \"application/json\"\n                    },\n                    data: {\n                        pageSize: 20,\n                        pageNumber: 1,\n                        filter: '',\n                        sort:'name',\n                    },\n                    success: function(response) {\n                        gridComponentParams.config.productData = response;\n                        layout([gridComponentParams]);\n                    },\n                    error: function() {\n                        console.log(\"error\");\n                    }\n                });\n            }\n            \n            this._isElementLoaded(\".bb-grid-popup-container\", function() {\n                let modalHtml = $('.bb-grid-popup-container');\n                var popup = modal(options, modalHtml);\n                popup.openModal();\n            });\n        },\n\n        _isElementLoaded: function ($element, callback) {\n            var self = this;\n            setTimeout(function() {\n                \n                if ($($element).is(':visible')) {\n                    callback();\n                } else {\n                    self._isElementLoaded($element, callback);\n                }\n            }, 50);\n        },\n\n        initCollectionButton: function () {\n            this.initProductButton({productInputType:true});\n        }\n\n    });\n});","Webkul_BuyButton/js/grid-popup.js":"define([\n    'uiComponent',\n    'uiLayout',\n    'uiRegistry',\n    'mage/translate',\n    'mage/template',\n    'jquery',\n    'ko'\n], function(\n    Component,\n    layout,\n    registry,\n    $t,\n    mageTemplate,\n    $,\n    ko\n) {\n    'use strict';\n    return Component.extend({\n        defaults: {\n            template: \"Webkul_BuyButton/grid-popup.html\",\n            productData:{},\n            products: [],\n            totalCount:0,\n            productSelector: false,\n            parentComponent: {},\n            productSelectedCheckbox:[],\n            productSelectedRadio:'',\n            pageNumber: 1,\n            searchString: '',\n            pages:0,\n            stores:window.stores,\n            currencies:window.currencies\n        },\n\n        /**\n         * @extends\n         */\n        initialize: function (config) {\n            var self = this;\n            this._super();\n            this.parentComponent = config.provider;\n            self.productSelector = config.provider.inputType;\n            self.totalCount(self.productData.total_count);\n            self.products(self.productData.items);\n            self.pages(Math.ceil(self.totalCount()/20));\n            self.productSelectedCheckbox.subscribe(function (ids) {\n                self.parentComponent.productIds(ids.join(\",\"));\n            });\n            self.productSelectedRadio.subscribe(function (id) {\n                self.parentComponent.productIds(id);\n            });\n            self.searchString.subscribe(function(q) {\n                if (q.length > 2 || q.length == 0) {\n                    self.searchProduct(q);\n                }\n            });\n\n            self.pageNumber.subscribe(function(n) {\n                //console.log(n);\n                if (n < 1) {\n                    self.pageNumber(1);\n                    return;\n                } else if (n > self.pages()) {\n                    self.pageNumber(self.pages());\n                    return;\n                }\n                \n                let promise = self.getProductCollection('');\n                promise.then(function(response) {\n                    self.products(response.items);\n                    self.totalCount(response.total_count);\n                }, function(error) {\n                    console.log(error);\n                });\n            });\n\n            self.totalCount.subscribe(function (n) {\n                self.pages(Math.ceil(n/20));\n                self.pageNumber(1);\n            });\n        },\n\n        /**\n         * initialize observers\n         */\n        initObservable: function () {\n            this._super().observe(\n                'totalCount products productSelectedCheckbox productSelectedRadio pageNumber searchString pages stores currencies'\n            );\n            return this;\n        },\n\n        prevPage: function() {\n            let self = this;\n            let pageNumber = parseInt(self.pageNumber());\n            if (pageNumber <= 1) {\n                self.pageNumber(1);\n            } else {\n                self.pageNumber(pageNumber-1);\n            }\n        },\n\n        isFirst: function() {\n            let self = this;\n            if (self.pageNumber() == 1) {\n                return true;\n            }\n\n            return false;\n        },\n\n        isLast: function() {\n            let self = this;\n            \n            if (self.pageNumber() == self.pages()) {\n                return true;\n            }\n\n            return false;\n        },\n\n        nextPage: function() {\n            let self = this;\n            let pageNumber = parseInt(self.pageNumber());\n            \n            self.pageNumber(pageNumber+1);\n            \n        },\n\n        searchProduct: function(filter) {\n            let self = this;\n            if (!filter) {\n                filter = $('.no-changes').val();\n            }\n            let promise = self.getProductCollection(filter);\n            promise.then(function(response) {\n                self.products(response.items);\n                self.totalCount(response.total_count);\n            }, function(error) {\n                console.log(error);\n            });\n        },\n\n        getProductCollection: function(filter) {\n            let self = this;\n            let promise = new Promise(function(resolve, reject) {\n                $.ajax({\n                    url: window.ajaxProductListUrl,\n                    type: 'GET',\n                    dataType: 'json',\n                    showLoader: true,\n                    headers: {\n                        \"Content-Type\": \"application/json\"\n                    },\n                    data: {\n                        pageSize: 20,\n                        pageNumber: parseInt(self.pageNumber()),\n                        filter: filter,\n                        sort:'name',\n                        type: $('.filter-product-type').val()\n                    },\n                    success: function(response) {\n                        resolve(response);\n                    },\n                    error: function() {\n                        reject(\"some error occured\");\n                    }\n                });\n            });\n\n            return promise;\n\n        }\n\n\n    });\n});","Webkul_BuyButton/js/create.js":"define([\n    'uiComponent',\n    'uiLayout',\n    'uiRegistry',\n    'mage/template',\n    'jquery',\n    'ko',\n    'Magento_Ui/js/modal/modal',\n    'Webkul_BuyButton/js/tabs',\n    'jquery/colorpicker/js/colorpicker',\n    'mage/translate'\n], function(\n    Component,\n    layout,\n    registry,\n    mageTemplate,\n    $,\n    ko,\n    modal,\n    collapsible\n) {\n    'use strict';\n    \n    return Component.extend({\n        defaults: {\n            template: \"Webkul_BuyButton/create.html\",\n            inputType: false,\n            productIds: '',\n            showSizeDropdown: false,\n            jsTemplate: '<div id=\"buybutton-init\"></div> <script>(function(d,s,id){var js,bjs=d.getElementsByTagName(s)[0];if(d.getElementById(id))return;js=d.createElement(s);js.id=id;js.async=true;js.src=\"${window.staticUrl}\";js.onload=function(){new BuyButton({productIds:<%- productIds %>, baseUrl: <%- baseUrl %>, styles: <%- styles %>});};bjs.parentNode.insertBefore(js,bjs);}(document,\"script\",\"buybutton-js\"));</script>',\n            iframeWinodw:{},\n            iframeDocument: {},\n            changesCss: [],\n            lessinput:'@containerBackground: #FFFFFF;@itemsAlign: center;@itemBackground: #FFFFFF;@itemWidth:18.4%;@buttonFont:Arial, Helvetica, sans-serif;@buttonFontSize:16px;@buttonFontColor:#FFF;@buttonBackgroundColor:#1979c3;@buttonBorderRadius:3px;@headingFont:Arial, Helvetica, sans-serif;@headingFontSize:18px;@headingFontColor:#000;@priceFont:Arial, Helvetica, sans-serif;@priceFontSize:18px;@priceFontColor:#000;@checkoutButtonColor: #fff;@checkoutButtonBackground: #1979c3;.buybutton-container{background: @containerBackground}.buybutton-item{text-align:@itemsAlign;background:@itemBackground;width:@itemWidth}.buybutton-item-name{font-family:@headingFont;font-size:@headingFontSize;color:@headingFontColor;}.buybutton-item-price{font-family:@priceFont;font-size:@priceFontSize;color:@priceFontColor;}.buybutton-item-view > button, .buybutton-product-addtocart > button.buybutton-primary {background:@buttonBackgroundColor;border-radius: @buttonBorderRadius;font-family:@buttonFont;font-size:@buttonFontSize;color:@buttonFontColor}.bb-cart-checkout > .button{font-family: @buttonFont; color: @checkoutButtonColor;background: @checkoutButtonBackground;border-color:@checkoutButtonBackground;}.buybutton-product-price, .bb-cart-item-price{font-family:@priceFont;font-size:@priceFontSize;color:@priceFontColor;} .bb-cart-item-name, .buybutton-product-name{font-family:@headingFont;font-size:@headingFontSize;color:@headingFontColor;}.buybutton-product-sku,.buybutton-product-description{font-family:@priceFont;font-size:@priceFontSize;color:#666666;}',\n            dynamicCss: '',\n            miniCartText: 'Cart',\n\t\t\taddToCartText: 'Add To Cart',\n\t\t\tbuyNowText: 'Buy Now',\n\t\t\titemInCartText: 'Item In Cart',\n            cButtonText: 'Proceed To Checkout',\n            vButtonText: 'View Details',\n            noItemFoundText: 'No items found in cart.',\n            shippingInfoText: '',\n\t\t\tqtyText: 'Qty',\n            subTotalText: 'Cart Subtotal',\n            dTemplate: 1,\n            availableSerifFonts: [\n                {\n                label: 'Sans Serif',\n                value: [\n                    {label:'Helvetica',value:'Helvetica, sans-serif'},\n                ]\n                },\n                {\n                    label: 'Serif',\n                    value: [\n                        {label:'Times New Roman',value:'Times New Roman, Times, serif'},\n                    ]\n                },\n                {\n                    label: 'Mono',\n                    value : [\n                        {label:'Courier New', value:'Courier'},\n                        {label:'FreeMono',value:'FreeMono, monospace'},\n                        {label:'Monospace', value:'Lucida Console, Monaco, monospace'}\n                    ]\n                }\n\n            ],\n            availableSizes: [\n                {label: '12px', value:'12px'},\n                {label: '14px', value:'14px'},\n                {label: '16px', value:'16px'},\n                {label: '18px', value:'18px'},\n                {label: '20px', value:'20px'}\n            ]\n        },\n\n        /**\n         * @extends\n         */\n        initialize: function () {\n            var self = this;\n            this._super();\n            /**\n             * initialize buy button create page left customization panel\n             */\n            collapsible({element: '.bb-tab-title'});   \n            \n            /**\n             * updating style in the by button demo when a customization is done in the customization panel\n             */\n            self.dynamicCss.subscribe(function(css) {\n                self.iframeWinodw = document.getElementById(\"bb-demo\").contentWindow; \n                self.iframeWinodw.wkBuyButtonRegistry.currenctObject.vueContainerModel.styles = css;\n                self.iframeWinodw.wkBuyButtonRegistry.currenctObject.vueContainerModel.addStyleTag;\n            });  \n            \n            /**\n             * changesCss is to array on modified css that needs to be merged with original css and update in the buy button code\n             */\n            self.changesCss.subscribe(function(cssArray) {\n                let cssObj = {};\n                $.each(cssArray, function(key, value) {\n                    $.extend(cssObj, value);\n                });\n                self.lessCompile(less, cssObj);\n            });\n            \n            /**\n             * listening mini cart text change to reflect it in the demo\n             */\n            self.miniCartText.subscribe(function(text) {\n                self.iframeWinodw = document.getElementById(\"bb-demo\").contentWindow;\n                self.iframeWinodw.wkBuyButtonRegistry.currenctObject.vueContainerModel.childData.miniCartText = text;\n            });\n\n            /**\n             * listening add to cart text change to reflect it in the demo\n             */\n            self.addToCartText.subscribe(function(text) {\n                self.iframeWinodw = document.getElementById(\"bb-demo\").contentWindow; \n                self.iframeWinodw.wkBuyButtonRegistry.currenctObject.vueContainerModel.childData.addToCartText = text;\n                self.iframeWinodw.wkBuyButtonRegistry.currenctObject.vueQuickModel.addToCartLabel = text;\n                self.iframeWinodw.wkaddTocartLabel.text = text;\n            });\n\n            /**\n             * listening buy now button text change to reflect it in the demo\n             */\n            self.buyNowText.subscribe(function(text) {\n                self.iframeWinodw = document.getElementById(\"bb-demo\").contentWindow; \n                self.iframeWinodw.wkBuyButtonRegistry.currenctObject.vueContainerModel.childData.buyNowText = text;\n            });\n\n            /**\n             * listening view details button text change to reflect it in the demo\n             */\n            self.vButtonText.subscribe(function(text) {\n                self.iframeWinodw = document.getElementById(\"bb-demo\").contentWindow; \n                self.iframeWinodw.wkBuyButtonRegistry.currenctObject.vueContainerModel.childData.vButtonText = text;\n            });\n\n            /**\n             * listening item in cart text change to reflect it in the demo\n             */\n            self.itemInCartText.subscribe(function(text) {\n                self.iframeWinodw = document.getElementById(\"bb-demo\").contentWindow; \n                self.iframeWinodw.wkBuyButtonRegistry.currenctObject.vueContainerModel.childData.itemInCartText = text;\n            });\n\n            /**\n             * listening proceed to checkout button text change to reflect it in the demo\n             */\n            self.cButtonText.subscribe(function(text) {\n                self.iframeWinodw = document.getElementById(\"bb-demo\").contentWindow; \n                self.iframeWinodw.wkBuyButtonRegistry.currenctObject.vueContainerModel.childData.cButtonText = text;\n            });\n\n            /**\n             * listening item not found text change to reflect it in the demo\n             */\n            self.noItemFoundText.subscribe(function(text) {\n                self.iframeWinodw = document.getElementById(\"bb-demo\").contentWindow; \n                self.iframeWinodw.wkBuyButtonRegistry.currenctObject.vueContainerModel.childData.noItemFoundText = text;\n            });\n\n            /**\n             * listening quantity text change to reflect it in the demo\n             */\n            self.qtyText.subscribe(function(text) {\n                self.iframeWinodw = document.getElementById(\"bb-demo\").contentWindow; \n                self.iframeWinodw.wkBuyButtonRegistry.currenctObject.vueContainerModel.childData.qtyText = text;\n            });\n\n            /**\n             * listening subtotal text change to reflect it in the demo\n             */\n            self.subTotalText.subscribe(function(text) {\n                self.iframeWinodw = document.getElementById(\"bb-demo\").contentWindow; \n                self.iframeWinodw.wkBuyButtonRegistry.currenctObject.vueContainerModel.childData.subTotalText = text;\n            });\n            \n        },\n\n        /**\n         * show buy button template or not\n         */\n        showTemplate: function() {\n            let productIds = window.productIds.split(\",\");\n            if (productIds.length > 1) {\n                return false;\n            }\n\n            return true;\n        },\n\n        /**\n         * update the design template(button, button with image name, button with image name desc ) \n         * in the demo and buy button code\n         */\n        designTemplate: function(v) {\n            let self = this;\n            \n            self.iframeWinodw = document.getElementById(\"bb-demo\").contentWindow; \n            let productIds = window.productIds.split(\",\");\n            if (productIds.length > 1) {\n                self.iframeWinodw.wkBuyButtonRegistry.currenctObject.vueContainerModel.designTemplate = 1;\n                self.dTemplate(1);\n            } else {\n                self.iframeWinodw.wkBuyButtonRegistry.currenctObject.vueContainerModel.designTemplate = parseInt(v);\n                self.dTemplate(v);\n            }\n        },\n        \n        /**\n         * compile less to generate css\n         */\n        lessCompile: function (less, modifyVars) {\n            var self = this;\n            less.render(this.lessinput, {modifyVars: modifyVars},  (function(e, result) {\n                if (e) {\n                    //console.log(e);\n                } else {\n                    self.dynamicCss(result.css.trim());\n                }\n            }).bind(self));\n        },\n\n        /**\n         * initialize observers\n         */\n        initObservable: function () {\n            this._super().observe('showSizeDropdown inputType productIds availableSerifFonts availableSizes dynamicCss changesCss miniCartText addToCartText buyNowText itemInCartText cButtonText noItemFoundText qtyText subTotalText dTemplate vButtonText');\n            return this;\n        },\n\n        /**\n         * demo iframe initialization content\n         */\n        initChildFrameVars: function() {\n            let iframeContent = `<html><body><div id=\"buybutton-init\"></div> <script>(function(d, s, id) { var js, bjs = d.getElementsByTagName(s)[0]; if (d.getElementById(id)) return; js = d.createElement(s);js.id = id; js.async = true; setTimeout(function() { js.src = '${window.jsUrl}'; js.onload = function() { new BuyButton({redirectToProduct: '${window.redirectToProduct}',locale: '${window.locale}', storeId: '${window.storeId}', currency_code: '${window.currency}', productIds: '${window.productIds}', baseUrl: '${window.baseUrl}', staticUrl:'${window.staticUrl}'}); }; bjs.parentNode.insertBefore(js, bjs); }, 2000); }(document, \"script\", \"buybutton-js\"));</script></body></html>`;\n            return iframeContent;\n        },\n\n        /**\n         * alignment change css\n         */\n        alignChange: function(data, event) {\n            this.changesCss.push({'@itemsAlign': $(event.target).val()});\n        },\n\n        /**\n         * TODO in future \n         */\n        actionChange: function(data, event) {\n            // this.lessCompile(less, {'@buttonFace': 'back', '@buttonText': 'silver'});\n        },\n\n        /**\n         * on size change small medium or large\n         * @deprecated\n         */\n        sizeChange: function(data, event) {\n            let size = $(event.target).val();\n            let productIds = window.productIds.split(\",\");\n            if (productIds.length > 1) {\n                switch(size) {\n                    case 'small':\n                    this.changesCss.push({'@itemWidth': '16%'});\n                    break;\n                    case 'medium':\n                    this.changesCss.push({'@itemWidth': '18.4%'});\n                    break;\n                    case 'large':\n                    this.changesCss.push({'@itemWidth': '20%'});\n\n                }\n            } else {\n                this.changesCss.push({'@itemWidth': '100%'});\n            }\n        },\n\n        buttonFontChange: function(data, event) {\n            this.changesCss.push({'@buttonFont': $(event.target).val()});\n        },\n\n        buttonBorderRadiusChange: function(data, event) {\n            this.changesCss.push({'@buttonBorderRadius': $(event.target).val()});\n        },\n\n        headingFontChange: function(data, event) {\n            this.changesCss.push({'@headingFont': $(event.target).val()});\n        },\n\n        priceFontChange: function(data, event) {\n            this.changesCss.push({'@priceFont': $(event.target).val()});\n        },\n\n        buttonColorChange: function(data, event) {\n            this.changesCss.push({'@buttonFontColor': $(event.target).val()});\n        },\n\n        buttonBackgroundColorChange: function(data, event) {\n            this.changesCss.push({'@buttonBackgroundColor': $(event.target).val()});\n        },\n\n        headingColorChange: function(data, event) {\n            this.changesCss.push({'@headingFontColor': $(event.target).val()});\n        },\n\n        priceColorChange: function(data, event) {\n            this.changesCss.push({'@priceFontColor': $(event.target).val()});\n        },\n\n        buttonFontSizeChange: function(data, event) {\n            this.changesCss.push({'@buttonFontSize': $(event.target).val()});\n        },\n\n        headingFontSizeChange: function(data, event) {\n            this.changesCss.push({'@headingFontSize': $(event.target).val()});\n        },\n\n        priceFontSizeChange: function(data, event) {\n            this.changesCss.push({'@priceFontSize': $(event.target).val()});\n        },\n\n        checkoutColorChange: function(data, event) {\n            this.changesCss.push({'@checkoutButtonColor': $(event.target).val()});\n        },\n\n        checkoutBackgroundChange: function(data, event) {\n            this.changesCss.push({'@checkoutButtonBackground': $(event.target).val()});\n        },\n\n        /**\n         * generate the code for buybutton \n         */\n        generateCode: function() {\n            var self = this;\n            let options = {\n                buttons: [{\n                    text: $.mage.__('Copy To Clipboard'),\n                    class: 'copy-button',\n                    click: function() {\n                        \n                        var range = document.createRange();\n                        range.selectNode(document.getElementById(\"bb-code-viewer\"));\n                        document.getElementById(\"bb-code-viewer\").focus();\n                        document.getElementById(\"bb-code-viewer\").select();\n                        var sel = window.getSelection();\n                        //sel.removeAllRanges();\n                        sel.addRange(range);\n                        document.execCommand(\"copy\");\n                        let buttonText = $(\".copy-button\").text();\n                        $(\".copy-button\").text(\"Copied\");\n                        $(\".copy-button\").attr(\"disabled\", true);\n                        setTimeout(function() {\n                            $(\".copy-button\").text(buttonText);\n                            $(\".copy-button\").removeAttr(\"disabled\");\n                        }, 2000);\n                    }\n                }],\n                closed: function() {\n                    document.getElementById(\"bb-code-viewer\").removeEventListener(\"dblclick\", function() {});\n                    $(\".buybutton-code-generate-modal\").parent().remove();\n                },\n                modalClass: 'buybutton-code-generate-modal',\n                responsive: true,\n                title: $.mage.__('Embed Code'),\n                type: 'popup'\n            };\n\n            let template = this.jsTemplate, tmpl, progressTemplate;\n            progressTemplate = mageTemplate(\"#buybutton-call-code\");\n            tmpl = progressTemplate({\n                productIds: window.productIds,\n                baseUrl: window.baseUrl,\n                staticUrl: window.staticUrl,\n                redirectToProduct: window.redirectToProduct,\n                styles: self.dynamicCss().trim().replace(/(\\r\\n\\t|\\n|\\r\\t)/gm,\"\"),\n                jsUrl: window.jsUrl,\n                miniCartText: self.miniCartText(),\n                addToCartText: self.addToCartText(),\n                buyNowText: self.buyNowText(),\n                itemInCartText: self.itemInCartText(),\n                cButtonText: self.cButtonText(),\n                vButtonText: self.vButtonText(),\n                noItemFoundText: self.noItemFoundText(),\n                shippingInfoText: self.shippingInfoText,\n                qtyText: self.qtyText(),\n                subTotalText: self.subTotalText(),\n                designTemplate: self.dTemplate(),\n                locale: window.locale,\n                currency_code: window.currency,\n                storeId: window.storeId\n            });\n            var popup = modal(options, tmpl);\n            popup.openModal();\n            \n            document.getElementById(\"bb-code-viewer\").addEventListener(\"dblclick\", function() {\n                var range = document.createRange();\n                this.select();\n                range.selectNodeContents(this);\n                var sel = window.getSelection();\n                sel.removeAllRanges();\n                sel.addRange(range);\n                document.execCommand(\"copy\");\n                let buttonText = $(\".copy-button\").text();\n                $(\".copy-button\").text(\"Copied\");\n                setTimeout(function() {\n                    $(\".copy-button\").text(buttonText);\n                }, 2000);\n            });\n        },\n\n        /**\n         * after knockout initialized adding color picker on different classes\n         */\n        afterTemplateRender: function() {\n            var self = this;\n            $.each(\n                ['.cart_background_color', '.cart_button_color', '.button_color', '.button_background_color', '.price_color', '.heading_color'],\n                function (key, value) {\n                    $(value).ColorPicker({\n                        color: '#0000ff',\n                        onShow: function (colpkr) {\n                            $(colpkr).fadeIn(500);\n                            return false;\n                        },\n                        onHide: function (colpkr) {\n                            $(colpkr).fadeOut(500);\n                            return false;\n                        },\n                        onChange: function(hsb, hex, rgb) {\n                            $(value).val('#'+hex);\n                            $(value).css({\"backgroundColor\": '#'+hex});\n                            $(value).trigger(\"change\");\n                        },\n                    });\n                }\n            );\n            // self.lessinput = \"@buttonFace: red;@buttonText: green;.buybutton-view-product {color: @buttonFace;background: @buttonText;}\"\n            require([\"//cdnjs.cloudflare.com/ajax/libs/less.js/2.7.1/less.min.js\"], (function() {}).bind(self));\n\n            //console.log(self.iframeDocument.querySelector(\".buybutton-item-name > span\").style.font);\n            \n        }\n    });\n});","Brandung_CashOnDeliveryFee/js/action/set-payment-and-update-totals.js":"/*jshint browser:true jquery:true*/\n/*global alert*/\ndefine(\n    [\n        'Magento_Checkout/js/model/quote',\n        'Brandung_CashOnDeliveryFee/js/model/resource-url-manager',\n        'Magento_Customer/js/model/customer',\n        'Magento_Checkout/js/model/full-screen-loader',\n        'mage/storage',\n        'underscore'\n    ],\n    function (quote, resourceUrlManager, customer, fullScreenLoader, storage, _) {\n        'use strict';\n        return function (paymentMethod) {\n            var payload = {\n                cartId: quote.getQuoteId(),\n                billingAddress: quote.billingAddress(),\n                paymentMethod: _.pick(\n                    paymentMethod,\n                    'method',\n                    'additional_data',\n                    'po_number',\n                    'extension_attributes'\n                )\n            };\n\n            if (!customer.isLoggedIn()) {\n                payload.email = quote.guestEmail;\n            }\n\n            fullScreenLoader.startLoader();\n            storage.post(\n                resourceUrlManager.getSetPaymentAndGetTotalsUrl(quote),\n                JSON.stringify(payload)\n            ).done(function (response) {\n                quote.setTotals(response);\n            }).always(function () {\n                fullScreenLoader.stopLoader();\n            });\n        };\n    }\n);\n","Brandung_CashOnDeliveryFee/js/view/checkout/summary/cash-on-delivery-fee.js":"/*jshint browser:true jquery:true*/\n/*global alert*/\ndefine(\n    [\n        'Magento_Checkout/js/view/summary/abstract-total',\n        'Magento_Checkout/js/model/quote',\n        'Magento_Catalog/js/price-utils',\n        'Magento_Checkout/js/model/totals',\n        'Brandung_CashOnDeliveryFee/js/action/set-payment-and-update-totals',\n        'knockout'\n    ],\n    function (Component, quote, priceUtils, totals, setPaymentAndUpdateTotalsAction, ko) {\n        \"use strict\";\n        return Component.extend({\n            defaults: {\n                template: 'Brandung_CashOnDeliveryFee/cash-on-delivery-fee',\n                title: 'Cash On Delivery Fee',\n                value: ko.observable(0.0),\n                shouldDisplay: ko.observable(false)\n            },\n            initialize: function() {\n                this._super();\n\n                quote.paymentMethod.subscribe(function(newPaymentMethod) {\n                    setPaymentAndUpdateTotalsAction(newPaymentMethod)\n                });\n\n                quote.totals.subscribe((function (newTotals) {\n                    this.value(this.getFormattedTotalValue(newTotals));\n                    this.shouldDisplay(this.isTotalDisplayed(newTotals));\n                }).bind(this));\n            },\n            isTotalDisplayed: function(totals) {\n                return this.getTotalValue(totals) > 0;\n            },\n            getTotalValue: function(totals) {\n                if (typeof totals.total_segments === 'undefined' || !totals.total_segments instanceof Array) {\n                    return 0.0;\n                }\n\n                return totals.total_segments.reduce(function (cashOnDeliveryTotalValue, currentTotal) {\n                    return currentTotal.code === 'cash_on_delivery_fee' ? currentTotal.value : cashOnDeliveryTotalValue\n                }, 0.0);\n            },\n            getFormattedTotalValue: function(totals) {\n                return this.getFormattedPrice(this.getTotalValue(totals));\n            }\n        });\n    }\n);\n","Brandung_CashOnDeliveryFee/js/model/resource-url-manager.js":"/*jshint browser:true jquery:true*/\n/*global alert*/\ndefine(\n    [\n        'Magento_Customer/js/model/customer',\n        'Magento_Checkout/js/model/url-builder',\n        'mageUtils'\n    ],\n    function(customer, urlBuilder, utils) {\n        \"use strict\";\n        return {\n            getSetPaymentAndGetTotalsUrl: function(quote) {\n                var params = (this.getCheckoutMethod() == 'guest') ? {cartId: quote.getQuoteId()} : {};\n                var urls = {\n                    'guest': '/guest-carts/:cartId/set-payment-information-and-get-totals',\n                    'customer': '/carts/mine/set-payment-information-and-get-totals'\n                };\n                return this.getUrl(urls, params);\n            },\n            getUrl: function(urls, urlParams) {\n                var url;\n                if (utils.isEmpty(urls)) {\n                    return 'Provided service call does not exist.';\n                }\n                url = urls[this.getCheckoutMethod()];\n                return urlBuilder.createUrl(url, urlParams);\n            },\n            getCheckoutMethod: function() {\n                return customer.isLoggedIn() ? 'customer' : 'guest';\n            }\n        };\n    }\n);\n","knockoutjs/knockout-repeat.js":"// REPEAT binding for Knockout http://knockoutjs.com/\n// (c) Michael Best\n// License: MIT (http://www.opensource.org/licenses/mit-license.php)\n// Version 2.1.0\n\n(function(factory) {\n    if (typeof define === 'function' && define.amd) {\n        // [1] AMD anonymous module\n        define(['knockout'], factory);\n    } else if (typeof exports === 'object') {\n        // [2] commonJS\n        factory(require('knockout'));\n    } else {\n        // [3] No module loader (plain <script> tag) - put directly in global namespace\n        factory(window.ko);\n    }\n})(function(ko) {\n\nif (!ko.virtualElements)\n    throw Error('Repeat requires at least Knockout 2.1');\n\nvar ko_bindingFlags = ko.bindingFlags || {};\nvar ko_unwrap = ko.utils.unwrapObservable;\n\nvar koProtoName = '__ko_proto__';\n\nif (ko.version >= \"3.0.0\") {\n    // In Knockout 3.0.0, use the node preprocessor to replace a node with a repeat binding with a virtual element\n    var provider = ko.bindingProvider.instance, previousPreprocessFn = provider.preprocessNode;\n    provider.preprocessNode = function(node) {\n        var newNodes, nodeBinding;\n        if (!previousPreprocessFn || !(newNodes = previousPreprocessFn.call(this, node))) {\n            if (node.nodeType === 1 && (nodeBinding = node.getAttribute('data-bind'))) {\n                if (/^\\s*repeat\\s*:/.test(nodeBinding)) {\n                    var leadingComment = node.ownerDocument.createComment('ko ' + nodeBinding),\n                        trailingComment = node.ownerDocument.createComment('/ko');\n                    node.parentNode.insertBefore(leadingComment, node);\n                    node.parentNode.insertBefore(trailingComment, node.nextSibling);\n                    node.removeAttribute('data-bind');\n                    newNodes = [leadingComment, node, trailingComment];\n                }\n            }\n        }\n        return newNodes;\n    };\n}\n\nko.virtualElements.allowedBindings.repeat = true;\nko.bindingHandlers.repeat = {\n    flags: ko_bindingFlags.contentBind | ko_bindingFlags.canUseVirtual,\n    init: function(element, valueAccessor, allBindingsAccessor, xxx, bindingContext) {\n\n        // Read and set fixed options--these options cannot be changed\n        var repeatParam = ko_unwrap(valueAccessor());\n        if (repeatParam && typeof repeatParam == 'object' && !('length' in repeatParam)) {\n            var repeatIndex = repeatParam.index,\n                repeatData = repeatParam.item,\n                repeatStep = repeatParam.step,\n                repeatReversed = repeatParam.reverse,\n                repeatBind = repeatParam.bind,\n                repeatInit = repeatParam.init,\n                repeatUpdate = repeatParam.update;\n        }\n        // Set default values for options that need it\n        repeatIndex = repeatIndex || '$index';\n        repeatData = repeatData || ko.bindingHandlers.repeat.itemName || '$item';\n        repeatStep = repeatStep || 1;\n        repeatReversed = repeatReversed || false;\n\n        var parent = element.parentNode, placeholder;\n        if (element.nodeType == 8) {    // virtual element\n            // Extract the \"children\" and find the single element node\n            var childNodes = ko.utils.arrayFilter(ko.virtualElements.childNodes(element), function(node) { return node.nodeType == 1;});\n            if (childNodes.length !== 1) {\n                throw Error(\"Repeat binding requires a single element to repeat\");\n            }\n            ko.virtualElements.emptyNode(element);\n\n            // The placeholder is the closing comment normally, or the opening comment if reversed\n            placeholder = repeatReversed ? element : element.nextSibling;\n            // The element to repeat is the contained element\n            element = childNodes[0];\n        } else {    // regular element\n            // First clean the element node and remove node's binding\n            var origBindString = element.getAttribute('data-bind');\n            ko.cleanNode(element);\n            element.removeAttribute('data-bind');\n\n            // Original element is no longer needed: delete it and create a placeholder comment\n            placeholder = element.ownerDocument.createComment('ko_repeatplaceholder ' + origBindString);\n            parent.replaceChild(placeholder, element);\n        }\n\n        // extract and remove a data-repeat-bind attribute, if present\n        if (!repeatBind) {\n            repeatBind = element.getAttribute('data-repeat-bind');\n            if (repeatBind) {\n                element.removeAttribute('data-repeat-bind');\n            }\n        }\n\n        // Make a copy of the element node to be copied for each repetition\n        var cleanNode = element.cloneNode(true);\n        if (typeof repeatBind == \"string\") {\n            cleanNode.setAttribute('data-bind', repeatBind);\n            repeatBind = null;\n        }\n\n        // Set up persistent data\n        var lastRepeatCount = 0,\n            notificationObservable = ko.observable(),\n            repeatArray, arrayObservable;\n\n        if (repeatInit) {\n            repeatInit(parent);\n        }\n\n        var subscribable = ko.computed(function() {\n            function makeArrayItemAccessor(index) {\n                var f = function(newValue) {\n                    var item = repeatArray[index];\n                    // Reading the value of the item\n                    if (!arguments.length) {\n                        notificationObservable();   // for dependency tracking\n                        return ko_unwrap(item);\n                    }\n                    // Writing a value to the item\n                    if (ko.isObservable(item)) {\n                        item(newValue);\n                    } else if (arrayObservable && arrayObservable.splice) {\n                        arrayObservable.splice(index, 1, newValue);\n                    } else {\n                        repeatArray[index] = newValue;\n                    }\n                    return this;\n                };\n                // Pretend that our accessor function is an observable\n                f[koProtoName] = ko.observable;\n                return f;\n            }\n\n            function makeBinding(item, index, context) {\n                return repeatArray\n                    ? function() { return repeatBind.call(bindingContext.$data, item, index, context); }\n                    : function() { return repeatBind.call(bindingContext.$data, index, context); }\n            }\n\n            // Read and set up variable options--these options can change and will update the binding\n            var paramObservable = valueAccessor(), repeatParam = ko_unwrap(paramObservable), repeatCount = 0;\n            if (repeatParam && typeof repeatParam == 'object') {\n                if ('length' in repeatParam) {\n                    repeatArray = repeatParam;\n                    repeatCount = repeatArray.length;\n                } else {\n                    if ('foreach' in repeatParam) {\n                        repeatArray = ko_unwrap(paramObservable = repeatParam.foreach);\n                        if (repeatArray && typeof repeatArray == 'object' && 'length' in repeatArray) {\n                            repeatCount = repeatArray.length || 0;\n                        } else {\n                            repeatCount = repeatArray || 0;\n                            repeatArray = null;\n                        }\n                    }\n                    // If a count value is provided (>0), always output that number of items\n                    if ('count' in repeatParam)\n                        repeatCount = ko_unwrap(repeatParam.count) || repeatCount;\n                    // If a limit is provided, don't output more than the limit\n                    if ('limit' in repeatParam)\n                        repeatCount = Math.min(repeatCount, ko_unwrap(repeatParam.limit)) || repeatCount;\n                }\n                arrayObservable = repeatArray && ko.isObservable(paramObservable) ? paramObservable : null;\n            } else {\n                repeatCount = repeatParam || 0;\n            }\n\n            // Remove nodes from end if array is shorter\n            for (; lastRepeatCount > repeatCount; lastRepeatCount-=repeatStep) {\n                ko.removeNode(repeatReversed ? placeholder.nextSibling : placeholder.previousSibling);\n            }\n\n            // Notify existing nodes of change\n            notificationObservable.notifySubscribers();\n\n            // Add nodes to end if array is longer (also initially populates nodes)\n            for (; lastRepeatCount < repeatCount; lastRepeatCount+=repeatStep) {\n                // Clone node and add to document\n                var newNode = cleanNode.cloneNode(true);\n                parent.insertBefore(newNode, repeatReversed ? placeholder.nextSibling : placeholder);\n                newNode.setAttribute('data-repeat-index', lastRepeatCount);\n\n                // Apply bindings to inserted node\n                if (repeatArray && repeatData == '$data') {\n                    var newContext = bindingContext.createChildContext(makeArrayItemAccessor(lastRepeatCount));\n                } else {\n                    var newContext = bindingContext.extend();\n                    if (repeatArray)\n                        newContext[repeatData] = makeArrayItemAccessor(lastRepeatCount);\n                }\n                newContext[repeatIndex] = lastRepeatCount;\n                if (repeatBind) {\n                    var result = ko.applyBindingsToNode(newNode, makeBinding(newContext[repeatData], lastRepeatCount, newContext), newContext, true),\n                        shouldBindDescendants = result && result.shouldBindDescendants;\n                }\n                if (!repeatBind || (result && shouldBindDescendants !== false)) {\n                    ko.applyBindings(newContext, newNode);\n                }\n            }\n            if (repeatUpdate) {\n                repeatUpdate(parent);\n            }\n        }, null, {disposeWhenNodeIsRemoved: placeholder});\n\n        return { controlsDescendantBindings: true, subscribable: subscribable };\n    }\n};\n});","knockoutjs/knockout-es5.js":"/*!\n * Knockout ES5 plugin - https://github.com/SteveSanderson/knockout-es5\n * Copyright (c) Steve Sanderson\n * MIT license\n */\n\n(function(global, undefined) {\n  'use strict';\n\n  var ko;\n\n  // Model tracking\n  // --------------\n  //\n  // This is the central feature of Knockout-ES5. We augment model objects by converting properties\n  // into ES5 getter/setter pairs that read/write an underlying Knockout observable. This means you can\n  // use plain JavaScript syntax to read/write the property while still getting the full benefits of\n  // Knockout's automatic dependency detection and notification triggering.\n  //\n  // For comparison, here's Knockout ES3-compatible syntax:\n  //\n  //     var firstNameLength = myModel.user().firstName().length; // Read\n  //     myModel.user().firstName('Bert'); // Write\n  //\n  // ... versus Knockout-ES5 syntax:\n  //\n  //     var firstNameLength = myModel.user.firstName.length; // Read\n  //     myModel.user.firstName = 'Bert'; // Write\n\n  // `ko.track(model)` converts each property on the given model object into a getter/setter pair that\n  // wraps a Knockout observable. Optionally specify an array of property names to wrap; otherwise we\n  // wrap all properties. If any of the properties are already observables, we replace them with\n  // ES5 getter/setter pairs that wrap your original observable instances. In the case of readonly\n  // ko.computed properties, we simply do not define a setter (so attempted writes will be ignored,\n  // which is how ES5 readonly properties normally behave).\n  //\n  // By design, this does *not* recursively walk child object properties, because making literally\n  // everything everywhere independently observable is usually unhelpful. When you do want to track\n  // child object properties independently, define your own class for those child objects and put\n  // a separate ko.track call into its constructor --- this gives you far more control.\n  /**\n   * @param {object} obj\n   * @param {object|array.<string>} propertyNamesOrSettings\n   * @param {boolean} propertyNamesOrSettings.deep Use deep track.\n   * @param {array.<string>} propertyNamesOrSettings.fields Array of property names to wrap.\n   * todo: @param {array.<string>} propertyNamesOrSettings.exclude Array of exclude property names to wrap.\n   * todo: @param {function(string, *):boolean} propertyNamesOrSettings.filter Function to filter property \n   *   names to wrap. A function that takes ... params\n   * @return {object}\n   */\n  function track(obj, propertyNamesOrSettings) {\n    if (!obj || typeof obj !== 'object') {\n      throw new Error('When calling ko.track, you must pass an object as the first parameter.');\n    }\n\n    var propertyNames;\n\n    if ( isPlainObject(propertyNamesOrSettings) ) {\n      // defaults\n      propertyNamesOrSettings.deep = propertyNamesOrSettings.deep || false;\n      propertyNamesOrSettings.fields = propertyNamesOrSettings.fields || Object.getOwnPropertyNames(obj);\n      propertyNamesOrSettings.lazy = propertyNamesOrSettings.lazy || false;\n\n      wrap(obj, propertyNamesOrSettings.fields, propertyNamesOrSettings);\n    } else {\n      propertyNames = propertyNamesOrSettings || Object.getOwnPropertyNames(obj);\n      wrap(obj, propertyNames, {});\n    }\n\n    return obj;\n  }\n\n  // fix for ie\n  var rFunctionName = /^function\\s*([^\\s(]+)/;\n  function getFunctionName( ctor ){\n    if (ctor.name) {\n      return ctor.name;\n    }\n    return (ctor.toString().trim().match( rFunctionName ) || [])[1];\n  }\n\n  function canTrack(obj) {\n    return obj && typeof obj === 'object' && getFunctionName(obj.constructor) === 'Object';\n  }\n\n  function createPropertyDescriptor(originalValue, prop, map) {\n    var isObservable = ko.isObservable(originalValue);\n    var isArray = !isObservable && Array.isArray(originalValue);\n    var observable = isObservable ? originalValue\n        : isArray ? ko.observableArray(originalValue)\n        : ko.observable(originalValue);\n\n    map[prop] = function () { return observable; };\n\n    // add check in case the object is already an observable array\n    if (isArray || (isObservable && 'push' in observable)) {\n      notifyWhenPresentOrFutureArrayValuesMutate(ko, observable);\n    }\n\n    return {\n      configurable: true,\n      enumerable: true,\n      get: observable,\n      set: ko.isWriteableObservable(observable) ? observable : undefined\n    };\n  }\n\n  function createLazyPropertyDescriptor(originalValue, prop, map) {\n    if (ko.isObservable(originalValue)) {\n      // no need to be lazy if we already have an observable\n      return createPropertyDescriptor(originalValue, prop, map);\n    }\n\n    var observable;\n\n    function getOrCreateObservable(value, writing) {\n      if (observable) {\n        return writing ? observable(value) : observable;\n      }\n\n      if (Array.isArray(value)) {\n        observable = ko.observableArray(value);\n        notifyWhenPresentOrFutureArrayValuesMutate(ko, observable);\n        return observable;\n      }\n\n      return (observable = ko.observable(value));\n    }\n\n    map[prop] = function () { return getOrCreateObservable(originalValue); };\n    return {\n      configurable: true,\n      enumerable: true,\n      get: function () { return getOrCreateObservable(originalValue)(); },\n      set: function (value) { getOrCreateObservable(value, true); }\n    };\n  }\n\n  function wrap(obj, props, options) {\n    if (!props.length) {\n      return;\n    }\n\n    var allObservablesForObject = getAllObservablesForObject(obj, true);\n    var descriptors = {};\n\n    props.forEach(function (prop) {\n      // Skip properties that are already tracked\n      if (prop in allObservablesForObject) {\n        return;\n      }\n\n      // Skip properties where descriptor can't be redefined\n      if (Object.getOwnPropertyDescriptor(obj, prop).configurable === false){\n        return;\n      }\n\n      var originalValue = obj[prop];\n      descriptors[prop] = (options.lazy ? createLazyPropertyDescriptor : createPropertyDescriptor)\n        (originalValue, prop, allObservablesForObject);\n\n      if (options.deep && canTrack(originalValue)) {\n        wrap(originalValue, Object.keys(originalValue), options);\n      }\n    });\n\n    Object.defineProperties(obj, descriptors);\n  }\n\n  function isPlainObject( obj ){\n    return !!obj && typeof obj === 'object' && obj.constructor === Object;\n  }\n\n  // Lazily created by `getAllObservablesForObject` below. Has to be created lazily because the\n  // WeakMap factory isn't available until the module has finished loading (may be async).\n  var objectToObservableMap;\n\n  // Gets or creates the hidden internal key-value collection of observables corresponding to\n  // properties on the model object.\n  function getAllObservablesForObject(obj, createIfNotDefined) {\n    if (!objectToObservableMap) {\n      objectToObservableMap = weakMapFactory();\n    }\n\n    var result = objectToObservableMap.get(obj);\n    if (!result && createIfNotDefined) {\n      result = {};\n      objectToObservableMap.set(obj, result);\n    }\n    return result;\n  }\n\n  // Removes the internal references to observables mapped to the specified properties\n  // or the entire object reference if no properties are passed in. This allows the\n  // observables to be replaced and tracked again.\n  function untrack(obj, propertyNames) {\n    if (!objectToObservableMap) {\n      return;\n    }\n\n    if (arguments.length === 1) {\n      objectToObservableMap['delete'](obj);\n    } else {\n      var allObservablesForObject = getAllObservablesForObject(obj, false);\n      if (allObservablesForObject) {\n        propertyNames.forEach(function(propertyName) {\n          delete allObservablesForObject[propertyName];\n        });\n      }\n    }\n  }\n\n  // Computed properties\n  // -------------------\n  //\n  // The preceding code is already sufficient to upgrade ko.computed model properties to ES5\n  // getter/setter pairs (or in the case of readonly ko.computed properties, just a getter).\n  // These then behave like a regular property with a getter function, except they are smarter:\n  // your evaluator is only invoked when one of its dependencies changes. The result is cached\n  // and used for all evaluations until the next time a dependency changes).\n  //\n  // However, instead of forcing developers to declare a ko.computed property explicitly, it's\n  // nice to offer a utility function that declares a computed getter directly.\n\n  // Implements `ko.defineProperty`\n  function defineComputedProperty(obj, propertyName, evaluatorOrOptions) {\n    var ko = this,\n      computedOptions = { owner: obj, deferEvaluation: true };\n\n    if (typeof evaluatorOrOptions === 'function') {\n      computedOptions.read = evaluatorOrOptions;\n    } else {\n      if ('value' in evaluatorOrOptions) {\n        throw new Error('For ko.defineProperty, you must not specify a \"value\" for the property. ' +\n                        'You must provide a \"get\" function.');\n      }\n\n      if (typeof evaluatorOrOptions.get !== 'function') {\n        throw new Error('For ko.defineProperty, the third parameter must be either an evaluator function, ' +\n                        'or an options object containing a function called \"get\".');\n      }\n\n      computedOptions.read = evaluatorOrOptions.get;\n      computedOptions.write = evaluatorOrOptions.set;\n    }\n\n    obj[propertyName] = ko.computed(computedOptions);\n    track.call(ko, obj, [propertyName]);\n    return obj;\n  }\n\n  // Array handling\n  // --------------\n  //\n  // Arrays are special, because unlike other property types, they have standard mutator functions\n  // (`push`/`pop`/`splice`/etc.) and it's desirable to trigger a change notification whenever one of\n  // those mutator functions is invoked.\n  //\n  // Traditionally, Knockout handles this by putting special versions of `push`/`pop`/etc. on observable\n  // arrays that mutate the underlying array and then trigger a notification. That approach doesn't\n  // work for Knockout-ES5 because properties now return the underlying arrays, so the mutator runs\n  // in the context of the underlying array, not any particular observable:\n  //\n  //     // Operates on the underlying array value\n  //     myModel.someCollection.push('New value');\n  //\n  // To solve this, Knockout-ES5 detects array values, and modifies them as follows:\n  //  1. Associates a hidden subscribable with each array instance that it encounters\n  //  2. Intercepts standard mutators (`push`/`pop`/etc.) and makes them trigger the subscribable\n  // Then, for model properties whose values are arrays, the property's underlying observable\n  // subscribes to the array subscribable, so it can trigger a change notification after mutation.\n\n  // Given an observable that underlies a model property, watch for any array value that might\n  // be assigned as the property value, and hook into its change events\n  function notifyWhenPresentOrFutureArrayValuesMutate(ko, observable) {\n    var watchingArraySubscription = null;\n    ko.computed(function () {\n      // Unsubscribe to any earlier array instance\n      if (watchingArraySubscription) {\n        watchingArraySubscription.dispose();\n        watchingArraySubscription = null;\n      }\n\n      // Subscribe to the new array instance\n      var newArrayInstance = observable();\n      if (newArrayInstance instanceof Array) {\n        watchingArraySubscription = startWatchingArrayInstance(ko, observable, newArrayInstance);\n      }\n    });\n  }\n\n  // Listens for array mutations, and when they happen, cause the observable to fire notifications.\n  // This is used to make model properties of type array fire notifications when the array changes.\n  // Returns a subscribable that can later be disposed.\n  function startWatchingArrayInstance(ko, observable, arrayInstance) {\n    var subscribable = getSubscribableForArray(ko, arrayInstance);\n    return subscribable.subscribe(observable);\n  }\n\n  // Lazily created by `getSubscribableForArray` below. Has to be created lazily because the\n  // WeakMap factory isn't available until the module has finished loading (may be async).\n  var arraySubscribablesMap;\n\n  // Gets or creates a subscribable that fires after each array mutation\n  function getSubscribableForArray(ko, arrayInstance) {\n    if (!arraySubscribablesMap) {\n      arraySubscribablesMap = weakMapFactory();\n    }\n\n    var subscribable = arraySubscribablesMap.get(arrayInstance);\n    if (!subscribable) {\n      subscribable = new ko.subscribable();\n      arraySubscribablesMap.set(arrayInstance, subscribable);\n\n      var notificationPauseSignal = {};\n      wrapStandardArrayMutators(arrayInstance, subscribable, notificationPauseSignal);\n      addKnockoutArrayMutators(ko, arrayInstance, subscribable, notificationPauseSignal);\n    }\n\n    return subscribable;\n  }\n\n  // After each array mutation, fires a notification on the given subscribable\n  function wrapStandardArrayMutators(arrayInstance, subscribable, notificationPauseSignal) {\n    ['pop', 'push', 'reverse', 'shift', 'sort', 'splice', 'unshift'].forEach(function(fnName) {\n      var origMutator = arrayInstance[fnName];\n      arrayInstance[fnName] = function() {\n        var result = origMutator.apply(this, arguments);\n        if (notificationPauseSignal.pause !== true) {\n          subscribable.notifySubscribers(this);\n        }\n        return result;\n      };\n    });\n  }\n\n  // Adds Knockout's additional array mutation functions to the array\n  function addKnockoutArrayMutators(ko, arrayInstance, subscribable, notificationPauseSignal) {\n    ['remove', 'removeAll', 'destroy', 'destroyAll', 'replace'].forEach(function(fnName) {\n      // Make it a non-enumerable property for consistency with standard Array functions\n      Object.defineProperty(arrayInstance, fnName, {\n        enumerable: false,\n        value: function() {\n          var result;\n\n          // These additional array mutators are built using the underlying push/pop/etc.\n          // mutators, which are wrapped to trigger notifications. But we don't want to\n          // trigger multiple notifications, so pause the push/pop/etc. wrappers and\n          // delivery only one notification at the end of the process.\n          notificationPauseSignal.pause = true;\n          try {\n            // Creates a temporary observableArray that can perform the operation.\n            result = ko.observableArray.fn[fnName].apply(ko.observableArray(arrayInstance), arguments);\n          }\n          finally {\n            notificationPauseSignal.pause = false;\n          }\n          subscribable.notifySubscribers(arrayInstance);\n          return result;\n        }\n      });\n    });\n  }\n\n  // Static utility functions\n  // ------------------------\n  //\n  // Since Knockout-ES5 sets up properties that return values, not observables, you can't\n  // trivially subscribe to the underlying observables (e.g., `someProperty.subscribe(...)`),\n  // or tell them that object values have mutated, etc. To handle this, we set up some\n  // extra utility functions that can return or work with the underlying observables.\n\n  // Returns the underlying observable associated with a model property (or `null` if the\n  // model or property doesn't exist, or isn't associated with an observable). This means\n  // you can subscribe to the property, e.g.:\n  //\n  //     ko.getObservable(model, 'propertyName')\n  //       .subscribe(function(newValue) { ... });\n  function getObservable(obj, propertyName) {\n    if (!obj || typeof obj !== 'object') {\n      return null;\n    }\n\n    var allObservablesForObject = getAllObservablesForObject(obj, false);\n    if (allObservablesForObject && propertyName in allObservablesForObject) {\n      return allObservablesForObject[propertyName]();\n    }\n\n    return null;\n  }\n  \n  // Returns a boolean indicating whether the property on the object has an underlying\n  // observables. This does the check in a way not to create an observable if the\n  // object was created with lazily created observables\n  function isTracked(obj, propertyName) {\n    if (!obj || typeof obj !== 'object') {\n      return false;\n    }\n    \n    var allObservablesForObject = getAllObservablesForObject(obj, false);\n    return !!allObservablesForObject && propertyName in allObservablesForObject;\n  }\n\n  // Causes a property's associated observable to fire a change notification. Useful when\n  // the property value is a complex object and you've modified a child property.\n  function valueHasMutated(obj, propertyName) {\n    var observable = getObservable(obj, propertyName);\n\n    if (observable) {\n      observable.valueHasMutated();\n    }\n  }\n\n  // Module initialisation\n  // ---------------------\n  //\n  // When this script is first evaluated, it works out what kind of module loading scenario\n  // it is in (Node.js or a browser `<script>` tag), stashes a reference to its dependencies\n  // (currently that's just the WeakMap shim), and then finally attaches itself to whichever\n  // instance of Knockout.js it can find.\n\n  // A function that returns a new ES6-compatible WeakMap instance (using ES5 shim if needed).\n  // Instantiated by prepareExports, accounting for which module loader is being used.\n  var weakMapFactory;\n\n  // Extends a Knockout instance with Knockout-ES5 functionality\n  function attachToKo(ko) {\n    ko.track = track;\n    ko.untrack = untrack;\n    ko.getObservable = getObservable;\n    ko.valueHasMutated = valueHasMutated;\n    ko.defineProperty = defineComputedProperty;\n\n    // todo: test it, maybe added it to ko. directly\n    ko.es5 = {\n      getAllObservablesForObject: getAllObservablesForObject,\n      notifyWhenPresentOrFutureArrayValuesMutate: notifyWhenPresentOrFutureArrayValuesMutate,\n      isTracked: isTracked\n    };\n  }\n\n  // Determines which module loading scenario we're in, grabs dependencies, and attaches to KO\n  function prepareExports() {\n    if (typeof exports === 'object' && typeof module === 'object') {\n      // Node.js case - load KO and WeakMap modules synchronously\n      ko = require('knockout');\n      var WM = require('../lib/weakmap');\n      attachToKo(ko);\n      weakMapFactory = function() { return new WM(); };\n      module.exports = ko;\n    } else if (typeof define === 'function' && define.amd) {\n      define(['knockout'], function(koModule) {\n        ko = koModule;\n        attachToKo(koModule);\n        weakMapFactory = function() { return new global.WeakMap(); };\n        return koModule;\n      });\n    } else if ('ko' in global) {\n      // Non-module case - attach to the global instance, and assume a global WeakMap constructor\n      ko = global.ko;\n      attachToKo(global.ko);\n      weakMapFactory = function() { return new global.WeakMap(); };\n    }\n  }\n\n  prepareExports();\n\n})(this);","knockoutjs/knockout-fast-foreach.js":"/*!\n  Knockout Fast Foreach v0.4.1 (2015-07-17T14:06:15.974Z)\n  By: Brian M Hunt (C) 2015\n  License: MIT\n\n  Adds `fastForEach` to `ko.bindingHandlers`.\n*/\n(function (root, factory) {\n  if (typeof define === 'function' && define.amd) {\n    define(['knockout'], factory);\n  } else if (typeof exports === 'object') {\n    module.exports = factory(require('knockout'));\n  } else {\n    root.KnockoutFastForeach = factory(root.ko);\n  }\n}(this, function (ko) {\n  \"use strict\";\n// index.js\n// --------\n// Fast For Each\n//\n// Employing sound techniques to make a faster Knockout foreach binding.\n// --------\n\n//      Utilities\n\n// from https://github.com/jonschlinkert/is-plain-object\nfunction isPlainObject(o) {\n  return !!o && typeof o === 'object' && o.constructor === Object;\n}\n\n// From knockout/src/virtualElements.js\nvar commentNodesHaveTextProperty = document && document.createComment(\"test\").text === \"<!--test-->\";\nvar startCommentRegex = commentNodesHaveTextProperty ? /^<!--\\s*ko(?:\\s+([\\s\\S]+))?\\s*-->$/ : /^\\s*ko(?:\\s+([\\s\\S]+))?\\s*$/;\nvar supportsDocumentFragment = document && typeof document.createDocumentFragment === \"function\";\nfunction isVirtualNode(node) {\n  return (node.nodeType === 8) && startCommentRegex.test(commentNodesHaveTextProperty ? node.text : node.nodeValue);\n}\n\n\n// Get a copy of the (possibly virtual) child nodes of the given element,\n// put them into a container, then empty the given node.\nfunction makeTemplateNode(sourceNode) {\n  var container = document.createElement(\"div\");\n  var parentNode;\n  if (sourceNode.content) {\n    // For e.g. <template> tags\n    parentNode = sourceNode.content;\n  } else if (sourceNode.tagName === 'SCRIPT') {\n    parentNode = document.createElement(\"div\");\n    parentNode.innerHTML = sourceNode.text;\n  } else {\n    // Anything else e.g. <div>\n    parentNode = sourceNode;\n  }\n  ko.utils.arrayForEach(ko.virtualElements.childNodes(parentNode), function (child) {\n    // FIXME - This cloneNode could be expensive; we may prefer to iterate over the\n    // parentNode children in reverse (so as not to foul the indexes as childNodes are\n    // removed from parentNode when inserted into the container)\n    if (child) {\n      container.insertBefore(child.cloneNode(true), null);\n    }\n  });\n  return container;\n}\n\nfunction insertAllAfter(containerNode, nodeOrNodeArrayToInsert, insertAfterNode) {\n  var frag, len, i;\n  // poor man's node and array check, should be enough for this\n  if (typeof nodeOrNodeArrayToInsert.nodeType !== \"undefined\" && typeof nodeOrNodeArrayToInsert.length === \"undefined\") {\n    throw new Error(\"Expected a single node or a node array\");\n  }\n\n  if (typeof nodeOrNodeArrayToInsert.nodeType !== \"undefined\") {\n    ko.virtualElements.insertAfter(containerNode, nodeOrNodeArrayToInsert, insertAfterNode);\n    return;\n  }\n\n  if (nodeOrNodeArrayToInsert.length === 1) {\n    ko.virtualElements.insertAfter(containerNode, nodeOrNodeArrayToInsert[0], insertAfterNode);\n    return;\n  }\n\n  if (supportsDocumentFragment) {\n    frag = document.createDocumentFragment();\n\n    for (i = 0, len = nodeOrNodeArrayToInsert.length; i !== len; ++i) {\n      frag.appendChild(nodeOrNodeArrayToInsert[i]);\n    }\n    ko.virtualElements.insertAfter(containerNode, frag, insertAfterNode);\n  } else {\n    // Nodes are inserted in reverse order - pushed down immediately after\n    // the last node for the previous item or as the first node of element.\n    for (i = nodeOrNodeArrayToInsert.length - 1; i >= 0; --i) {\n      var child = nodeOrNodeArrayToInsert[i];\n      if (!child) {\n        return;\n      }\n      ko.virtualElements.insertAfter(containerNode, child, insertAfterNode);\n    }\n  }\n}\n\n// Mimic a KO change item 'add'\nfunction valueToChangeAddItem(value, index) {\n  return {\n    status: 'added',\n    value: value,\n    index: index\n  };\n}\n\nfunction isAdditionAdjacentToLast(changeIndex, arrayChanges) {\n  return changeIndex > 0 &&\n    changeIndex < arrayChanges.length &&\n    arrayChanges[changeIndex].status === \"added\" &&\n    arrayChanges[changeIndex - 1].status === \"added\" &&\n    arrayChanges[changeIndex - 1].index === arrayChanges[changeIndex].index - 1;\n}\n\nfunction FastForEach(spec) {\n  this.element = spec.element;\n  this.container = isVirtualNode(this.element) ?\n                   this.element.parentNode : this.element;\n  this.$context = spec.$context;\n  this.data = spec.data;\n  this.as = spec.as;\n  this.noContext = spec.noContext;\n  this.templateNode = makeTemplateNode(\n    spec.name ? document.getElementById(spec.name).cloneNode(true) : spec.element\n  );\n  this.afterQueueFlush = spec.afterQueueFlush;\n  this.beforeQueueFlush = spec.beforeQueueFlush;\n  this.changeQueue = [];\n  this.lastNodesList = [];\n  this.indexesToDelete = [];\n  this.rendering_queued = false;\n\n  // Remove existing content.\n  ko.virtualElements.emptyNode(this.element);\n\n  // Prime content\n  var primeData = ko.unwrap(this.data);\n  if (primeData.map) {\n    this.onArrayChange(primeData.map(valueToChangeAddItem));\n  }\n\n  // Watch for changes\n  if (ko.isObservable(this.data)) {\n    if (!this.data.indexOf) {\n      // Make sure the observable is trackable.\n      this.data = this.data.extend({trackArrayChanges: true});\n    }\n    this.changeSubs = this.data.subscribe(this.onArrayChange, this, 'arrayChange');\n  }\n}\n\n\nFastForEach.animateFrame = window.requestAnimationFrame || window.webkitRequestAnimationFrame ||\n  window.mozRequestAnimationFrame || window.msRequestAnimationFrame ||\n  function(cb) { return window.setTimeout(cb, 1000 / 60); };\n\n\nFastForEach.prototype.dispose = function () {\n  if (this.changeSubs) {\n    this.changeSubs.dispose();\n  }\n};\n\n\n// If the array changes we register the change.\nFastForEach.prototype.onArrayChange = function (changeSet) {\n  var self = this;\n  var changeMap = {\n    added: [],\n    deleted: []\n  };\n  for (var i = 0, len = changeSet.length; i < len; i++) {\n    // the change is appended to a last change info object when both are 'added' and have indexes next to each other\n    // here I presume that ko is sending changes in monotonic order (in index variable) which happens to be true, tested with push and splice with multiple pushed values\n    if (isAdditionAdjacentToLast(i, changeSet)) {\n      var batchValues = changeMap.added[changeMap.added.length - 1].values;\n      if (!batchValues) {\n        // transform the last addition into a batch addition object\n        var lastAddition = changeMap.added.pop();\n        var batchAddition = {\n          isBatch: true,\n          status: 'added',\n          index: lastAddition.index,\n          values: [lastAddition.value]\n        };\n        batchValues = batchAddition.values;\n        changeMap.added.push(batchAddition);\n      }\n      batchValues.push(changeSet[i].value);\n    } else {\n      changeMap[changeSet[i].status].push(changeSet[i]);\n    }\n  }\n  if (changeMap.deleted.length > 0) {\n    this.changeQueue.push.apply(this.changeQueue, changeMap.deleted);\n    this.changeQueue.push({status: 'clearDeletedIndexes'});\n  }\n  this.changeQueue.push.apply(this.changeQueue, changeMap.added);\n  // Once a change is registered, the ticking count-down starts for the processQueue.\n  if (this.changeQueue.length > 0 && !this.rendering_queued) {\n    this.rendering_queued = true;\n    FastForEach.animateFrame.call(window, function () { self.processQueue(); });\n  }\n};\n\n\n// Reflect all the changes in the queue in the DOM, then wipe the queue.\nFastForEach.prototype.processQueue = function () {\n  var self = this;\n\n  // Callback so folks can do things before the queue flush.\n  if (typeof this.beforeQueueFlush === 'function') {\n    this.beforeQueueFlush(this.changeQueue);\n  }\n\n  ko.utils.arrayForEach(this.changeQueue, function (changeItem) {\n    // console.log(self.data(), \"CI\", JSON.stringify(changeItem, null, 2), JSON.stringify($(self.element).text()))\n    self[changeItem.status](changeItem);\n    // console.log(\"  ==> \", JSON.stringify($(self.element).text()))\n  });\n  this.rendering_queued = false;\n  // Callback so folks can do things.\n  if (typeof this.afterQueueFlush === 'function') {\n    this.afterQueueFlush(this.changeQueue);\n  }\n  this.changeQueue = [];\n};\n\n\n// Process a changeItem with {status: 'added', ...}\nFastForEach.prototype.added = function (changeItem) {\n  var index = changeItem.index;\n  var valuesToAdd = changeItem.isBatch ? changeItem.values : [changeItem.value];\n  var referenceElement = this.lastNodesList[index - 1] || null;\n  // gather all childnodes for a possible batch insertion\n  var allChildNodes = [];\n\n  for (var i = 0, len = valuesToAdd.length; i < len; ++i) {\n    var templateClone = this.templateNode.cloneNode(true);\n    var childContext;\n\n    if (this.noContext) {\n      childContext = this.$context.extend({\n        '$item': valuesToAdd[i]\n      });\n    } else {\n      childContext = this.$context.createChildContext(valuesToAdd[i], this.as || null);\n    }\n\n    // apply bindings first, and then process child nodes, because bindings can add childnodes\n    ko.applyBindingsToDescendants(childContext, templateClone);\n\n    var childNodes = ko.virtualElements.childNodes(templateClone);\n    // Note discussion at https://github.com/angular/angular.js/issues/7851\n    allChildNodes.push.apply(allChildNodes, Array.prototype.slice.call(childNodes));\n    this.lastNodesList.splice(index + i, 0, childNodes[childNodes.length - 1]);\n  }\n\n  insertAllAfter(this.element, allChildNodes, referenceElement);\n};\n\n\n// Process a changeItem with {status: 'deleted', ...}\nFastForEach.prototype.deleted = function (changeItem) {\n  var index = changeItem.index;\n  var ptr = this.lastNodesList[index],\n      // We use this.element because that will be the last previous node\n      // for virtual element lists.\n      lastNode = this.lastNodesList[index - 1] || this.element;\n  do {\n    ptr = ptr.previousSibling;\n    ko.removeNode((ptr && ptr.nextSibling) || ko.virtualElements.firstChild(this.element));\n  } while (ptr && ptr !== lastNode);\n  // The \"last node\" in the DOM from which we begin our delets of the next adjacent node is\n  // now the sibling that preceded the first node of this item.\n  this.lastNodesList[index] = this.lastNodesList[index - 1];\n  this.indexesToDelete.push(index);\n};\n\n\n// We batch our deletion of item indexes in our parallel array.\n// See brianmhunt/knockout-fast-foreach#6/#8\nFastForEach.prototype.clearDeletedIndexes = function () {\n  // We iterate in reverse on the presumption (following the unit tests) that KO's diff engine\n  // processes diffs (esp. deletes) monotonically ascending i.e. from index 0 -> N.\n  for (var i = this.indexesToDelete.length - 1; i >= 0; --i) {\n    this.lastNodesList.splice(this.indexesToDelete[i], 1);\n  }\n  this.indexesToDelete = [];\n};\n\n\nko.bindingHandlers.fastForEach = {\n  // Valid valueAccessors:\n  //    []\n  //    ko.observable([])\n  //    ko.observableArray([])\n  //    ko.computed\n  //    {data: array, name: string, as: string}\n  init: function init(element, valueAccessor, bindings, vm, context) {\n    var value = valueAccessor(),\n        ffe;\n    if (isPlainObject(value)) {\n      value.element = value.element || element;\n      value.$context = context;\n      ffe = new FastForEach(value);\n    } else {\n      ffe = new FastForEach({\n        element: element,\n        data: ko.unwrap(context.$rawData) === value ? context.$rawData : value,\n        $context: context\n      });\n    }\n    ko.utils.domNodeDisposal.addDisposeCallback(element, function () {\n      ffe.dispose();\n    });\n    return {controlsDescendantBindings: true};\n  },\n\n  // Export for testing, debugging, and overloading.\n  FastForEach: FastForEach\n};\n\nko.virtualElements.allowedBindings.fastForEach = true;\n}));"}
}});