![]() Server : Apache System : Linux server2.corals.io 4.18.0-348.2.1.el8_5.x86_64 #1 SMP Mon Nov 15 09:17:08 EST 2021 x86_64 User : corals ( 1002) PHP Version : 7.4.33 Disable Function : exec,passthru,shell_exec,system Directory : /home/corals/cartforge.co/pub/static/frontend/Smartwave/porto/en_US/js/bundle/ |
require.config({"config": { "jsbuild":{"Mageplaza_Core/js/bootstrap.min.js":"/*!\n * Bootstrap v3.3.6 (http://getbootstrap.com)\n * Copyright 2011-2015 Twitter, Inc.\n * Licensed under the MIT license\n */\nif(\"undefined\"==typeof jQuery)throw new Error(\"Bootstrap's JavaScript requires jQuery\");+function(a){\"use strict\";var b=a.fn.jquery.split(\" \")[0].split(\".\");if(b[0]<2&&b[1]<9||1==b[0]&&9==b[1]&&b[2]<1||b[0]>2)throw new Error(\"Bootstrap's JavaScript requires jQuery version 1.9.1 or higher, but lower than version 3\")}(jQuery),+function(a){\"use strict\";function b(){var a=document.createElement(\"bootstrap\"),b={WebkitTransition:\"webkitTransitionEnd\",MozTransition:\"transitionend\",OTransition:\"oTransitionEnd otransitionend\",transition:\"transitionend\"};for(var c in b)if(void 0!==a.style[c])return{end:b[c]};return!1}a.fn.emulateTransitionEnd=function(b){var c=!1,d=this;a(this).one(\"bsTransitionEnd\",function(){c=!0});var e=function(){c||a(d).trigger(a.support.transition.end)};return setTimeout(e,b),this},a(function(){a.support.transition=b(),a.support.transition&&(a.event.special.bsTransitionEnd={bindType:a.support.transition.end,delegateType:a.support.transition.end,handle:function(b){return a(b.target).is(this)?b.handleObj.handler.apply(this,arguments):void 0}})})}(jQuery),+function(a){\"use strict\";function b(b){return this.each(function(){var c=a(this),e=c.data(\"bs.alert\");e||c.data(\"bs.alert\",e=new d(this)),\"string\"==typeof b&&e[b].call(c)})}var c='[data-dismiss=\"alert\"]',d=function(b){a(b).on(\"click\",c,this.close)};d.VERSION=\"3.3.6\",d.TRANSITION_DURATION=150,d.prototype.close=function(b){function c(){g.detach().trigger(\"closed.bs.alert\").remove()}var e=a(this),f=e.attr(\"data-target\");f||(f=e.attr(\"href\"),f=f&&f.replace(/.*(?=#[^\\s]*$)/,\"\"));var g=a(f);b&&b.preventDefault(),g.length||(g=e.closest(\".alert\")),g.trigger(b=a.Event(\"close.bs.alert\")),b.isDefaultPrevented()||(g.removeClass(\"in\"),a.support.transition&&g.hasClass(\"fade\")?g.one(\"bsTransitionEnd\",c).emulateTransitionEnd(d.TRANSITION_DURATION):c())};var e=a.fn.alert;a.fn.alert=b,a.fn.alert.Constructor=d,a.fn.alert.noConflict=function(){return a.fn.alert=e,this},a(document).on(\"click.bs.alert.data-api\",c,d.prototype.close)}(jQuery),+function(a){\"use strict\";function b(b){return this.each(function(){var d=a(this),e=d.data(\"bs.button\"),f=\"object\"==typeof b&&b;e||d.data(\"bs.button\",e=new c(this,f)),\"toggle\"==b?e.toggle():b&&e.setState(b)})}var c=function(b,d){this.$element=a(b),this.options=a.extend({},c.DEFAULTS,d),this.isLoading=!1};c.VERSION=\"3.3.6\",c.DEFAULTS={loadingText:\"loading...\"},c.prototype.setState=function(b){var c=\"disabled\",d=this.$element,e=d.is(\"input\")?\"val\":\"html\",f=d.data();b+=\"Text\",null==f.resetText&&d.data(\"resetText\",d[e]()),setTimeout(a.proxy(function(){d[e](null==f[b]?this.options[b]:f[b]),\"loadingText\"==b?(this.isLoading=!0,d.addClass(c).attr(c,c)):this.isLoading&&(this.isLoading=!1,d.removeClass(c).removeAttr(c))},this),0)},c.prototype.toggle=function(){var a=!0,b=this.$element.closest('[data-toggle=\"buttons\"]');if(b.length){var c=this.$element.find(\"input\");\"radio\"==c.prop(\"type\")?(c.prop(\"checked\")&&(a=!1),b.find(\".active\").removeClass(\"active\"),this.$element.addClass(\"active\")):\"checkbox\"==c.prop(\"type\")&&(c.prop(\"checked\")!==this.$element.hasClass(\"active\")&&(a=!1),this.$element.toggleClass(\"active\")),c.prop(\"checked\",this.$element.hasClass(\"active\")),a&&c.trigger(\"change\")}else this.$element.attr(\"aria-pressed\",!this.$element.hasClass(\"active\")),this.$element.toggleClass(\"active\")};var d=a.fn.button;a.fn.button=b,a.fn.button.Constructor=c,a.fn.button.noConflict=function(){return a.fn.button=d,this},a(document).on(\"click.bs.button.data-api\",'[data-toggle^=\"button\"]',function(c){var d=a(c.target);d.hasClass(\"btn\")||(d=d.closest(\".btn\")),b.call(d,\"toggle\"),a(c.target).is('input[type=\"radio\"]')||a(c.target).is('input[type=\"checkbox\"]')||c.preventDefault()}).on(\"focus.bs.button.data-api blur.bs.button.data-api\",'[data-toggle^=\"button\"]',function(b){a(b.target).closest(\".btn\").toggleClass(\"focus\",/^focus(in)?$/.test(b.type))})}(jQuery),+function(a){\"use strict\";function b(b){return this.each(function(){var d=a(this),e=d.data(\"bs.carousel\"),f=a.extend({},c.DEFAULTS,d.data(),\"object\"==typeof b&&b),g=\"string\"==typeof b?b:f.slide;e||d.data(\"bs.carousel\",e=new c(this,f)),\"number\"==typeof b?e.to(b):g?e[g]():f.interval&&e.pause().cycle()})}var c=function(b,c){this.$element=a(b),this.$indicators=this.$element.find(\".carousel-indicators\"),this.options=c,this.paused=null,this.sliding=null,this.interval=null,this.$active=null,this.$items=null,this.options.keyboard&&this.$element.on(\"keydown.bs.carousel\",a.proxy(this.keydown,this)),\"hover\"==this.options.pause&&!(\"ontouchstart\"in document.documentElement)&&this.$element.on(\"mouseenter.bs.carousel\",a.proxy(this.pause,this)).on(\"mouseleave.bs.carousel\",a.proxy(this.cycle,this))};c.VERSION=\"3.3.6\",c.TRANSITION_DURATION=600,c.DEFAULTS={interval:5e3,pause:\"hover\",wrap:!0,keyboard:!0},c.prototype.keydown=function(a){if(!/input|textarea/i.test(a.target.tagName)){switch(a.which){case 37:this.prev();break;case 39:this.next();break;default:return}a.preventDefault()}},c.prototype.cycle=function(b){return b||(this.paused=!1),this.interval&&clearInterval(this.interval),this.options.interval&&!this.paused&&(this.interval=setInterval(a.proxy(this.next,this),this.options.interval)),this},c.prototype.getItemIndex=function(a){return this.$items=a.parent().children(\".item\"),this.$items.index(a||this.$active)},c.prototype.getItemForDirection=function(a,b){var c=this.getItemIndex(b),d=\"prev\"==a&&0===c||\"next\"==a&&c==this.$items.length-1;if(d&&!this.options.wrap)return b;var e=\"prev\"==a?-1:1,f=(c+e)%this.$items.length;return this.$items.eq(f)},c.prototype.to=function(a){var b=this,c=this.getItemIndex(this.$active=this.$element.find(\".item.active\"));return a>this.$items.length-1||0>a?void 0:this.sliding?this.$element.one(\"slid.bs.carousel\",function(){b.to(a)}):c==a?this.pause().cycle():this.slide(a>c?\"next\":\"prev\",this.$items.eq(a))},c.prototype.pause=function(b){return b||(this.paused=!0),this.$element.find(\".next, .prev\").length&&a.support.transition&&(this.$element.trigger(a.support.transition.end),this.cycle(!0)),this.interval=clearInterval(this.interval),this},c.prototype.next=function(){return this.sliding?void 0:this.slide(\"next\")},c.prototype.prev=function(){return this.sliding?void 0:this.slide(\"prev\")},c.prototype.slide=function(b,d){var e=this.$element.find(\".item.active\"),f=d||this.getItemForDirection(b,e),g=this.interval,h=\"next\"==b?\"left\":\"right\",i=this;if(f.hasClass(\"active\"))return this.sliding=!1;var j=f[0],k=a.Event(\"slide.bs.carousel\",{relatedTarget:j,direction:h});if(this.$element.trigger(k),!k.isDefaultPrevented()){if(this.sliding=!0,g&&this.pause(),this.$indicators.length){this.$indicators.find(\".active\").removeClass(\"active\");var l=a(this.$indicators.children()[this.getItemIndex(f)]);l&&l.addClass(\"active\")}var m=a.Event(\"slid.bs.carousel\",{relatedTarget:j,direction:h});return a.support.transition&&this.$element.hasClass(\"slide\")?(f.addClass(b),f[0].offsetWidth,e.addClass(h),f.addClass(h),e.one(\"bsTransitionEnd\",function(){f.removeClass([b,h].join(\" \")).addClass(\"active\"),e.removeClass([\"active\",h].join(\" \")),i.sliding=!1,setTimeout(function(){i.$element.trigger(m)},0)}).emulateTransitionEnd(c.TRANSITION_DURATION)):(e.removeClass(\"active\"),f.addClass(\"active\"),this.sliding=!1,this.$element.trigger(m)),g&&this.cycle(),this}};var d=a.fn.carousel;a.fn.carousel=b,a.fn.carousel.Constructor=c,a.fn.carousel.noConflict=function(){return a.fn.carousel=d,this};var e=function(c){var d,e=a(this),f=a(e.attr(\"data-target\")||(d=e.attr(\"href\"))&&d.replace(/.*(?=#[^\\s]+$)/,\"\"));if(f.hasClass(\"carousel\")){var g=a.extend({},f.data(),e.data()),h=e.attr(\"data-slide-to\");h&&(g.interval=!1),b.call(f,g),h&&f.data(\"bs.carousel\").to(h),c.preventDefault()}};a(document).on(\"click.bs.carousel.data-api\",\"[data-slide]\",e).on(\"click.bs.carousel.data-api\",\"[data-slide-to]\",e),a(window).on(\"load\",function(){a('[data-ride=\"carousel\"]').each(function(){var c=a(this);b.call(c,c.data())})})}(jQuery),+function(a){\"use strict\";function b(b){var c,d=b.attr(\"data-target\")||(c=b.attr(\"href\"))&&c.replace(/.*(?=#[^\\s]+$)/,\"\");return a(d)}function c(b){return this.each(function(){var c=a(this),e=c.data(\"bs.collapse\"),f=a.extend({},d.DEFAULTS,c.data(),\"object\"==typeof b&&b);!e&&f.toggle&&/show|hide/.test(b)&&(f.toggle=!1),e||c.data(\"bs.collapse\",e=new d(this,f)),\"string\"==typeof b&&e[b]()})}var d=function(b,c){this.$element=a(b),this.options=a.extend({},d.DEFAULTS,c),this.$trigger=a('[data-toggle=\"collapse\"][href=\"#'+b.id+'\"],[data-toggle=\"collapse\"][data-target=\"#'+b.id+'\"]'),this.transitioning=null,this.options.parent?this.$parent=this.getParent():this.addAriaAndCollapsedClass(this.$element,this.$trigger),this.options.toggle&&this.toggle()};d.VERSION=\"3.3.6\",d.TRANSITION_DURATION=350,d.DEFAULTS={toggle:!0},d.prototype.dimension=function(){var a=this.$element.hasClass(\"width\");return a?\"width\":\"height\"},d.prototype.show=function(){if(!this.transitioning&&!this.$element.hasClass(\"in\")){var b,e=this.$parent&&this.$parent.children(\".panel\").children(\".in, .collapsing\");if(!(e&&e.length&&(b=e.data(\"bs.collapse\"),b&&b.transitioning))){var f=a.Event(\"show.bs.collapse\");if(this.$element.trigger(f),!f.isDefaultPrevented()){e&&e.length&&(c.call(e,\"hide\"),b||e.data(\"bs.collapse\",null));var g=this.dimension();this.$element.removeClass(\"collapse\").addClass(\"collapsing\")[g](0).attr(\"aria-expanded\",!0),this.$trigger.removeClass(\"collapsed\").attr(\"aria-expanded\",!0),this.transitioning=1;var h=function(){this.$element.removeClass(\"collapsing\").addClass(\"collapse in\")[g](\"\"),this.transitioning=0,this.$element.trigger(\"shown.bs.collapse\")};if(!a.support.transition)return h.call(this);var i=a.camelCase([\"scroll\",g].join(\"-\"));this.$element.one(\"bsTransitionEnd\",a.proxy(h,this)).emulateTransitionEnd(d.TRANSITION_DURATION)[g](this.$element[0][i])}}}},d.prototype.hide=function(){if(!this.transitioning&&this.$element.hasClass(\"in\")){var b=a.Event(\"hide.bs.collapse\");if(this.$element.trigger(b),!b.isDefaultPrevented()){var c=this.dimension();this.$element[c](this.$element[c]())[0].offsetHeight,this.$element.addClass(\"collapsing\").removeClass(\"collapse in\").attr(\"aria-expanded\",!1),this.$trigger.addClass(\"collapsed\").attr(\"aria-expanded\",!1),this.transitioning=1;var e=function(){this.transitioning=0,this.$element.removeClass(\"collapsing\").addClass(\"collapse\").trigger(\"hidden.bs.collapse\")};return a.support.transition?void this.$element[c](0).one(\"bsTransitionEnd\",a.proxy(e,this)).emulateTransitionEnd(d.TRANSITION_DURATION):e.call(this)}}},d.prototype.toggle=function(){this[this.$element.hasClass(\"in\")?\"hide\":\"show\"]()},d.prototype.getParent=function(){return a(this.options.parent).find('[data-toggle=\"collapse\"][data-parent=\"'+this.options.parent+'\"]').each(a.proxy(function(c,d){var e=a(d);this.addAriaAndCollapsedClass(b(e),e)},this)).end()},d.prototype.addAriaAndCollapsedClass=function(a,b){var c=a.hasClass(\"in\");a.attr(\"aria-expanded\",c),b.toggleClass(\"collapsed\",!c).attr(\"aria-expanded\",c)};var e=a.fn.collapse;a.fn.collapse=c,a.fn.collapse.Constructor=d,a.fn.collapse.noConflict=function(){return a.fn.collapse=e,this},a(document).on(\"click.bs.collapse.data-api\",'[data-toggle=\"collapse\"]',function(d){var e=a(this);e.attr(\"data-target\")||d.preventDefault();var f=b(e),g=f.data(\"bs.collapse\"),h=g?\"toggle\":e.data();c.call(f,h)})}(jQuery),+function(a){\"use strict\";function b(b){var c=b.attr(\"data-target\");c||(c=b.attr(\"href\"),c=c&&/#[A-Za-z]/.test(c)&&c.replace(/.*(?=#[^\\s]*$)/,\"\"));var d=c&&a(c);return d&&d.length?d:b.parent()}function c(c){c&&3===c.which||(a(e).remove(),a(f).each(function(){var d=a(this),e=b(d),f={relatedTarget:this};e.hasClass(\"open\")&&(c&&\"click\"==c.type&&/input|textarea/i.test(c.target.tagName)&&a.contains(e[0],c.target)||(e.trigger(c=a.Event(\"hide.bs.dropdown\",f)),c.isDefaultPrevented()||(d.attr(\"aria-expanded\",\"false\"),e.removeClass(\"open\").trigger(a.Event(\"hidden.bs.dropdown\",f)))))}))}function d(b){return this.each(function(){var c=a(this),d=c.data(\"bs.dropdown\");d||c.data(\"bs.dropdown\",d=new g(this)),\"string\"==typeof b&&d[b].call(c)})}var e=\".dropdown-backdrop\",f='[data-toggle=\"dropdown\"]',g=function(b){a(b).on(\"click.bs.dropdown\",this.toggle)};g.VERSION=\"3.3.6\",g.prototype.toggle=function(d){var e=a(this);if(!e.is(\".disabled, :disabled\")){var f=b(e),g=f.hasClass(\"open\");if(c(),!g){\"ontouchstart\"in document.documentElement&&!f.closest(\".navbar-nav\").length&&a(document.createElement(\"div\")).addClass(\"dropdown-backdrop\").insertAfter(a(this)).on(\"click\",c);var h={relatedTarget:this};if(f.trigger(d=a.Event(\"show.bs.dropdown\",h)),d.isDefaultPrevented())return;e.trigger(\"focus\").attr(\"aria-expanded\",\"true\"),f.toggleClass(\"open\").trigger(a.Event(\"shown.bs.dropdown\",h))}return!1}},g.prototype.keydown=function(c){if(/(38|40|27|32)/.test(c.which)&&!/input|textarea/i.test(c.target.tagName)){var d=a(this);if(c.preventDefault(),c.stopPropagation(),!d.is(\".disabled, :disabled\")){var e=b(d),g=e.hasClass(\"open\");if(!g&&27!=c.which||g&&27==c.which)return 27==c.which&&e.find(f).trigger(\"focus\"),d.trigger(\"click\");var h=\" li:not(.disabled):visible a\",i=e.find(\".dropdown-menu\"+h);if(i.length){var j=i.index(c.target);38==c.which&&j>0&&j--,40==c.which&&j<i.length-1&&j++,~j||(j=0),i.eq(j).trigger(\"focus\")}}}};var h=a.fn.dropdown;a.fn.dropdown=d,a.fn.dropdown.Constructor=g,a.fn.dropdown.noConflict=function(){return a.fn.dropdown=h,this},a(document).on(\"click.bs.dropdown.data-api\",c).on(\"click.bs.dropdown.data-api\",\".dropdown form\",function(a){a.stopPropagation()}).on(\"click.bs.dropdown.data-api\",f,g.prototype.toggle).on(\"keydown.bs.dropdown.data-api\",f,g.prototype.keydown).on(\"keydown.bs.dropdown.data-api\",\".dropdown-menu\",g.prototype.keydown)}(jQuery),+function(a){\"use strict\";function b(b,d){return this.each(function(){var e=a(this),f=e.data(\"bs.modal\"),g=a.extend({},c.DEFAULTS,e.data(),\"object\"==typeof b&&b);f||e.data(\"bs.modal\",f=new c(this,g)),\"string\"==typeof b?f[b](d):g.show&&f.show(d)})}var c=function(b,c){this.options=c,this.$body=a(document.body),this.$element=a(b),this.$dialog=this.$element.find(\".modal-dialog\"),this.$backdrop=null,this.isShown=null,this.originalBodyPad=null,this.scrollbarWidth=0,this.ignoreBackdropClick=!1,this.options.remote&&this.$element.find(\".modal-content\").load(this.options.remote,a.proxy(function(){this.$element.trigger(\"loaded.bs.modal\")},this))};c.VERSION=\"3.3.6\",c.TRANSITION_DURATION=300,c.BACKDROP_TRANSITION_DURATION=150,c.DEFAULTS={backdrop:!0,keyboard:!0,show:!0},c.prototype.toggle=function(a){return this.isShown?this.hide():this.show(a)},c.prototype.show=function(b){var d=this,e=a.Event(\"show.bs.modal\",{relatedTarget:b});this.$element.trigger(e),this.isShown||e.isDefaultPrevented()||(this.isShown=!0,this.checkScrollbar(),this.setScrollbar(),this.$body.addClass(\"modal-open\"),this.escape(),this.resize(),this.$element.on(\"click.dismiss.bs.modal\",'[data-dismiss=\"modal\"]',a.proxy(this.hide,this)),this.$dialog.on(\"mousedown.dismiss.bs.modal\",function(){d.$element.one(\"mouseup.dismiss.bs.modal\",function(b){a(b.target).is(d.$element)&&(d.ignoreBackdropClick=!0)})}),this.backdrop(function(){var e=a.support.transition&&d.$element.hasClass(\"fade\");d.$element.parent().length||d.$element.appendTo(d.$body),d.$element.show().scrollTop(0),d.adjustDialog(),e&&d.$element[0].offsetWidth,d.$element.addClass(\"in\"),d.enforceFocus();var f=a.Event(\"shown.bs.modal\",{relatedTarget:b});e?d.$dialog.one(\"bsTransitionEnd\",function(){d.$element.trigger(\"focus\").trigger(f)}).emulateTransitionEnd(c.TRANSITION_DURATION):d.$element.trigger(\"focus\").trigger(f)}))},c.prototype.hide=function(b){b&&b.preventDefault(),b=a.Event(\"hide.bs.modal\"),this.$element.trigger(b),this.isShown&&!b.isDefaultPrevented()&&(this.isShown=!1,this.escape(),this.resize(),a(document).off(\"focusin.bs.modal\"),this.$element.removeClass(\"in\").off(\"click.dismiss.bs.modal\").off(\"mouseup.dismiss.bs.modal\"),this.$dialog.off(\"mousedown.dismiss.bs.modal\"),a.support.transition&&this.$element.hasClass(\"fade\")?this.$element.one(\"bsTransitionEnd\",a.proxy(this.hideModal,this)).emulateTransitionEnd(c.TRANSITION_DURATION):this.hideModal())},c.prototype.enforceFocus=function(){a(document).off(\"focusin.bs.modal\").on(\"focusin.bs.modal\",a.proxy(function(a){this.$element[0]===a.target||this.$element.has(a.target).length||this.$element.trigger(\"focus\")},this))},c.prototype.escape=function(){this.isShown&&this.options.keyboard?this.$element.on(\"keydown.dismiss.bs.modal\",a.proxy(function(a){27==a.which&&this.hide()},this)):this.isShown||this.$element.off(\"keydown.dismiss.bs.modal\")},c.prototype.resize=function(){this.isShown?a(window).on(\"resize.bs.modal\",a.proxy(this.handleUpdate,this)):a(window).off(\"resize.bs.modal\")},c.prototype.hideModal=function(){var a=this;this.$element.hide(),this.backdrop(function(){a.$body.removeClass(\"modal-open\"),a.resetAdjustments(),a.resetScrollbar(),a.$element.trigger(\"hidden.bs.modal\")})},c.prototype.removeBackdrop=function(){this.$backdrop&&this.$backdrop.remove(),this.$backdrop=null},c.prototype.backdrop=function(b){var d=this,e=this.$element.hasClass(\"fade\")?\"fade\":\"\";if(this.isShown&&this.options.backdrop){var f=a.support.transition&&e;if(this.$backdrop=a(document.createElement(\"div\")).addClass(\"modal-backdrop \"+e).appendTo(this.$body),this.$element.on(\"click.dismiss.bs.modal\",a.proxy(function(a){return this.ignoreBackdropClick?void(this.ignoreBackdropClick=!1):void(a.target===a.currentTarget&&(\"static\"==this.options.backdrop?this.$element[0].focus():this.hide()))},this)),f&&this.$backdrop[0].offsetWidth,this.$backdrop.addClass(\"in\"),!b)return;f?this.$backdrop.one(\"bsTransitionEnd\",b).emulateTransitionEnd(c.BACKDROP_TRANSITION_DURATION):b()}else if(!this.isShown&&this.$backdrop){this.$backdrop.removeClass(\"in\");var g=function(){d.removeBackdrop(),b&&b()};a.support.transition&&this.$element.hasClass(\"fade\")?this.$backdrop.one(\"bsTransitionEnd\",g).emulateTransitionEnd(c.BACKDROP_TRANSITION_DURATION):g()}else b&&b()},c.prototype.handleUpdate=function(){this.adjustDialog()},c.prototype.adjustDialog=function(){var a=this.$element[0].scrollHeight>document.documentElement.clientHeight;this.$element.css({paddingLeft:!this.bodyIsOverflowing&&a?this.scrollbarWidth:\"\",paddingRight:this.bodyIsOverflowing&&!a?this.scrollbarWidth:\"\"})},c.prototype.resetAdjustments=function(){this.$element.css({paddingLeft:\"\",paddingRight:\"\"})},c.prototype.checkScrollbar=function(){var a=window.innerWidth;if(!a){var b=document.documentElement.getBoundingClientRect();a=b.right-Math.abs(b.left)}this.bodyIsOverflowing=document.body.clientWidth<a,this.scrollbarWidth=this.measureScrollbar()},c.prototype.setScrollbar=function(){var a=parseInt(this.$body.css(\"padding-right\")||0,10);this.originalBodyPad=document.body.style.paddingRight||\"\",this.bodyIsOverflowing&&this.$body.css(\"padding-right\",a+this.scrollbarWidth)},c.prototype.resetScrollbar=function(){this.$body.css(\"padding-right\",this.originalBodyPad)},c.prototype.measureScrollbar=function(){var a=document.createElement(\"div\");a.className=\"modal-scrollbar-measure\",this.$body.append(a);var b=a.offsetWidth-a.clientWidth;return this.$body[0].removeChild(a),b};var d=a.fn.modal;a.fn.modal=b,a.fn.modal.Constructor=c,a.fn.modal.noConflict=function(){return a.fn.modal=d,this},a(document).on(\"click.bs.modal.data-api\",'[data-toggle=\"modal\"]',function(c){var d=a(this),e=d.attr(\"href\"),f=a(d.attr(\"data-target\")||e&&e.replace(/.*(?=#[^\\s]+$)/,\"\")),g=f.data(\"bs.modal\")?\"toggle\":a.extend({remote:!/#/.test(e)&&e},f.data(),d.data());d.is(\"a\")&&c.preventDefault(),f.one(\"show.bs.modal\",function(a){a.isDefaultPrevented()||f.one(\"hidden.bs.modal\",function(){d.is(\":visible\")&&d.trigger(\"focus\")})}),b.call(f,g,this)})}(jQuery),+function(a){\"use strict\";function b(b){return this.each(function(){var d=a(this),e=d.data(\"bs.tooltip\"),f=\"object\"==typeof b&&b;(e||!/destroy|hide/.test(b))&&(e||d.data(\"bs.tooltip\",e=new c(this,f)),\"string\"==typeof b&&e[b]())})}var c=function(a,b){this.type=null,this.options=null,this.enabled=null,this.timeout=null,this.hoverState=null,this.$element=null,this.inState=null,this.init(\"tooltip\",a,b)};c.VERSION=\"3.3.6\",c.TRANSITION_DURATION=150,c.DEFAULTS={animation:!0,placement:\"top\",selector:!1,template:'<div class=\"tooltip\" role=\"tooltip\"><div class=\"tooltip-arrow\"></div><div class=\"tooltip-inner\"></div></div>',trigger:\"hover focus\",title:\"\",delay:0,html:!1,container:!1,viewport:{selector:\"body\",padding:0}},c.prototype.init=function(b,c,d){if(this.enabled=!0,this.type=b,this.$element=a(c),this.options=this.getOptions(d),this.$viewport=this.options.viewport&&a(a.isFunction(this.options.viewport)?this.options.viewport.call(this,this.$element):this.options.viewport.selector||this.options.viewport),this.inState={click:!1,hover:!1,focus:!1},this.$element[0]instanceof document.constructor&&!this.options.selector)throw new Error(\"`selector` option must be specified when initializing \"+this.type+\" on the window.document object!\");for(var e=this.options.trigger.split(\" \"),f=e.length;f--;){var g=e[f];if(\"click\"==g)this.$element.on(\"click.\"+this.type,this.options.selector,a.proxy(this.toggle,this));else if(\"manual\"!=g){var h=\"hover\"==g?\"mouseenter\":\"focusin\",i=\"hover\"==g?\"mouseleave\":\"focusout\";this.$element.on(h+\".\"+this.type,this.options.selector,a.proxy(this.enter,this)),this.$element.on(i+\".\"+this.type,this.options.selector,a.proxy(this.leave,this))}}this.options.selector?this._options=a.extend({},this.options,{trigger:\"manual\",selector:\"\"}):this.fixTitle()},c.prototype.getDefaults=function(){return c.DEFAULTS},c.prototype.getOptions=function(b){return b=a.extend({},this.getDefaults(),this.$element.data(),b),b.delay&&\"number\"==typeof b.delay&&(b.delay={show:b.delay,hide:b.delay}),b},c.prototype.getDelegateOptions=function(){var b={},c=this.getDefaults();return this._options&&a.each(this._options,function(a,d){c[a]!=d&&(b[a]=d)}),b},c.prototype.enter=function(b){var c=b instanceof this.constructor?b:a(b.currentTarget).data(\"bs.\"+this.type);return c||(c=new this.constructor(b.currentTarget,this.getDelegateOptions()),a(b.currentTarget).data(\"bs.\"+this.type,c)),b instanceof a.Event&&(c.inState[\"focusin\"==b.type?\"focus\":\"hover\"]=!0),c.tip().hasClass(\"in\")||\"in\"==c.hoverState?void(c.hoverState=\"in\"):(clearTimeout(c.timeout),c.hoverState=\"in\",c.options.delay&&c.options.delay.show?void(c.timeout=setTimeout(function(){\"in\"==c.hoverState&&c.show()},c.options.delay.show)):c.show())},c.prototype.isInStateTrue=function(){for(var a in this.inState)if(this.inState[a])return!0;return!1},c.prototype.leave=function(b){var c=b instanceof this.constructor?b:a(b.currentTarget).data(\"bs.\"+this.type);return c||(c=new this.constructor(b.currentTarget,this.getDelegateOptions()),a(b.currentTarget).data(\"bs.\"+this.type,c)),b instanceof a.Event&&(c.inState[\"focusout\"==b.type?\"focus\":\"hover\"]=!1),c.isInStateTrue()?void 0:(clearTimeout(c.timeout),c.hoverState=\"out\",c.options.delay&&c.options.delay.hide?void(c.timeout=setTimeout(function(){\"out\"==c.hoverState&&c.hide()},c.options.delay.hide)):c.hide())},c.prototype.show=function(){var b=a.Event(\"show.bs.\"+this.type);if(this.hasContent()&&this.enabled){this.$element.trigger(b);var d=a.contains(this.$element[0].ownerDocument.documentElement,this.$element[0]);if(b.isDefaultPrevented()||!d)return;var e=this,f=this.tip(),g=this.getUID(this.type);this.setContent(),f.attr(\"id\",g),this.$element.attr(\"aria-describedby\",g),this.options.animation&&f.addClass(\"fade\");var h=\"function\"==typeof this.options.placement?this.options.placement.call(this,f[0],this.$element[0]):this.options.placement,i=/\\s?auto?\\s?/i,j=i.test(h);j&&(h=h.replace(i,\"\")||\"top\"),f.detach().css({top:0,left:0,display:\"block\"}).addClass(h).data(\"bs.\"+this.type,this),this.options.container?f.appendTo(this.options.container):f.insertAfter(this.$element),this.$element.trigger(\"inserted.bs.\"+this.type);var k=this.getPosition(),l=f[0].offsetWidth,m=f[0].offsetHeight;if(j){var n=h,o=this.getPosition(this.$viewport);h=\"bottom\"==h&&k.bottom+m>o.bottom?\"top\":\"top\"==h&&k.top-m<o.top?\"bottom\":\"right\"==h&&k.right+l>o.width?\"left\":\"left\"==h&&k.left-l<o.left?\"right\":h,f.removeClass(n).addClass(h)}var p=this.getCalculatedOffset(h,k,l,m);this.applyPlacement(p,h);var q=function(){var a=e.hoverState;e.$element.trigger(\"shown.bs.\"+e.type),e.hoverState=null,\"out\"==a&&e.leave(e)};a.support.transition&&this.$tip.hasClass(\"fade\")?f.one(\"bsTransitionEnd\",q).emulateTransitionEnd(c.TRANSITION_DURATION):q()}},c.prototype.applyPlacement=function(b,c){var d=this.tip(),e=d[0].offsetWidth,f=d[0].offsetHeight,g=parseInt(d.css(\"margin-top\"),10),h=parseInt(d.css(\"margin-left\"),10);isNaN(g)&&(g=0),isNaN(h)&&(h=0),b.top+=g,b.left+=h,a.offset.setOffset(d[0],a.extend({using:function(a){d.css({top:Math.round(a.top),left:Math.round(a.left)})}},b),0),d.addClass(\"in\");var i=d[0].offsetWidth,j=d[0].offsetHeight;\"top\"==c&&j!=f&&(b.top=b.top+f-j);var k=this.getViewportAdjustedDelta(c,b,i,j);k.left?b.left+=k.left:b.top+=k.top;var l=/top|bottom/.test(c),m=l?2*k.left-e+i:2*k.top-f+j,n=l?\"offsetWidth\":\"offsetHeight\";d.offset(b),this.replaceArrow(m,d[0][n],l)},c.prototype.replaceArrow=function(a,b,c){this.arrow().css(c?\"left\":\"top\",50*(1-a/b)+\"%\").css(c?\"top\":\"left\",\"\")},c.prototype.setContent=function(){var a=this.tip(),b=this.getTitle();a.find(\".tooltip-inner\")[this.options.html?\"html\":\"text\"](b),a.removeClass(\"fade in top bottom left right\")},c.prototype.hide=function(b){function d(){\"in\"!=e.hoverState&&f.detach(),e.$element.removeAttr(\"aria-describedby\").trigger(\"hidden.bs.\"+e.type),b&&b()}var e=this,f=a(this.$tip),g=a.Event(\"hide.bs.\"+this.type);return this.$element.trigger(g),g.isDefaultPrevented()?void 0:(f.removeClass(\"in\"),a.support.transition&&f.hasClass(\"fade\")?f.one(\"bsTransitionEnd\",d).emulateTransitionEnd(c.TRANSITION_DURATION):d(),this.hoverState=null,this)},c.prototype.fixTitle=function(){var a=this.$element;(a.attr(\"title\")||\"string\"!=typeof a.attr(\"data-original-title\"))&&a.attr(\"data-original-title\",a.attr(\"title\")||\"\").attr(\"title\",\"\")},c.prototype.hasContent=function(){return this.getTitle()},c.prototype.getPosition=function(b){b=b||this.$element;var c=b[0],d=\"BODY\"==c.tagName,e=c.getBoundingClientRect();null==e.width&&(e=a.extend({},e,{width:e.right-e.left,height:e.bottom-e.top}));var f=d?{top:0,left:0}:b.offset(),g={scroll:d?document.documentElement.scrollTop||document.body.scrollTop:b.scrollTop()},h=d?{width:a(window).width(),height:a(window).height()}:null;return a.extend({},e,g,h,f)},c.prototype.getCalculatedOffset=function(a,b,c,d){return\"bottom\"==a?{top:b.top+b.height,left:b.left+b.width/2-c/2}:\"top\"==a?{top:b.top-d,left:b.left+b.width/2-c/2}:\"left\"==a?{top:b.top+b.height/2-d/2,left:b.left-c}:{top:b.top+b.height/2-d/2,left:b.left+b.width}},c.prototype.getViewportAdjustedDelta=function(a,b,c,d){var e={top:0,left:0};if(!this.$viewport)return e;var f=this.options.viewport&&this.options.viewport.padding||0,g=this.getPosition(this.$viewport);if(/right|left/.test(a)){var h=b.top-f-g.scroll,i=b.top+f-g.scroll+d;h<g.top?e.top=g.top-h:i>g.top+g.height&&(e.top=g.top+g.height-i)}else{var j=b.left-f,k=b.left+f+c;j<g.left?e.left=g.left-j:k>g.right&&(e.left=g.left+g.width-k)}return e},c.prototype.getTitle=function(){var a,b=this.$element,c=this.options;return a=b.attr(\"data-original-title\")||(\"function\"==typeof c.title?c.title.call(b[0]):c.title)},c.prototype.getUID=function(a){do a+=~~(1e6*Math.random());while(document.getElementById(a));return a},c.prototype.tip=function(){if(!this.$tip&&(this.$tip=a(this.options.template),1!=this.$tip.length))throw new Error(this.type+\" `template` option must consist of exactly 1 top-level element!\");return this.$tip},c.prototype.arrow=function(){return this.$arrow=this.$arrow||this.tip().find(\".tooltip-arrow\")},c.prototype.enable=function(){this.enabled=!0},c.prototype.disable=function(){this.enabled=!1},c.prototype.toggleEnabled=function(){this.enabled=!this.enabled},c.prototype.toggle=function(b){var c=this;b&&(c=a(b.currentTarget).data(\"bs.\"+this.type),c||(c=new this.constructor(b.currentTarget,this.getDelegateOptions()),a(b.currentTarget).data(\"bs.\"+this.type,c))),b?(c.inState.click=!c.inState.click,c.isInStateTrue()?c.enter(c):c.leave(c)):c.tip().hasClass(\"in\")?c.leave(c):c.enter(c)},c.prototype.destroy=function(){var a=this;clearTimeout(this.timeout),this.hide(function(){a.$element.off(\".\"+a.type).removeData(\"bs.\"+a.type),a.$tip&&a.$tip.detach(),a.$tip=null,a.$arrow=null,a.$viewport=null})};var d=a.fn.tooltip;a.fn.tooltip=b,a.fn.tooltip.Constructor=c,a.fn.tooltip.noConflict=function(){return a.fn.tooltip=d,this}}(jQuery),+function(a){\"use strict\";function b(b){return this.each(function(){var d=a(this),e=d.data(\"bs.popover\"),f=\"object\"==typeof b&&b;(e||!/destroy|hide/.test(b))&&(e||d.data(\"bs.popover\",e=new c(this,f)),\"string\"==typeof b&&e[b]())})}var c=function(a,b){this.init(\"popover\",a,b)};if(!a.fn.tooltip)throw new Error(\"Popover requires tooltip.js\");c.VERSION=\"3.3.6\",c.DEFAULTS=a.extend({},a.fn.tooltip.Constructor.DEFAULTS,{placement:\"right\",trigger:\"click\",content:\"\",template:'<div class=\"popover\" role=\"tooltip\"><div class=\"arrow\"></div><h3 class=\"popover-title\"></h3><div class=\"popover-content\"></div></div>'}),c.prototype=a.extend({},a.fn.tooltip.Constructor.prototype),c.prototype.constructor=c,c.prototype.getDefaults=function(){return c.DEFAULTS},c.prototype.setContent=function(){var a=this.tip(),b=this.getTitle(),c=this.getContent();a.find(\".popover-title\")[this.options.html?\"html\":\"text\"](b),a.find(\".popover-content\").children().detach().end()[this.options.html?\"string\"==typeof c?\"html\":\"append\":\"text\"](c),a.removeClass(\"fade top bottom left right in\"),a.find(\".popover-title\").html()||a.find(\".popover-title\").hide()},c.prototype.hasContent=function(){return this.getTitle()||this.getContent()},c.prototype.getContent=function(){var a=this.$element,b=this.options;return a.attr(\"data-content\")||(\"function\"==typeof b.content?b.content.call(a[0]):b.content)},c.prototype.arrow=function(){return this.$arrow=this.$arrow||this.tip().find(\".arrow\")};var d=a.fn.popover;a.fn.popover=b,a.fn.popover.Constructor=c,a.fn.popover.noConflict=function(){return a.fn.popover=d,this}}(jQuery),+function(a){\"use strict\";function b(c,d){this.$body=a(document.body),this.$scrollElement=a(a(c).is(document.body)?window:c),this.options=a.extend({},b.DEFAULTS,d),this.selector=(this.options.target||\"\")+\" .nav li > a\",this.offsets=[],this.targets=[],this.activeTarget=null,this.scrollHeight=0,this.$scrollElement.on(\"scroll.bs.scrollspy\",a.proxy(this.process,this)),this.refresh(),this.process()}function c(c){return this.each(function(){var d=a(this),e=d.data(\"bs.scrollspy\"),f=\"object\"==typeof c&&c;e||d.data(\"bs.scrollspy\",e=new b(this,f)),\"string\"==typeof c&&e[c]()})}b.VERSION=\"3.3.6\",b.DEFAULTS={offset:10},b.prototype.getScrollHeight=function(){return this.$scrollElement[0].scrollHeight||Math.max(this.$body[0].scrollHeight,document.documentElement.scrollHeight)},b.prototype.refresh=function(){var b=this,c=\"offset\",d=0;this.offsets=[],this.targets=[],this.scrollHeight=this.getScrollHeight(),a.isWindow(this.$scrollElement[0])||(c=\"position\",d=this.$scrollElement.scrollTop()),this.$body.find(this.selector).map(function(){var b=a(this),e=b.data(\"target\")||b.attr(\"href\"),f=/^#./.test(e)&&a(e);return f&&f.length&&f.is(\":visible\")&&[[f[c]().top+d,e]]||null}).sort(function(a,b){return a[0]-b[0]}).each(function(){b.offsets.push(this[0]),b.targets.push(this[1])})},b.prototype.process=function(){var a,b=this.$scrollElement.scrollTop()+this.options.offset,c=this.getScrollHeight(),d=this.options.offset+c-this.$scrollElement.height(),e=this.offsets,f=this.targets,g=this.activeTarget;if(this.scrollHeight!=c&&this.refresh(),b>=d)return g!=(a=f[f.length-1])&&this.activate(a);if(g&&b<e[0])return this.activeTarget=null,this.clear();for(a=e.length;a--;)g!=f[a]&&b>=e[a]&&(void 0===e[a+1]||b<e[a+1])&&this.activate(f[a])},b.prototype.activate=function(b){this.activeTarget=b,this.clear();var c=this.selector+'[data-target=\"'+b+'\"],'+this.selector+'[href=\"'+b+'\"]',d=a(c).parents(\"li\").addClass(\"active\");\n d.parent(\".dropdown-menu\").length&&(d=d.closest(\"li.dropdown\").addClass(\"active\")),d.trigger(\"activate.bs.scrollspy\")},b.prototype.clear=function(){a(this.selector).parentsUntil(this.options.target,\".active\").removeClass(\"active\")};var d=a.fn.scrollspy;a.fn.scrollspy=c,a.fn.scrollspy.Constructor=b,a.fn.scrollspy.noConflict=function(){return a.fn.scrollspy=d,this},a(window).on(\"load.bs.scrollspy.data-api\",function(){a('[data-spy=\"scroll\"]').each(function(){var b=a(this);c.call(b,b.data())})})}(jQuery),+function(a){\"use strict\";function b(b){return this.each(function(){var d=a(this),e=d.data(\"bs.tab\");e||d.data(\"bs.tab\",e=new c(this)),\"string\"==typeof b&&e[b]()})}var c=function(b){this.element=a(b)};c.VERSION=\"3.3.6\",c.TRANSITION_DURATION=150,c.prototype.show=function(){var b=this.element,c=b.closest(\"ul:not(.dropdown-menu)\"),d=b.data(\"target\");if(d||(d=b.attr(\"href\"),d=d&&d.replace(/.*(?=#[^\\s]*$)/,\"\")),!b.parent(\"li\").hasClass(\"active\")){var e=c.find(\".active:last a\"),f=a.Event(\"hide.bs.tab\",{relatedTarget:b[0]}),g=a.Event(\"show.bs.tab\",{relatedTarget:e[0]});if(e.trigger(f),b.trigger(g),!g.isDefaultPrevented()&&!f.isDefaultPrevented()){var h=a(d);this.activate(b.closest(\"li\"),c),this.activate(h,h.parent(),function(){e.trigger({type:\"hidden.bs.tab\",relatedTarget:b[0]}),b.trigger({type:\"shown.bs.tab\",relatedTarget:e[0]})})}}},c.prototype.activate=function(b,d,e){function f(){g.removeClass(\"active\").find(\"> .dropdown-menu > .active\").removeClass(\"active\").end().find('[data-toggle=\"tab\"]').attr(\"aria-expanded\",!1),b.addClass(\"active\").find('[data-toggle=\"tab\"]').attr(\"aria-expanded\",!0),h?(b[0].offsetWidth,b.addClass(\"in\")):b.removeClass(\"fade\"),b.parent(\".dropdown-menu\").length&&b.closest(\"li.dropdown\").addClass(\"active\").end().find('[data-toggle=\"tab\"]').attr(\"aria-expanded\",!0),e&&e()}var g=d.find(\"> .active\"),h=e&&a.support.transition&&(g.length&&g.hasClass(\"fade\")||!!d.find(\"> .fade\").length);g.length&&h?g.one(\"bsTransitionEnd\",f).emulateTransitionEnd(c.TRANSITION_DURATION):f(),g.removeClass(\"in\")};var d=a.fn.tab;a.fn.tab=b,a.fn.tab.Constructor=c,a.fn.tab.noConflict=function(){return a.fn.tab=d,this};var e=function(c){c.preventDefault(),b.call(a(this),\"show\")};a(document).on(\"click.bs.tab.data-api\",'[data-toggle=\"tab\"]',e).on(\"click.bs.tab.data-api\",'[data-toggle=\"pill\"]',e)}(jQuery),+function(a){\"use strict\";function b(b){return this.each(function(){var d=a(this),e=d.data(\"bs.affix\"),f=\"object\"==typeof b&&b;e||d.data(\"bs.affix\",e=new c(this,f)),\"string\"==typeof b&&e[b]()})}var c=function(b,d){this.options=a.extend({},c.DEFAULTS,d),this.$target=a(this.options.target).on(\"scroll.bs.affix.data-api\",a.proxy(this.checkPosition,this)).on(\"click.bs.affix.data-api\",a.proxy(this.checkPositionWithEventLoop,this)),this.$element=a(b),this.affixed=null,this.unpin=null,this.pinnedOffset=null,this.checkPosition()};c.VERSION=\"3.3.6\",c.RESET=\"affix affix-top affix-bottom\",c.DEFAULTS={offset:0,target:window},c.prototype.getState=function(a,b,c,d){var e=this.$target.scrollTop(),f=this.$element.offset(),g=this.$target.height();if(null!=c&&\"top\"==this.affixed)return c>e?\"top\":!1;if(\"bottom\"==this.affixed)return null!=c?e+this.unpin<=f.top?!1:\"bottom\":a-d>=e+g?!1:\"bottom\";var h=null==this.affixed,i=h?e:f.top,j=h?g:b;return null!=c&&c>=e?\"top\":null!=d&&i+j>=a-d?\"bottom\":!1},c.prototype.getPinnedOffset=function(){if(this.pinnedOffset)return this.pinnedOffset;this.$element.removeClass(c.RESET).addClass(\"affix\");var a=this.$target.scrollTop(),b=this.$element.offset();return this.pinnedOffset=b.top-a},c.prototype.checkPositionWithEventLoop=function(){setTimeout(a.proxy(this.checkPosition,this),1)},c.prototype.checkPosition=function(){if(this.$element.is(\":visible\")){var b=this.$element.height(),d=this.options.offset,e=d.top,f=d.bottom,g=Math.max(a(document).height(),a(document.body).height());\"object\"!=typeof d&&(f=e=d),\"function\"==typeof e&&(e=d.top(this.$element)),\"function\"==typeof f&&(f=d.bottom(this.$element));var h=this.getState(g,b,e,f);if(this.affixed!=h){null!=this.unpin&&this.$element.css(\"top\",\"\");var i=\"affix\"+(h?\"-\"+h:\"\"),j=a.Event(i+\".bs.affix\");if(this.$element.trigger(j),j.isDefaultPrevented())return;this.affixed=h,this.unpin=\"bottom\"==h?this.getPinnedOffset():null,this.$element.removeClass(c.RESET).addClass(i).trigger(i.replace(\"affix\",\"affixed\")+\".bs.affix\")}\"bottom\"==h&&this.$element.offset({top:g-b-f})}};var d=a.fn.affix;a.fn.affix=b,a.fn.affix.Constructor=c,a.fn.affix.noConflict=function(){return a.fn.affix=d,this},a(window).on(\"load\",function(){a('[data-spy=\"affix\"]').each(function(){var c=a(this),d=c.data();d.offset=d.offset||{},null!=d.offsetBottom&&(d.offset.bottom=d.offsetBottom),null!=d.offsetTop&&(d.offset.top=d.offsetTop),b.call(c,d)})})}(jQuery);","StripeIntegration_Payments/js/stripe.js":"// Copyright \u00a9 Stripe, Inc\n//\n// @package StripeIntegration_Payments\n// @version 4.2.0\ndefine(\n [\n 'stripejs'\n ],\n function ()\n {\n 'use strict';\n\n // Warning: This file should be kept lightweight as it is loaded on nearly all pages.\n\n return (window.stripe = {\n\n // Properties\n version: \"4.2.0\",\n stripeJs: null,\n\n initStripe: function(params, callback)\n {\n if (typeof callback == \"undefined\")\n callback = null;\n\n var message = null;\n\n if (!this.stripeJs)\n {\n try\n {\n var options = {};\n if (params.options)\n {\n options = params.options;\n }\n\n this.stripeJs = Stripe(params.apiKey, options);\n }\n catch (e)\n {\n if (typeof e != \"undefined\" && typeof e.message != \"undefined\")\n message = 'Could not initialize Stripe.js: ' + e.message;\n else\n message = 'Could not initialize Stripe.js';\n }\n\n if (this.stripeJs && typeof params.appInfo != \"undefined\")\n {\n try\n {\n this.stripeJs.registerAppInfo(params.appInfo);\n }\n catch (e)\n {\n console.warn(e);\n }\n }\n }\n\n if (callback)\n callback(message);\n else if (message)\n console.error(message);\n },\n\n authenticateCustomer: function(intentId, done) {\n try {\n var isPaymentIntent = intentId.startsWith('pi_');\n var isSetupIntent = intentId.startsWith('seti_');\n\n var handleIntent = function(result) {\n if (result.error)\n return done(result.error);\n\n var intent = result.paymentIntent || result.setupIntent;\n var requiresActionStatuses = [\"requires_action\", \"requires_source_action\"];\n\n if (requiresActionStatuses.includes(intent.status))\n {\n if (intent.next_action && intent.next_action.type === \"verify_with_microdeposits\")\n {\n window.location = intent.next_action.verify_with_microdeposits.hosted_verification_url;\n }\n else\n {\n stripe.stripeJs.handleNextAction({\n clientSecret: intent.client_secret\n })\n .then(function(result)\n {\n if (result && result.error)\n {\n return done(result.error.message);\n }\n\n return done();\n });\n }\n }\n else\n {\n return done();\n }\n };\n\n if (isPaymentIntent) {\n this.stripeJs.retrievePaymentIntent(intentId).then(handleIntent);\n } else if (isSetupIntent) {\n this.stripeJs.retrieveSetupIntent(intentId).then(handleIntent);\n } else {\n throw new Error(\"Invalid intent ID\");\n }\n } catch (e) {\n done(e.message);\n }\n }\n });\n }\n);\n","StripeIntegration_Payments/js/stripe_payments_express.js":"/*global define*/\ndefine(\n [\n 'jquery',\n 'mage/url',\n 'mage/storage',\n 'Magento_Ui/js/modal/alert',\n 'mage/translate',\n 'Magento_Customer/js/customer-data',\n 'StripeIntegration_Payments/js/stripe',\n 'mage/loader'\n ],\n function (\n jQuery,\n urlBuilder,\n storage,\n alert,\n $t,\n customerData,\n stripe\n ) {\n 'use strict';\n\n return {\n shippingAddress: [],\n shippingMethod: null,\n elements: null,\n expressCheckoutElement: null,\n expressCheckoutOptions: null,\n clickResolvePayload: null,\n resolvePayload: null,\n pendingActionsQueue: [],\n isAddToCartPending: false,\n waitingForNewTotals: false,\n lastTotal: null,\n mountElementId: null,\n mode: null,\n isLoading: false,\n debug: false,\n\n getExpressCheckoutElementParams: function(payload, callback)\n {\n var serviceUrl = urlBuilder.build('/rest/V1/stripe/payments/ece_params', {}),\n self = this;\n\n return storage.post(\n serviceUrl,\n JSON.stringify(payload),\n false\n )\n .fail(function (xhr, textStatus, errorThrown)\n {\n console.error(\"Could not retrieve initialization params for Express Checkout\");\n })\n .done(function (response) {\n self.processResponseWithECEParams(response, callback);\n });\n },\n\n processResponseWithECEParams: function(response, callback)\n {\n try\n {\n if (typeof response === 'string') {\n response = JSON.parse(response);\n }\n\n if (response && response.resolvePayload)\n {\n if (response.resolvePayload.allowedShippingCountries)\n {\n // Convert to object map to array\n response.resolvePayload.allowedShippingCountries = Object.keys(response.resolvePayload.allowedShippingCountries).map(function (key) { return response.resolvePayload.allowedShippingCountries[key]; });\n }\n\n callback(null, response);\n }\n else\n {\n callback(null, response);\n }\n }\n catch (e)\n {\n callback(e.message, response);\n }\n },\n\n /**\n * Init Stripe Express\n * @param elementId\n * @param apiKey\n * @param paramsType\n * @param settings\n * @param callback\n */\n initStripeExpress: function (elementId, stripeJsInitParams, locationDetails, expressCheckoutOptions, callback)\n {\n // Only one express element is allowed per page\n if (locationDetails.location == 'minicart')\n {\n if (document.body.classList.contains('catalog-product-view') && // We are on the product page\n locationDetails.activeLocations.indexOf('product_page') >= 0) // ECE is enabled on the product page\n return;\n\n if (document.body.classList.contains('checkout-cart-index') && // We are on the cart page\n locationDetails.activeLocations.indexOf('shopping_cart_page') >= 0) // ECE is enabled on the cart page\n return;\n }\n\n if (this.waitingForNewTotals)\n {\n // This method can be called from cart.subscribe(). In that case, we do not want to re-initialize the widget\n // because we are waiting for the addToCart() to finish. We will update the amounts after the addToCart() is done.\n return;\n }\n\n var self = this;\n this.mountElementId = elementId;\n this.stripeJsInitParams = stripeJsInitParams;\n this.locationDetails = locationDetails;\n this.expressCheckoutOptions = expressCheckoutOptions;\n\n this.getExpressCheckoutElementParams(locationDetails, function(err, result)\n {\n if (err)\n {\n console.warn('Cannot initialize wallets: ' + err);\n return;\n }\n\n if (!result.elementOptions)\n return;\n\n if (result.elementOptions.mode != 'setup')\n {\n // if (!result.elementOptions.amount || result.elementOptions.amount == 0)\n // return;\n }\n\n self.mode = result.elementOptions.mode;\n self.clickResolvePayload = result.resolvePayload;\n\n stripe.initStripe(stripeJsInitParams, function (err)\n {\n if (err)\n {\n self.showError(self.maskError(err));\n return;\n }\n\n self.initElements(result.elementOptions);\n self.initExpressCheckoutElement(elementId, expressCheckoutOptions, callback);\n });\n });\n },\n\n // Accepts unlimited parameters\n log: function()\n {\n if (!this.debug)\n return;\n\n console.log.apply(console, arguments);\n },\n\n initElements: function(elementsOptions)\n {\n if (!this.elements)\n {\n this.log('initElements', elementsOptions);\n this.elements = stripe.stripeJs.elements(elementsOptions);\n }\n else\n {\n this.log('updateElements', elementsOptions);\n this.elements.update(elementsOptions);\n }\n },\n\n maskError: function(err)\n {\n var errLowercase = err.toLowerCase();\n var pos1 = errLowercase.indexOf(\"Invalid API key provided\".toLowerCase());\n var pos2 = errLowercase.indexOf(\"No API key provided\".toLowerCase());\n if (pos1 === 0 || pos2 === 0)\n return 'Invalid Stripe API key provided.';\n\n return err;\n },\n\n initExpressCheckoutElement: function(elementId, expressCheckoutOptions, callback)\n {\n if (this.expressCheckoutElement)\n {\n // ECE was already initialized, no need to update it.\n return;\n }\n\n var DOMElement = jQuery(elementId),\n self = this;\n\n try {\n if (typeof expressCheckoutOptions === 'string')\n expressCheckoutOptions = JSON.parse(expressCheckoutOptions);\n\n this.log('initExpressCheckoutElement', expressCheckoutOptions);\n this.expressCheckoutElement = this.elements.create('expressCheckout', expressCheckoutOptions);\n }\n catch (e)\n {\n console.warn(e.message);\n return;\n }\n\n if (document.getElementById(elementId.substr(1)))\n this.expressCheckoutElement.mount(elementId);\n\n this.expressCheckoutElement.on('ready', function (result)\n {\n self.log(\"on.ready\");\n if (result.availablePaymentMethods)\n {\n callback(self.expressCheckoutElement);\n }\n else\n {\n DOMElement.hide();\n }\n });\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 /**\n * Place Order\n * @param result\n * @param callback\n */\n placeOrder: function (result, location, callback) {\n var serviceUrl = urlBuilder.build('/rest/V1/stripe/payments/place_order', {}),\n payload = {\n result: result,\n location: location\n },\n self = this;\n\n return storage.post(\n serviceUrl,\n JSON.stringify(payload),\n false\n ).fail(function (xhr, textStatus, errorThrown)\n {\n try\n {\n var response = JSON.parse(xhr.responseText);\n\n var clientSecret = self.getClientSecretFromResponse(response.message);\n\n if (clientSecret)\n {\n return stripe.authenticateCustomer(clientSecret, function(err)\n {\n if (err)\n return callback(err, { message: err }, result);\n\n self.placeOrder(result, location, callback);\n });\n }\n else\n callback(response.message, response, result);\n }\n catch (e)\n {\n return self.showError(xhr.responseText);\n }\n }).done(function (response) { // @todo - this should be success, we dont want to callback() on failure\n if (typeof response === 'string')\n {\n try\n {\n response = JSON.parse(response);\n }\n catch (e)\n {\n return self.showError(response);\n }\n }\n\n callback(null, response, result);\n });\n },\n\n /**\n * Add Item to Cart\n * @param params\n * @param shipping_id\n * @param callback\n */\n addToCart: function(params, shipping_id, callback) {\n var self = this;\n this.isAddToCartPending = this.waitingForNewTotals = true;\n var addToCartPromise = new Promise(function(resolve, reject) {\n var serviceUrl = urlBuilder.build('/rest/V1/stripe/payments/addtocart', {}),\n payload = {params: params, shipping_id: shipping_id};\n\n storage.post(\n serviceUrl,\n JSON.stringify(payload),\n false\n ).fail(function(xhr, textStatus, errorThrown) {\n self.parseFailedResponse.apply(self, [xhr.responseText, callback]);\n self.waitingForNewTotals = false;\n reject(); // Reject the promise\n }).done(function(response) {\n customerData.invalidate(['cart']);\n customerData.reload(['cart'], true);\n callback(null, response);\n resolve(); // Resolve the promise\n });\n });\n\n addToCartPromise.then(function() {\n self.isAddToCartPending = false;\n\n // After the promise is resolved, run the functions in the queue\n while (self.pendingActionsQueue.length) {\n var fn = self.pendingActionsQueue.shift(); // Dequeue the first function\n fn(); // Execute the dequeued function\n }\n\n self.waitingForNewTotals = false;\n\n // Invalidate the minicart and display any errors or warnings. The wait is needed so that the server side finishes processing any cart updates\n setTimeout(function()\n {\n customerData.reload(['cart', 'messages'], true);\n }, 1000);\n });\n\n return addToCartPromise;\n },\n\n getShippingAddressFrom: function(eceShippingAddress)\n {\n if (!eceShippingAddress)\n return null;\n\n // For some countries like Japan, the ECE does not set the City, only the region\n if (eceShippingAddress.city.length == 0 && eceShippingAddress.region.length > 0)\n eceShippingAddress.city = eceShippingAddress.region;\n\n return eceShippingAddress;\n },\n\n getNewShippingRatesFor: function(address, callback) {\n var serviceUrl = urlBuilder.build('/rest/V1/stripe/payments/ece_shipping_address_changed', {}),\n payload = {newAddress: address, location: this.locationDetails.location},\n self = this;\n\n return storage.post(\n serviceUrl,\n JSON.stringify(payload),\n false\n ).fail(function (xhr, textStatus, errorThrown)\n {\n self.parseFailedResponse.apply(self, [ xhr.responseText, callback ]);\n }\n ).done(function (response) {\n self.processResponseWithECEParams(response, callback);\n });\n },\n\n parseFailedResponse: function(responseText, callback)\n {\n try\n {\n var response = JSON.parse(responseText);\n callback(response.message);\n }\n catch (e)\n {\n callback(responseText);\n }\n },\n\n /**\n * Apply Shipping and Return Totals\n * @param address\n * @param shipping_id\n * @param callback\n * @returns {*}\n */\n updateShippingRate: function(address, shipping_id, callback) {\n var serviceUrl = urlBuilder.build('/rest/V1/stripe/payments/ece_shipping_rate_changed', {}),\n payload = {address: address, shipping_id: shipping_id},\n self = this;\n\n return storage.post(\n serviceUrl,\n JSON.stringify(payload),\n false\n ).fail(function (xhr, textStatus, errorThrown)\n {\n self.parseFailedResponse.apply(self, [ xhr.responseText, callback ]);\n }\n ).done(function (response) {\n self.processResponseWithECEParams(response, callback);\n });\n },\n\n onShippingAddressChange: function(event)\n {\n this.log(\"onShippingAddressChange\");\n var executeMethod = this.onShippingAddressChangeAction.bind(this, event);\n\n if (this.isAddToCartPending) {\n this.pendingActionsQueue.push(executeMethod);\n } else {\n executeMethod();\n }\n },\n\n onShippingAddressChangeAction: function(event)\n {\n var self = this;\n this.shippingAddress = this.getShippingAddressFrom(event.address);\n this.waitingForNewTotals = true;\n this.getNewShippingRatesFor(this.shippingAddress, function (err, eceResponseParams)\n {\n if (err)\n {\n event.reject();\n self.waitingForNewTotals = false;\n return self.showError(err);\n }\n\n if (!eceResponseParams.resolvePayload.shippingRates)\n {\n event.reject();\n self.waitingForNewTotals = false;\n return;\n }\n\n self.resolveEvent(event, eceResponseParams.resolvePayload);\n self.waitingForNewTotals = false;\n });\n },\n\n resolveEvent: function(event, resolvePayload)\n {\n if (!event)\n return;\n\n var self = this;\n var total = this.getLineItemsTotal(resolvePayload.lineItems);\n\n if (resolvePayload.lineItems && !event.isClick && this.mode != \"setup\")\n {\n if (total > 0)\n {\n this.log('Updating total to ' + total + ' cents');\n var promise = self.elements.update({amount: total});\n }\n else\n {\n this.log('Will not update total to ' + total + ' cents');\n delete resolvePayload.lineItems;\n }\n\n // We need this until a promise is implemented by Stripe\n setTimeout(function() {\n self.log('Resolving event with delay ', resolvePayload);\n event.resolve(resolvePayload);\n }, 1000);\n }\n else\n {\n if (this.mode == \"setup\" && resolvePayload.lineItems)\n {\n delete resolvePayload.lineItems;\n }\n this.log('Resolving event with no delay ', resolvePayload, this.isAddToCartPending, total);\n event.resolve(resolvePayload);\n }\n },\n\n getLineItemsTotal: function(lineItems)\n {\n var total = 0;\n\n if (!lineItems || !lineItems.length)\n return total;\n\n for (var i = 0; i < lineItems.length; i++) {\n total += lineItems[i].amount;\n }\n\n return total;\n },\n\n onShippingRateChange: function(event)\n {\n this.log(\"onShippingRateChange\");\n var executeMethod = this.onShippingRateChangeAction.bind(this, event);\n\n if (this.isAddToCartPending) {\n this.pendingActionsQueue.push(executeMethod);\n } else {\n executeMethod();\n }\n },\n\n onShippingRateChangeAction: function(event)\n {\n var self = this;\n var shippingMethod = event.shippingRate.hasOwnProperty('id') ? event.shippingRate.id : null;\n this.waitingForNewTotals = true;\n this.updateShippingRate(this.shippingAddress, shippingMethod, function (err, response)\n {\n if (err) {\n event.reject();\n self.waitingForNewTotals = false;\n return self.showError(err);\n }\n\n self.resolveEvent(event, response.resolvePayload);\n self.waitingForNewTotals = false;\n });\n },\n\n startLoader: function()\n {\n if (this.isLoading)\n return;\n\n this.isLoading = true;\n jQuery('body').trigger('processStart');\n },\n\n stopLoader: function()\n {\n if (!this.isLoading)\n return;\n\n this.isLoading = false;\n jQuery('body').trigger('processStop');\n },\n\n onConfirm: function(location, confirmResult)\n {\n this.startLoader();\n\n var onPaymentMethodCreated = this.onPaymentMethodCreated.bind(this, confirmResult, location);\n var showError = this.showError.bind(this);\n\n var paymentMethodData = {\n elements: this.elements,\n params: {\n billing_details: confirmResult.billingDetails\n },\n shipping: confirmResult.shippingAddress\n };\n\n this.elements.submit().then(function()\n {\n stripe.stripeJs.createConfirmationToken(paymentMethodData).then(function(createConfirmationTokenResult)\n {\n if (createConfirmationTokenResult.error)\n {\n return showError(createConfirmationTokenResult.error.message);\n }\n else if (createConfirmationTokenResult.confirmationToken)\n {\n confirmResult.confirmationToken = createConfirmationTokenResult.confirmationToken;\n return onPaymentMethodCreated();\n }\n else\n {\n this.stopLoader();\n throw new Error('Invalid response from Stripe');\n }\n }).catch(function(error) {\n return showError(error.message);\n });\n }).catch(function(error) {\n return showError(error.message);\n });\n\n },\n\n onCancel: function()\n {\n this.log(\"onCancel\");\n this.stopLoader();\n },\n\n initCheckoutWidget: function (checkoutValidator)\n {\n var self = this;\n this.expressCheckoutElement.on('click', function(event)\n {\n if (!checkoutValidator())\n {\n event.preventDefault();\n return;\n }\n\n event.isClick = true;\n self.startLoader();\n self.resolveEvent(event, self.clickResolvePayload);\n });\n this.expressCheckoutElement.on('shippingaddresschange', this.onShippingAddressChange.bind(this));\n this.expressCheckoutElement.on('shippingratechange', this.onShippingRateChange.bind(this));\n this.expressCheckoutElement.on('confirm', this.onConfirm.bind(this, 'checkout'));\n this.expressCheckoutElement.on('cancel', this.onCancel.bind(this));\n },\n\n /**\n * Init Widget for Cart Page\n */\n initCartWidget: function ()\n {\n var self = this;\n this.expressCheckoutElement.on('click', function(event) {\n event.isClick = true;\n self.startLoader();\n self.resolveEvent(event, self.clickResolvePayload);\n });\n this.expressCheckoutElement.on('shippingaddresschange', this.onShippingAddressChange.bind(this));\n this.expressCheckoutElement.on('shippingratechange', this.onShippingRateChange.bind(this));\n this.expressCheckoutElement.on('confirm', this.onConfirm.bind(this, 'cart'));\n this.expressCheckoutElement.on('cancel', this.onCancel.bind(this));\n },\n\n /**\n * Init Widget for Mini cart\n */\n initMiniCartWidget: function ()\n {\n var self = this;\n this.expressCheckoutElement.on('click', function(event) {\n event.isClick = true;\n self.startLoader();\n self.resolveEvent(event, self.clickResolvePayload);\n });\n this.expressCheckoutElement.on('shippingaddresschange', this.onShippingAddressChange.bind(this));\n this.expressCheckoutElement.on('shippingratechange', this.onShippingRateChange.bind(this));\n this.expressCheckoutElement.on('confirm', this.onConfirm.bind(this, 'minicart'));\n this.expressCheckoutElement.on('cancel', this.onCancel.bind(this));\n },\n\n /**\n * Init Widget for Single Product Page\n */\n initProductWidget: function ()\n {\n var self = this;\n this.expressCheckoutElement.on('click', function(event) {\n event.isClick = true;\n self.startLoader();\n self.onClickAtProductPage(event);\n });\n this.expressCheckoutElement.on('shippingaddresschange', this.onShippingAddressChange.bind(this));\n this.expressCheckoutElement.on('shippingratechange', this.onShippingRateChange.bind(this));\n this.expressCheckoutElement.on('confirm', this.onConfirm.bind(this, 'product'));\n this.expressCheckoutElement.on('cancel', this.onCancel.bind(this));\n\n this.bindConfigurableProductOptions();\n },\n\n formToArrayObject: function(data) {\n var obj = {};\n for (var i = 0; i < data.length; i++) {\n obj[data[i].name] = data[i].value;\n }\n return obj;\n },\n\n onClickAtProductPage: function(event)\n {\n this.log(\"onClickAtProductPage\");\n var self = this,\n form = jQuery('#product_addtocart_form'),\n params = [];\n\n var validator = form.validation({radioCheckboxClosest: '.nested'});\n\n if (!validator.valid())\n {\n this.stopLoader();\n return;\n }\n\n // Add to Cart\n params = this.formToArrayObject(form.serializeArray());\n this.addToCart(params, this.shippingMethod, function (err)\n {\n if (err)\n {\n return self.showError(err);\n }\n });\n\n this.resolveEvent(event, this.clickResolvePayload);\n },\n\n showError: function(message)\n {\n this.stopLoader();\n\n alert({\n title: $t('Error'),\n content: message,\n actions: {\n always: function (){}\n }\n });\n },\n\n onPaymentMethodCreated: function(result, location)\n {\n var self = this;\n this.placeOrder(result, location, function (err, response, result)\n {\n if (err)\n {\n self.showError(response.message);\n }\n else if (response.hasOwnProperty('redirect'))\n {\n customerData.invalidate(['cart']);\n window.location = response.redirect;\n }\n else\n {\n self.stopLoader();\n }\n });\n },\n\n bindConfigurableProductOptions: function()\n {\n var self = this;\n var options = jQuery(\"#product-options-wrapper .configurable select.super-attribute-select\");\n\n options.each(function(index)\n {\n var onConfigurableProductChanged = self.onConfigurableProductChanged.bind(self, this);\n jQuery(this).on(\"change\", onConfigurableProductChanged);\n });\n },\n\n onConfigurableProductChanged: function(element)\n {\n var self = this;\n\n if (element.value)\n {\n var locationDetails = {\n location: 'product',\n productId: this.locationDetails.productId,\n attribute: element.value\n };\n this.initStripeExpress(\n this.mountElementId,\n this.stripeJsInitParams,\n locationDetails,\n self.expressCheckoutOptions,\n self.initProductWidget.bind(self)\n );\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 setNewPaymentMethods: function(newMethods, isDuplicate)\n {\n this.savedPaymentMethods(newMethods);\n\n if (isDuplicate)\n {\n this.showSuccessMessage($t(\"An existing payment method has been updated.\"));\n }\n else\n {\n this.showSuccessMessage($t(\"The payment method has been saved.\"));\n }\n\n this.clearFormData();\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 if (data.client_secret)\n {\n stripe.authenticateCustomer(data.client_secret, function(err)\n {\n if (err)\n {\n self.showError($t(\"Sorry, the payment method could not be saved: \" + err));\n return;\n }\n\n self.setNewPaymentMethods(newMethods, isDuplicate);\n });\n }\n else\n {\n self.setNewPaymentMethods(newMethods, isDuplicate);\n }\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 if (response && response.responseJSON && response.responseJSON.message)\n {\n self.showError(response.responseJSON.message);\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/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/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/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/payment/stripe_payments.js":"define(\n [\n 'uiComponent',\n 'Magento_Checkout/js/model/payment/renderer-list',\n 'Magento_Checkout/js/model/payment/method-group',\n 'StripeIntegration_Payments/js/helper/subscriptions'\n ],\n function (\n Component,\n rendererList,\n methodGroup,\n subscriptions\n ) {\n 'use strict';\n\n var subscriptionUpdateComponent = null;\n if (subscriptions.isSubscriptionUpdate())\n {\n subscriptionUpdateComponent = 'StripeIntegration_Payments/js/view/subscription_update/review';\n }\n\n rendererList.push(\n {\n type: 'stripe_payments',\n component: subscriptionUpdateComponent || 'StripeIntegration_Payments/js/view/payment/method-renderer/stripe_payments'\n },\n {\n type: 'stripe_payments_checkout',\n component: subscriptionUpdateComponent || 'StripeIntegration_Payments/js/view/payment/method-renderer/checkout'\n },\n {\n type: 'stripe_payments_bank_transfers',\n component: subscriptionUpdateComponent || 'StripeIntegration_Payments/js/view/payment/method-renderer/bank_transfers'\n }\n );\n\n // Add view logic here if needed\n return Component.extend({});\n }\n);\n","StripeIntegration_Payments/js/view/payment/express_checkout.js":"// This file can only be loaded at the checkout page because it injects Magento_Checkout/js/model/quote\ndefine(\n [\n 'jquery',\n 'uiComponent',\n 'StripeIntegration_Payments/js/helper/subscriptions',\n 'stripe_payments_express',\n 'Magento_Checkout/js/model/quote',\n 'Magento_Ui/js/model/messageList'\n ],\n function (\n $,\n Component,\n subscriptions,\n stripeExpress,\n quote,\n globalMessageList\n ) {\n 'use strict';\n\n return Component.extend({\n defaults: {\n // template: 'StripeIntegration_Payments/payment/express_checkout',\n stripePaymentsShowExpressCheckoutSection: false,\n isECErendered: false\n },\n\n initObservable: function ()\n {\n this._super()\n .observe([\n 'stripePaymentsShowExpressCheckoutSection',\n 'isExpressCheckoutElementSupported'\n ]);\n\n if (subscriptions.isSubscriptionUpdate())\n return this;\n\n var self = this;\n var currentTotals = quote.totals();\n\n quote.totals.subscribe(function (totals)\n {\n if (JSON.stringify(totals.total_segments) == JSON.stringify(currentTotals.total_segments))\n return;\n\n currentTotals = totals;\n\n if (!self.isECErendered)\n return;\n\n self.initECE();\n }, this);\n\n quote.paymentMethod.subscribe(function(method)\n {\n if (method != null)\n {\n $(\".payment-method.stripe-payments.mobile\").removeClass(\"_active\");\n }\n }, null, 'change');\n\n return this;\n },\n\n initECE: function()\n {\n if (!this.config().enabled)\n return;\n\n var self = this;\n var params = self.config().initParams;\n var payload = {\n location: 'checkout'\n };\n stripeExpress.initStripeExpress('#payment-request-button', params, payload, self.config().buttonConfig,\n function () {\n self.isExpressCheckoutElementSupported(true);\n self.stripePaymentsShowExpressCheckoutSection(true);\n stripeExpress.initCheckoutWidget(self.validate.bind(self));\n self.isECErendered = true;\n }\n );\n },\n\n config: function()\n {\n return window.checkoutConfig.payment.express_checkout;\n },\n\n validate: function()\n {\n var agreementsConfig = window.checkoutConfig ? window.checkoutConfig.checkoutAgreements : {},\n agreementsInputPath = '.payment-method.stripe-payments.mobile div.checkout-agreements input';\n var isValid = true;\n\n if (!agreementsConfig.isEnabled || $(agreementsInputPath).length === 0) {\n return true;\n }\n\n $(agreementsInputPath).each(function (index, element)\n {\n if (!$.validator.validateSingleElement(element, {\n errorElement: 'div',\n hideError: false\n })) {\n isValid = false;\n }\n });\n\n return isValid;\n },\n\n showError: function(message)\n {\n document.getElementById('checkout').scrollIntoView(true);\n globalMessageList.addErrorMessage({ \"message\": message });\n }\n });\n }\n);\n","StripeIntegration_Payments/js/view/payment/method-renderer/stripe_payments.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/post-cancel-order',\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 cancelLastOrderAction,\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 stripePaymentsShowExpressCheckoutSection: 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 threeDecimalCurrencies: ['BHD','JOD','KWD','OMR','TND'],\n selectedPaymentMethodCode: 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 '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.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 if (this.isExternalPaymentMethodCode(this.selectedPaymentMethodCode))\n {\n return this.selectedPaymentMethodCode;\n }\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 isWalletEnabled: function(walletName)\n {\n if (window.checkoutConfig &&\n window.checkoutConfig.payment &&\n window.checkoutConfig.payment.express_checkout &&\n window.checkoutConfig.payment.express_checkout.buttonConfig &&\n window.checkoutConfig.payment.express_checkout.buttonConfig.paymentMethods &&\n window.checkoutConfig.payment.express_checkout.buttonConfig.paymentMethods[walletName]\n )\n {\n var value = window.checkoutConfig.payment.express_checkout.buttonConfig.paymentMethods[walletName];\n return (value == \"always\" || value == \"auto\");\n }\n\n return false;\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 self.cardCvcElement.on('loaderror', self.onLoadError.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 this.paymentElement.on('loaderror', this.onLoadError.bind(this));\n }\n catch (e)\n {\n this.crash(e.message);\n }\n },\n\n onLoadError: function(event)\n {\n if (event && event.error && event.error.message)\n {\n this.permanentError(event.error.message);\n }\n else\n {\n this.crash(event);\n }\n },\n\n shouldHideRedirectBasedPaymentMethods: function()\n {\n var totals = quote.totals();\n if (!totals || !totals.total_segments || !totals.total_segments.length)\n {\n return false;\n }\n\n var targetSegments = [\"giftcardaccount\", \"customerbalance\", \"reward\"];\n\n for (var i = 0; i < totals.total_segments.length; i++)\n {\n var segment = totals.total_segments[i];\n if (targetSegments.indexOf(segment.code) >= 0 && !isNaN(segment.value) && segment.value != 0)\n {\n return true;\n }\n }\n\n return false;\n },\n\n getElementsOptions: function(filterPaymentMethods)\n {\n var options = Object.assign({}, window.checkoutConfig.payment.stripe_payments.elementOptions);\n\n if (this.shouldHideRedirectBasedPaymentMethods())\n {\n options.paymentMethodTypes = ['card'];\n\n if (this.isWalletEnabled(\"link\"))\n {\n options.paymentMethodTypes.push('link');\n }\n }\n else if (options.paymentMethodTypes)\n {\n // Case where paymentMethodOptions were passed from the server side\n }\n else\n {\n // Unset any previously set paymentMethodTypes in case a gift card was removed etc\n options.paymentMethodTypes = null;\n }\n\n if (!filterPaymentMethods && options.paymentMethodTypes)\n delete options.paymentMethodTypes;\n\n if (options.mode != \"setup\")\n {\n options.amount = this.getElementsAmount();\n }\n\n var externalPaymentMethods = this.getExternalPaymentMethods();\n if (externalPaymentMethods)\n {\n options.externalPaymentMethodTypes = externalPaymentMethods.map(function(method)\n {\n return method.code;\n });\n }\n\n return options;\n },\n\n getExternalPaymentMethods: function()\n {\n var initParams = this.getInitParams();\n\n if (initParams &&\n initParams.externalPaymentMethods &&\n initParams.externalPaymentMethods.length > 0 &&\n initParams.externalPaymentMethods[0].code &&\n initParams.externalPaymentMethods[0].redirect_url\n )\n {\n return initParams.externalPaymentMethods;\n }\n\n return null;\n },\n\n getPaymentElementOptions: function()\n {\n var options = {};\n\n var params = this.getInitParams();\n if (params)\n {\n if (params.wallets)\n options.wallets = params.wallets;\n\n if (params.layout)\n options.layout = params.layout;\n\n if (params.terms)\n options.terms = params.terms;\n }\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 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 if (event.value && event.value.type)\n {\n this.selectedPaymentMethodCode = event.value.type;\n }\n else\n {\n this.selectedPaymentMethodCode = null;\n }\n },\n\n isExternalPaymentMethodCode: function(code)\n {\n var methods = this.getExternalPaymentMethods();\n if (!methods)\n return false;\n\n for (var i = 0; i < methods.length; i++)\n {\n if (methods[i].code == code)\n return true;\n }\n\n return false;\n },\n\n getExternalPaymentMethodRedirectUrl: function(code)\n {\n var methods = this.getExternalPaymentMethods();\n if (!methods)\n return null;\n\n for (var i = 0; i < methods.length; i++)\n {\n if (methods[i].code == code)\n return methods[i].redirect_url;\n }\n\n return null;\n },\n\n getElementsAmount: function()\n {\n var totals = quote.totals();\n\n if (totals && totals.grand_total)\n {\n // If total_segments includes a grand_total, we use that instead\n if (totals.total_segments && totals.total_segments.length > 0)\n {\n for (var i = 0; i < totals.total_segments.length; i++)\n {\n var segment = totals.total_segments[i];\n if (segment.code == \"grand_total\")\n {\n return this.convertToStripeAmount(segment.value, this.getElementsCurrency());\n }\n }\n }\n\n // Othewise use the quote grand total\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 if (this.threeDecimalCurrencies.indexOf(code) >= 0)\n {\n return Math.round(amount * 100) * 10;\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 if (this.isExternalPaymentMethodCode(this.selectedPaymentMethodCode))\n {\n this.onPaymentMethodCreatedForOrderPlacement();\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 setTimeout(function(){\n // The loading mask is disabled so that the MFTF tests can continue running\n self.isLoading(false);\n }, 4000);\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 }\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\n if (this.isExternalPaymentMethodCode(this.selectedPaymentMethodCode))\n {\n window.location.href = this.getExternalPaymentMethodRedirectUrl(this.selectedPaymentMethodCode);\n return;\n }\n\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.authenticateCustomer(clientSecret, function(err)\n {\n if (err)\n return self.showError(err);\n\n self.onConfirm.bind(self)();\n });\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 .fail(function(result)\n {\n restoreQuoteAction();\n self.showError(\"The order was placed but we could not confirm if the payment was successful.\");\n console.error(result);\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 if (address.regionCode)\n stripeAddress.state = address.regionCode;\n else\n stripeAddress.state = address.region ? address.region : null;\n\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 if (result && result.error)\n {\n this.showError(result.error.message);\n\n if (this.isOrderPlaced())\n {\n cancelLastOrderAction(result.error.message);\n this.isOrderPlaced(false);\n }\n }\n else\n {\n customerData.invalidate(['cart']);\n // In the case of a 3DS, we redirect to stripe/payment/index so that the quote is de-activated\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 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 stripe.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_method': this.getPaymentMethodId()\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/payment/method-renderer/checkout.js":"/*browser:true*/\n/*global define*/\ndefine(\n [\n 'ko',\n 'jquery',\n 'Magento_Checkout/js/model/quote',\n 'Magento_Checkout/js/model/payment/additional-validators',\n 'Magento_Checkout/js/action/place-order',\n 'Magento_Checkout/js/model/full-screen-loader',\n 'Magento_Customer/js/customer-data',\n 'StripeIntegration_Payments/js/stripe',\n 'StripeIntegration_Payments/js/action/get-checkout-methods',\n 'StripeIntegration_Payments/js/action/get-checkout-session-id',\n 'Magento_Checkout/js/view/payment/default',\n 'mage/translate',\n 'stripejs',\n 'domReady!'\n ],\n function (\n ko,\n $,\n quote,\n additionalValidators,\n placeOrderAction,\n fullScreenLoader,\n customerData,\n stripe,\n getCheckoutMethods,\n getCheckoutSessionId,\n Component,\n $t\n ) {\n 'use strict';\n\n return Component.extend({\n defaults: {\n self: this,\n template: 'StripeIntegration_Payments/payment/checkout',\n code: \"stripe_checkout\",\n customRedirect: true,\n guestEmail: null,\n methodIcons: ko.observableArray([])\n },\n redirectAfterPlaceOrder: false,\n\n initObservable: function()\n {\n this._super().observe([\n 'methodIcons',\n 'permanentError'\n ]);\n\n var params = window.checkoutConfig.payment.stripe_payments.initParams;\n\n stripe.initStripe(params);\n\n var self = this;\n var currentTotals = quote.totals();\n var currentBillingAddress = quote.billingAddress();\n var currentShippingAddress = quote.shippingAddress();\n this.guestEmail = quote.guestEmail;\n\n getCheckoutMethods(quote, self.setPaymentMethods.bind(self));\n\n quote.billingAddress.subscribe(function(address)\n {\n if (!address)\n return;\n\n if (self.isAddressSame(address, currentBillingAddress))\n return;\n\n currentBillingAddress = address;\n\n getCheckoutMethods(quote, self.setPaymentMethods.bind(self));\n }, this);\n\n quote.shippingAddress.subscribe(function(address)\n {\n if (!address)\n return;\n\n if (self.isAddressSame(address, currentShippingAddress))\n return;\n\n currentShippingAddress = address;\n\n getCheckoutMethods(quote, self.setPaymentMethods.bind(self));\n }, this);\n\n quote.totals.subscribe(function (totals)\n {\n if (JSON.stringify(totals.total_segments) == JSON.stringify(currentTotals.total_segments))\n return;\n\n currentTotals = totals;\n\n getCheckoutMethods(quote, self.setPaymentMethods.bind(self));\n }, this);\n\n return this;\n },\n\n isAddressSame: function(address1, address2)\n {\n var a = this.stringifyAddress(address1);\n var b = this.stringifyAddress(address2);\n\n return a == b;\n },\n\n stringifyAddress: function(address)\n {\n if (typeof address == \"undefined\" || !address)\n return null;\n\n return JSON.stringify({\n \"countryId\": (typeof address.countryId != \"undefined\") ? address.countryId : \"\",\n \"region\": (typeof address.region != \"undefined\") ? address.region : \"\",\n \"city\": (typeof address.city != \"undefined\") ? address.city : \"\",\n \"postcode\": (typeof address.postcode != \"undefined\") ? address.postcode : \"\"\n });\n },\n\n setPaymentMethods: function(response)\n {\n var methods = [];\n\n if (typeof response == \"string\")\n response = JSON.parse(response);\n\n if (typeof response.error != \"undefined\")\n {\n this.permanentError(response.error);\n }\n\n if (typeof response.methods != \"undefined\" && response.methods.length > 0)\n methods = response.methods;\n\n var icons = window.checkoutConfig.payment.stripe_payments.icons;\n var self = this;\n\n methods.forEach(function(method)\n {\n if (self.hasPaymentMethod(icons, method))\n return;\n\n if (typeof window.checkoutConfig.payment.stripe_payments.pmIcons[method] != \"undefined\")\n {\n icons.push({\n \"code\": method,\n \"path\": window.checkoutConfig.payment.stripe_payments.pmIcons[method].icon,\n \"name\": window.checkoutConfig.payment.stripe_payments.pmIcons[method].name\n });\n }\n else if (method != \"card\")\n {\n icons.push({\n \"code\": method,\n \"path\": window.checkoutConfig.payment.stripe_payments.pmIcons.bank.icon,\n \"name\": self.methodName(method)\n });\n }\n });\n\n this.methodIcons(icons);\n },\n\n hasPaymentMethod: function(collection, code)\n {\n var exists = collection.filter(function (o)\n {\n return o.hasOwnProperty(\"code\") && o.code == code;\n }).length > 0;\n\n return exists;\n },\n\n performRedirect: function()\n {\n var self = this;\n\n getCheckoutSessionId().then(function (response)\n {\n if (response && response.length && response.indexOf(\"cs_\") === 0)\n {\n self.redirect.bind(self)(response);\n }\n else\n {\n self.showError($t('Could not redirect to Stripe Checkout.'));\n }\n },\n function (e)\n {\n self.showError($t('An error has occurred on the server. Could not redirect to Stripe Checkout.'));\n console.error(e.responseJSON.message);\n });\n },\n\n checkoutPlaceOrder: function()\n {\n var self = this;\n\n if (additionalValidators.validate())\n {\n fullScreenLoader.startLoader();\n getCheckoutSessionId().then(function (response)\n {\n if (response && response.length && response.indexOf(\"cs_\") === 0)\n {\n self.redirect.bind(self)(response);\n }\n else\n {\n self.placeOrder.bind(self)(self.performRedirect.bind(self));\n }\n },\n function (e)\n {\n self.showError($t('An error has occurred on the server. Could not redirect to Stripe Checkout.'));\n console.error(e.responseJSON.message);\n });\n }\n\n return false;\n },\n\n placeOrder: function()\n {\n var self = this;\n\n placeOrderAction(self.getData(), self.messageContainer)\n .then(\n this.performRedirect.bind(this),\n function (e) {\n self.showError($t('An error has occurred. Could not redirect to Stripe Checkout.'));\n console.error(e.responseJSON.message);\n }\n );\n\n return false;\n },\n\n redirectToURL: function(url)\n {\n try\n {\n customerData.invalidate(['cart']);\n $.mage.redirect(url);\n }\n catch (e)\n {\n console.error(e);\n }\n },\n\n redirect: function(sessionId)\n {\n try\n {\n customerData.invalidate(['cart']);\n stripe.stripeJs.redirectToCheckout({ sessionId: sessionId }, this.onRedirectFailure.bind(this));\n }\n catch (e)\n {\n fullScreenLoader.stopLoader();\n console.error(e);\n }\n },\n\n onRedirectFailure: function(result)\n {\n if (result.error)\n {\n this.showError(result.error.message);\n }\n else\n {\n this.showError($(\"A redirect error has occurred.\"));\n console.error(result);\n }\n },\n\n methodName: function(code)\n {\n if (typeof code == 'undefined')\n return '';\n\n return code.charAt(0).toUpperCase() + Array.from(code).splice(1).join('');\n },\n\n showError: function(message)\n {\n fullScreenLoader.stopLoader();\n document.getElementById('stripe-checkout-actions-toolbar').scrollIntoView(true);\n this.messageContainer.addErrorMessage({ \"message\": message });\n },\n });\n }\n);\n","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 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 stripe.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_method': this.getPaymentMethodId()\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/payment/method-renderer/bank_transfers.js":"define(\n [\n 'Magento_Checkout/js/view/payment/default',\n 'Magento_Checkout/js/model/quote',\n 'StripeIntegration_Payments/js/action/post-restore-quote',\n 'StripeIntegration_Payments/js/action/get-requires-action',\n 'StripeIntegration_Payments/js/stripe',\n 'mage/translate',\n 'Magento_Checkout/js/action/place-order',\n 'Magento_Checkout/js/model/payment/additional-validators',\n 'Magento_Checkout/js/action/redirect-on-success',\n 'Magento_CheckoutAgreements/js/model/agreement-validator',\n 'Magento_Customer/js/customer-data',\n ],\n function (\n Component,\n quote,\n restoreQuoteAction,\n getRequiresAction,\n stripe,\n $t,\n placeOrderAction,\n additionalValidators,\n redirectOnSuccessAction,\n agreementValidator,\n customerData\n ) {\n 'use strict';\n\n return Component.extend({\n externalRedirectUrl: null,\n defaults: {\n template: 'StripeIntegration_Payments/payment/bank_transfers'\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 'isLoading',\n 'stripePaymentsError',\n 'permanentError',\n 'isInitializing',\n 'isInitialized',\n 'useQuoteBillingAddress',\n 'paymentElementPaymentMethod',\n ]);\n\n var self = this;\n\n this.isInitializing(true);\n this.isInitialized(false);\n this.useQuoteBillingAddress(false);\n\n quote.paymentMethod.subscribe(function (method)\n {\n if (method && 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\n getPaymentMethodId: function()\n {\n var paymentMethod = this.paymentElementPaymentMethod();\n if (paymentMethod && paymentMethod.id)\n {\n return paymentMethod.id;\n }\n\n return null;\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 getInitParams: function()\n {\n return window.checkoutConfig.payment.stripe_payments_bank_transfers.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.initPaymentForm();\n });\n },\n\n onContainerRendered: function()\n {\n this.onPaymentElementContainerRendered();\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-bank-transfers') === null)\n return this.crash(\"Cannot initialize Payment Element on a DOM that does not contain a div.stripe-payment-element-bank-transfers.\");\n\n if (!stripe.stripeJs)\n return this.crash(\"Stripe.js could not be initialized.\");\n\n try\n {\n this.elements = stripe.stripeJs.elements(this.getElementsOptions());\n this.paymentElement = this.elements.create('payment', this.getPaymentElementOptions());\n this.paymentElement.mount('#stripe-payment-element-bank-transfers');\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()\n {\n var options = window.checkoutConfig.payment.stripe_payments_bank_transfers.elementOptions;\n\n options.amount = this.getElementsAmount();\n options.currency = this.getElementsCurrency();\n\n return options;\n },\n\n getPaymentElementOptions: function()\n {\n var options = {};\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 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 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\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 this.createPaymentMethod(this.onPaymentMethodCreatedForOrderPlacement.bind(this));\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 onPaymentMethodCreatedForOrderPlacement: function(paymentMethod)\n {\n var placeNewOrder = this.placeNewOrder.bind(this);\n var self = this;\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 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 onOrderPlaced: function(result, outcome, response)\n {\n this.isLoading(true);\n var self = 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 return (['processing', 'requires_capture', 'succeeded'].indexOf(stripeObject.status) >= 0);\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 redirectOnSuccessAction.execute();\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 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 stripe.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 agreementValidator.validate() && additionalValidators.validate();\n },\n\n getCode: function()\n {\n return 'stripe_payments_bank_transfers';\n },\n\n getData: function()\n {\n var data = {\n 'method': this.item.method,\n 'additional_data': {\n 'payment_method': this.getPaymentMethodId(),\n }\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/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).on(\"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).trigger(\"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).trigger(\"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_method': this.token()\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/action/list-payment-methods.js":"define(\n [\n 'mage/url',\n 'mage/storage'\n ],\n function (\n urlBuilder,\n storage\n ) {\n 'use strict';\n return function (callback)\n {\n var serviceUrl = urlBuilder.build('rest/V1/stripe/payments/list_payment_methods');\n\n return storage.get(serviceUrl).always(callback);\n };\n }\n);\n","StripeIntegration_Payments/js/action/add-payment-method.js":"define(\n [\n 'mage/url',\n 'mage/storage'\n ],\n function (\n urlBuilder,\n storage\n ) {\n 'use strict';\n return function (paymentMethodId, callback)\n {\n var serviceUrl = urlBuilder.build('rest/V1/stripe/payments/add_payment_method');\n\n var payload = {\n paymentMethodId: paymentMethodId\n };\n\n return storage.post(serviceUrl, JSON.stringify(payload)).always(callback);\n };\n }\n);\n","StripeIntegration_Payments/js/action/delete-payment-method.js":"define(\n [\n 'mage/url',\n 'mage/storage'\n ],\n function (\n urlBuilder,\n storage\n ) {\n 'use strict';\n return function (paymentMethodId, fingerprint, callback)\n {\n var serviceUrl = urlBuilder.build('rest/V1/stripe/payments/delete_payment_method');\n\n var payload = {\n paymentMethodId: paymentMethodId\n };\n\n if (fingerprint)\n {\n payload.fingerprint = fingerprint;\n }\n\n return storage.post(serviceUrl, JSON.stringify(payload)).always(callback);\n };\n }\n);\n","StripeIntegration_Payments/js/action/post-cancel-order.js":"define(\n [\n 'Magento_Checkout/js/model/url-builder',\n 'Magento_Customer/js/customer-data',\n 'mage/storage'\n ],\n function (urlBuilder, customerData, storage) {\n 'use strict';\n\n var promise = null; // If this is set, the promise is not resolved\n\n return function (errorMessage, callback)\n {\n var serviceUrl = urlBuilder.createUrl('/stripe/payments/cancel_last_order', {});\n\n var payload = {\n errorMessage: errorMessage\n };\n\n customerData.invalidate(['cart']);\n\n if (!promise)\n promise = storage.post(serviceUrl, JSON.stringify(payload));\n else\n return promise.always(callback); // Stack multiple callbacks onto the promise\n\n return promise.always(function(result, outcome, response)\n {\n promise = null; // Marks it as resolved\n callback(result, outcome, response);\n });\n };\n }\n);\n","StripeIntegration_Payments/js/action/get-upcoming-invoice.js":"define(\n [\n 'Magento_Checkout/js/model/url-builder',\n 'mage/storage'\n ],\n function (urlBuilder, storage) {\n 'use strict';\n\n var promise = null; // If this is set, the promise is not resolved\n\n return function (callback)\n {\n var serviceUrl = urlBuilder.createUrl('/stripe/payments/get_upcoming_invoice', {});\n\n if (!promise)\n promise = storage.get(serviceUrl);\n else\n return promise.always(callback); // Stack multiple callbacks onto the promise\n\n return promise.always(function(result, outcome, response)\n {\n promise = null; // Marks it as resolved\n callback(result, outcome, response);\n });\n };\n }\n);\n","StripeIntegration_Payments/js/action/get-requires-action.js":"define(\n [\n 'Magento_Checkout/js/model/url-builder',\n 'Magento_Customer/js/customer-data',\n 'mage/storage'\n ],\n function (urlBuilder, customerData, storage) {\n 'use strict';\n\n var promise = null; // If this is set, the promise is not resolved\n\n return function (callback)\n {\n var serviceUrl = urlBuilder.createUrl('/stripe/payments/get_requires_action', {});\n\n customerData.invalidate(['cart']);\n\n if (!promise)\n promise = storage.get(serviceUrl);\n else\n return promise.always(callback); // Stack multiple callbacks onto the promise\n\n return promise.always(function(result, outcome, response)\n {\n promise = null; // Marks it as resolved\n callback(result, outcome, response);\n });\n };\n }\n);\n","StripeIntegration_Payments/js/action/finalize-multishipping-order.js":"define(\n [\n 'jquery',\n 'Magento_Checkout/js/model/url-builder',\n 'mage/storage',\n 'Magento_Customer/js/customer-data',\n 'Magento_Ui/js/modal/alert'\n ],\n function ($, urlBuilder, storage, customerData, alert) {\n 'use strict';\n\n var showError = function(message, e)\n {\n alert( { content: message });\n\n if (typeof e != \"undefined\")\n console.error(e);\n };\n\n return function (error)\n {\n customerData.invalidate(['cart']);\n\n var serviceUrl = urlBuilder.createUrl('/stripe/payments/finalize_multishipping_order', {});\n var payload = { error: error };\n\n return storage.post(serviceUrl, JSON.stringify(payload))\n .then(function(result, b, c)\n {\n var response = null;\n\n try\n {\n response = JSON.parse(result);\n }\n catch (e)\n {\n return showError(\"Sorry, a server side error has occurred.\", e);\n }\n\n if (response.error)\n return showError(response.error, response.error);\n\n if (response.redirect)\n return $.mage.redirect(response.redirect);\n\n return showError(response, response);\n })\n .fail(function(result)\n {\n return showError(\"Sorry, a server side error has occurred.\", result);\n });\n };\n }\n);\n","StripeIntegration_Payments/js/action/post-update-cart.js":"define(\n [\n 'Magento_Checkout/js/model/url-builder',\n 'mage/storage',\n 'Magento_Customer/js/customer-data'\n ],\n function (urlBuilder, storage, customerData) {\n 'use strict';\n return function (data, callback)\n {\n var serviceUrl = urlBuilder.createUrl('/stripe/payments/update_cart', {});\n\n // This API call may inactivate the customer cart\n customerData.invalidate(['cart']);\n\n if (data)\n {\n return storage.post(\n serviceUrl,\n JSON.stringify({ data: data })\n ).always(callback);\n }\n else\n {\n\n return storage.post(serviceUrl).always(callback);\n }\n };\n }\n);\n","StripeIntegration_Payments/js/action/post-restore-quote.js":"define(\n [\n 'Magento_Checkout/js/model/url-builder',\n 'mage/storage',\n 'Magento_Customer/js/customer-data',\n 'Magento_Checkout/js/model/quote'\n ],\n function (\n urlBuilder,\n storage,\n customerData,\n quote\n ) {\n 'use strict';\n return function (callback)\n {\n var serviceUrl = urlBuilder.createUrl('/stripe/payments/restore_quote', {});\n\n customerData.invalidate(['cart']);\n\n return storage.post(serviceUrl).always(callback);\n };\n }\n);\n","StripeIntegration_Payments/js/action/get-checkout-session-id.js":"define(\n [\n 'Magento_Checkout/js/model/url-builder',\n 'mage/storage'\n ],\n function (urlBuilder, storage) {\n 'use strict';\n\n return function ()\n {\n var serviceUrl = urlBuilder.createUrl('/stripe/payments/get_checkout_session_id', {});\n\n return storage.get(serviceUrl);\n };\n }\n);\n","StripeIntegration_Payments/js/action/get-payment-url.js":"define(\n [\n 'Magento_Checkout/js/model/url-builder',\n 'mage/storage',\n 'Magento_Checkout/js/model/error-processor',\n 'Magento_Checkout/js/model/full-screen-loader'\n ],\n function (urlBuilder, storage, errorProcessor, fullScreenLoader) {\n 'use strict';\n return function (messageContainer) {\n var serviceUrl = urlBuilder.createUrl('/stripe/payments/redirect_url', {});\n\n fullScreenLoader.startLoader();\n\n return storage.get(\n serviceUrl\n ).fail(\n function (response) {\n errorProcessor.process(response, messageContainer);\n fullScreenLoader.stopLoader();\n }\n );\n };\n }\n);\n","StripeIntegration_Payments/js/action/get-trialing-subscriptions.js":"define(\n [\n 'Magento_Checkout/js/model/url-builder',\n 'mage/storage',\n 'Magento_Checkout/js/model/error-processor',\n 'Magento_Checkout/js/model/full-screen-loader',\n 'Magento_Checkout/js/model/quote'\n ],\n function (urlBuilder, storage, errorProcessor, fullScreenLoader, quote) {\n 'use strict';\n return function (quote)\n {\n var serviceUrl = urlBuilder.createUrl('/stripe/payments/get_trialing_subscriptions', {});\n\n var payload = {\n billingAddress: quote.billingAddress()\n };\n\n if (quote.shippingAddress())\n payload.shippingAddress = quote.shippingAddress();\n\n if (quote.shippingMethod())\n payload.shippingMethod = quote.shippingMethod();\n\n var totals = quote.totals();\n if (typeof totals.coupon_code != \"undefined\" && totals.coupon_code && totals.coupon_code.length > 0)\n payload.couponCode = totals.coupon_code;\n\n return storage.post(serviceUrl, JSON.stringify(payload));\n };\n }\n);\n","StripeIntegration_Payments/js/action/get-checkout-methods.js":"define(\n [\n 'Magento_Checkout/js/model/url-builder',\n 'mage/storage',\n 'Magento_Checkout/js/model/error-processor',\n 'Magento_Checkout/js/model/full-screen-loader',\n 'Magento_Checkout/js/model/quote'\n ],\n function (urlBuilder, storage, errorProcessor, fullScreenLoader, quote) {\n 'use strict';\n\n var timesRequested = 0;\n\n return function (quote, onDoneCallback)\n {\n var serviceUrl = urlBuilder.createUrl('/stripe/payments/get_checkout_payment_methods', {});\n\n var payload = {\n billingAddress: quote.billingAddress()\n };\n\n if (quote.shippingAddress())\n payload.shippingAddress = quote.shippingAddress();\n\n if (quote.shippingMethod())\n payload.shippingMethod = quote.shippingMethod();\n\n var totals = quote.totals();\n if (typeof totals.coupon_code != \"undefined\" && totals.coupon_code && totals.coupon_code.length > 0)\n payload.couponCode = totals.coupon_code;\n\n try\n {\n if (!payload.billingAddress.countryId.length)\n return;\n\n if (!quote.isVirtual())\n {\n if (!payload.shippingAddress.countryId.length)\n return;\n }\n\n if (timesRequested > 0)\n return;\n }\n catch (e)\n {\n return;\n }\n\n timesRequested++;\n return storage.post(serviceUrl, JSON.stringify(payload)).done(onDoneCallback);\n };\n }\n);\n","StripeIntegration_Payments/js/action/place-multishipping-order.js":"define(\n [\n 'jquery',\n 'Magento_Checkout/js/model/url-builder',\n 'mage/storage',\n 'Magento_Customer/js/customer-data',\n 'Magento_Ui/js/modal/alert'\n ],\n function ($, urlBuilder, storage, customerData, alert) {\n 'use strict';\n\n var showError = function(message, e)\n {\n alert( { content: message });\n\n if (typeof e != \"undefined\")\n console.error(e);\n };\n\n return function (callback, onAuthenticationRequired)\n {\n customerData.invalidate(['cart']);\n\n var serviceUrl = urlBuilder.createUrl('/stripe/payments/place_multishipping_order', {});\n\n return storage.post(serviceUrl)\n .then(function(result, b, c)\n {\n var response = null;\n\n try\n {\n response = JSON.parse(result);\n }\n catch (e)\n {\n return showError(\"Sorry, a server side error has occurred.\", e);\n }\n\n if (response.error)\n return showError(response.error, response.error);\n\n if (response.redirect)\n return $.mage.redirect(response.redirect);\n\n if (response.authenticate)\n return onAuthenticationRequired(response.authenticate);\n\n return showError(response, response);\n })\n .fail(function(result)\n {\n return showError(\"Sorry, a server side error has occurred.\", result);\n })\n .always(callback);\n };\n }\n);\n","StripeIntegration_Payments/js/mixins/messages-mixin.js":"define([], function() {\n 'use strict';\n return function(target) {\n return target.extend({\n isVisible: function () {\n var msgs = this.messageContainer.errorMessages();\n for (var i = 0; i < msgs.length; i++)\n {\n if (typeof msgs[i] != 'string')\n continue;\n\n if (msgs[i].indexOf(\"Authentication Required: \") >= 0)\n return false;\n }\n return this.isHidden(this.messageContainer.hasMessages());\n }\n });\n };\n});\n","StripeIntegration_Payments/js/mixins/checkout/payment/list.js":"define([\n 'StripeIntegration_Payments/js/helper/subscriptions',\n 'mage/translate',\n],\nfunction(\n subscriptions,\n $t\n) {\n 'use strict';\n return function(target) {\n return target.extend({\n /**\n * Returns payment group title\n *\n * @param {Object} group\n * @returns {String}\n */\n getGroupTitle: function (group)\n {\n if (subscriptions.isSubscriptionUpdate())\n return $t(\"Subscription Update Review\");\n\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});\n","StripeIntegration_Payments/js/mixins/checkout/summary/grand_total.js":"define([\n 'Magento_Checkout/js/model/quote',\n 'Magento_Checkout/js/model/totals',\n 'Magento_Catalog/js/price-utils',\n 'StripeIntegration_Payments/js/view/checkout/trialing_subscriptions',\n 'StripeIntegration_Payments/js/view/checkout/summary/prorations'\n], function (\n quote,\n totals,\n priceUtils,\n trialingSubscriptions,\n prorations\n) {\n 'use strict';\n\n return function (grandTotal)\n {\n return grandTotal.extend(\n {\n totals: quote.getTotals(),\n\n getValue: function()\n {\n var price = 0;\n\n if (totals && totals.getSegment('grand_total'))\n {\n price = parseFloat(totals.getSegment('grand_total').value);\n price += trialingSubscriptions().getPureValue();\n price += prorations().getPureValue();\n }\n\n return grandTotal().getFormattedPrice(price);\n },\n\n getBaseValue: function () {\n var price = 0;\n\n if (totals && totals.getSegment('base_grand_total'))\n {\n price = parseFloat(totals.getSegment('base_grand_total').value);\n price += trialingSubscriptions().getBasePureValue();\n price += prorations().getBasePureValue();\n }\n\n return priceUtils.formatPrice(price, quote.getBasePriceFormat());\n },\n\n getTaxAmount: function()\n {\n if (totals.getSegment('tax_amount'))\n {\n // Tax exclusive settings\n return parseFloat(totals.getSegment('tax_amount').value);\n }\n\n if (totals.getSegment('tax'))\n {\n // Tax inclusive settings\n return parseFloat(totals.getSegment('tax').value);\n }\n\n // Core implementation should handle both cases\n var total = this.totals();\n if (total && total.tax_amount) {\n return total.tax_amount;\n }\n\n return 0;\n },\n\n getGrandTotalExclTax: function()\n {\n var price = 0;\n\n if (totals.getSegment('grand_total'))\n {\n price = parseFloat(totals.getSegment('grand_total').value);\n price -= parseFloat(this.getTaxAmount());\n price += trialingSubscriptions().getTaxAmount();\n price += trialingSubscriptions().getPureValue();\n price += prorations().getPureValue();\n }\n\n return grandTotal().getFormattedPrice(price);\n }\n });\n };\n});\n","StripeIntegration_Payments/js/helper/subscriptions.js":"define(\n [\n 'ko'\n ],\n function (\n ko\n ) {\n 'use strict';\n\n return {\n isSubscriptionUpdate: function()\n {\n return !!(window.checkoutConfig &&\n window.checkoutConfig.payment &&\n window.checkoutConfig.payment.stripe_payments &&\n window.checkoutConfig.payment.stripe_payments.subscriptionUpdateDetails);\n },\n\n getConfig: function(key)\n {\n var config = null;\n\n if (window.checkoutConfig && window.checkoutConfig.payment && window.checkoutConfig.payment.stripe_payments)\n {\n config = window.checkoutConfig.payment.stripe_payments;\n }\n\n if (!config || !config.subscriptionUpdateDetails)\n {\n return null;\n }\n\n if (!config.subscriptionUpdateDetails[key])\n {\n return \"--\";\n }\n\n return config.subscriptionUpdateDetails[key];\n },\n\n getSuccessUrl: function()\n {\n return this.getConfig(\"success_url\");\n },\n\n getCancelUrl: function()\n {\n return this.getConfig(\"cancel_url\");\n },\n\n displaySidebar: function()\n {\n return this.isSubscriptionUpdate();\n // && !window.checkoutConfig.payment.stripe_payments.subscriptionUpdateDetails.is_virtual\n // && window.location.href.indexOf('#payment') < 0;\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","Webkul_PrivateShop/js/view/wishlist-view.js":"/**\n * Webkul Software\n *\n * @category Webkul\n * @package Webkul_PrivateShop\n * @author Webkul Software Private Limited\n * @copyright Webkul Software Private Limited (https://webkul.com)\n * @license https://store.webkul.com/license.html\n */\ndefine(\n ['jquery'],\n function ($) {\n $.widget(\n 'webkul.privateProductLabel',\n {\n _create: function () {\n var self = this;\n $(\".price-box\").each(function () {\n var id= $(this).attr('data-product-id');\n var self1 = this;\n $.ajax({\n url: self.options.labetData.url,\n type: 'POST',\n data: { id : id},\n dataType: 'json',\n success: function (response) {\n if (response == 'true') {\n $($(self1).parent().find(\"a\").find(\"span\").find(\"span\"))\n .append(self.options.labetData.html);\n $($(self1).parent().parent('.product-item-info').find(\"a\").find(\"span\").find(\"span\"))\n .append(self.options.labetData.html);\n $($(self1).parent().parent().find(\"div.product-item-img\").find(\"a.product-image\"))\n .prepend(self.options.labetData.html);\n $($(self1).parent().parent().find(\"div.product-item-photo\"))\n .prepend(self.options.labetData.html);\n } \n }\n })\n });\n }\n }\n );\n return $.webkul.privateProductLabel;\n }\n);","Webkul_PrivateShop/js/view/category-view.js":"/**\n * Webkul Software\n *\n * @category Webkul\n * @package Webkul_PrivateShop\n * @author Webkul Software Private Limited\n * @copyright Webkul Software Private Limited (https://webkul.com)\n * @license https://store.webkul.com/license.html\n */\ndefine(\n ['jquery'],\n function ($) {\n $.widget(\n 'webkul.privateProductLabel',\n {\n _create: function () {\n var self = this;\n $(\".private-label-available\").each(function () {\n if ($(this).val() == 1) {\n $($(this).parent().find(\"a\").find(\"span\").find(\"span\"))\n .append(self.options.labetData.html);\n $($(this).parent().parent('.product-item-info').find(\"a\").find(\"span\").find(\"span\"))\n .append(self.options.labetData.html);\n\n $($(this).parent().parent().find(\"div.product-item-img\").find(\"a.product-image\"))\n .prepend(self.options.labetData.html);\n\n $($(this).parent().parent().find(\"div.product-item-photo\"))\n .prepend(self.options.labetData.html);\n }\n });\n }\n }\n );\n return $.webkul.privateProductLabel;\n }\n);","Webkul_PrivateShop/js/view/product-view.js":"/**\n * Webkul Software\n *\n * @category Webkul\n * @package Webkul_PrivateShop\n * @author Webkul Software Private Limited\n * @copyright Webkul Software Private Limited (https://webkul.com)\n * @license https://store.webkul.com/license.html\n */\ndefine(\n [\n 'jquery'\n ],\n function ($) {\n $.widget(\n 'private.viewProduct',\n {\n _create: function () {\n var self = this;\n $(\".product.media\").prepend(self.options.labetData.html);\n }\n }\n );\n return $.private.viewProduct;\n }\n);","Magento_Captcha/js/captcha.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 /**\n * @api\n */\n $.widget('mage.captcha', {\n options: {\n refreshClass: 'refreshing',\n reloadSelector: '.captcha-reload',\n imageSelector: '.captcha-img',\n imageLoader: ''\n },\n\n /**\n * Method binds click event to reload image\n * @private\n */\n _create: function () {\n this.element.on('click', this.options.reloadSelector, $.proxy(this.refresh, this));\n },\n\n /**\n * Method triggers an AJAX request to refresh the CAPTCHA image\n */\n refresh: function () {\n var imageLoader = this.options.imageLoader;\n\n if (imageLoader) {\n this.element.find(this.options.imageSelector).attr('src', imageLoader);\n }\n this.element.addClass(this.options.refreshClass);\n\n $.ajax({\n url: this.options.url,\n type: 'post',\n dataType: 'json',\n context: this,\n data: {\n 'formId': this.options.type\n },\n\n /**\n * @param {Object} response\n */\n success: function (response) {\n if (response.imgSrc) {\n this.element.find(this.options.imageSelector).attr('src', response.imgSrc);\n }\n },\n\n /** Complete callback. */\n complete: function () {\n this.element.removeClass(this.options.refreshClass);\n }\n });\n }\n });\n\n return $.mage.captcha;\n});\n","Magento_Captcha/js/view/checkout/loginCaptcha.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 'Magento_Customer/js/action/login',\n 'underscore'\n],\nfunction (defaultCaptcha, captchaList, loginAction, _) {\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\n if (currentCaptcha != null) {\n currentCaptcha.setIsVisible(true);\n this.setCurrentCaptcha(currentCaptcha);\n\n loginAction.registerLoginCallback(function (loginData) {\n if (loginData['captcha_form_id'] &&\n loginData['captcha_form_id'] === self.formId &&\n self.isRequired()\n ) {\n _.defer(self.refresh.bind(self));\n }\n });\n }\n }\n });\n});\n","Magento_Captcha/js/view/checkout/defaultCaptcha.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_Captcha/js/model/captcha',\n 'Magento_Captcha/js/model/captchaList',\n 'Magento_Customer/js/customer-data',\n 'underscore'\n], function ($, Component, Captcha, captchaList, customerData, _) {\n 'use strict';\n\n var captchaConfig;\n\n return Component.extend({\n defaults: {\n template: 'Magento_Captcha/checkout/captcha'\n },\n dataScope: 'global',\n currentCaptcha: null,\n subscribedFormIds: [],\n\n /**\n * @return {*}\n */\n captchaValue: function () {\n return this.currentCaptcha.getCaptchaValue();\n },\n\n /** @inheritdoc */\n initialize: function () {\n this._super();\n\n if (window[this.configSource] && window[this.configSource].captcha) {\n captchaConfig = window[this.configSource].captcha;\n $.each(captchaConfig, function (formId, captchaData) {\n var captcha;\n\n captchaData.formId = formId;\n captcha = Captcha(captchaData);\n this.checkCustomerData(formId, customerData.get('captcha')(), captcha);\n this.subscribeCustomerData(formId, captcha);\n captchaList.add(captcha);\n }.bind(this));\n }\n },\n\n /**\n * Check customer data for captcha configuration.\n *\n * @param {String} formId\n * @param {Object} captchaData\n * @param {Object} captcha\n */\n checkCustomerData: function (formId, captchaData, captcha) {\n if (!_.isEmpty(captchaData) &&\n !_.isEmpty(captchaData[formId]) &&\n captchaData[formId].timestamp > captcha.timestamp\n ) {\n if (!captcha.isRequired() && captchaData[formId].isRequired) {\n captcha.refresh();\n }\n captcha.isRequired(captchaData[formId].isRequired);\n captcha.timestamp = captchaData[formId].timestamp;\n }\n },\n\n /**\n * Subscribe for customer data updates.\n *\n * @param {String} formId\n * @param {Object} captcha\n */\n subscribeCustomerData: function (formId, captcha) {\n if (this.subscribedFormIds.includes(formId) === false) {\n this.subscribedFormIds.push(formId);\n customerData.get('captcha').subscribe(function (captchaData) {\n this.checkCustomerData(formId, captchaData, captcha);\n }.bind(this));\n }\n },\n\n /**\n * @return {Boolean}\n */\n getIsLoading: function () {\n return this.currentCaptcha !== null ? this.currentCaptcha.isLoading : false;\n },\n\n /**\n * @return {null|Object}\n */\n getCurrentCaptcha: function () {\n return this.currentCaptcha;\n },\n\n /**\n * @param {Object} captcha\n */\n setCurrentCaptcha: function (captcha) {\n this.currentCaptcha = captcha;\n },\n\n /**\n * @return {String|null}\n */\n getFormId: function () {\n return this.currentCaptcha !== null ? this.currentCaptcha.getFormId() : null;\n },\n\n /**\n * @return {Boolean}\n */\n getIsVisible: function () {\n return this.currentCaptcha !== null ? this.currentCaptcha.getIsVisible() : false;\n },\n\n /**\n * @param {Boolean} flag\n */\n setIsVisible: function (flag) {\n this.currentCaptcha.setIsVisible(flag);\n },\n\n /**\n * @return {Boolean}\n */\n isRequired: function () {\n return this.currentCaptcha !== null ? this.currentCaptcha.getIsRequired() : false;\n },\n\n /**\n * Set isRequired on current captcha model.\n *\n * @param {Boolean} flag\n */\n setIsRequired: function (flag) {\n this.currentCaptcha.setIsRequired(flag);\n },\n\n /**\n * @return {Boolean}\n */\n isCaseSensitive: function () {\n return this.currentCaptcha !== null ? this.currentCaptcha.getIsCaseSensitive() : false;\n },\n\n /**\n * @return {String|Number|null}\n */\n imageHeight: function () {\n return this.currentCaptcha !== null ? this.currentCaptcha.getImageHeight() : null;\n },\n\n /**\n * @return {String|null}\n */\n getImageSource: function () {\n return this.currentCaptcha !== null ? this.currentCaptcha.getImageSource() : null;\n },\n\n /**\n * Refresh captcha.\n */\n refresh: function () {\n this.currentCaptcha.refresh();\n }\n });\n});\n","Magento_Captcha/js/action/refresh.js":"/**\n * Copyright \u00a9 Magento, Inc. All rights reserved.\n * See COPYING.txt for license details.\n */\n\ndefine([\n 'jquery', 'mage/url'\n], function ($, urlBuilder) {\n 'use strict';\n\n return function (refreshUrl, formId, imageSource) {\n return $.ajax({\n url: urlBuilder.build(refreshUrl),\n type: 'POST',\n data: JSON.stringify({\n 'formId': formId\n }),\n global: false,\n contentType: 'application/json'\n }).done(\n function (response) {\n if (response.imgSrc) {\n imageSource(response.imgSrc);\n }\n }\n );\n };\n});\n","Magento_Captcha/js/model/captchaList.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 var captchaList = [];\n\n return {\n /**\n * @param {Object} captcha\n */\n add: function (captcha) {\n captchaList.push(captcha);\n },\n\n /**\n * @param {String} formId\n * @return {Object}\n */\n getCaptchaByFormId: function (formId) {\n var captcha = null;\n\n $.each(captchaList, function (key, item) {\n if (formId === item.formId) {\n captcha = item;\n\n return false;\n }\n });\n\n return captcha;\n },\n\n /**\n * @return {Array}\n */\n getCaptchaList: function () {\n return captchaList;\n }\n };\n});\n","Magento_Captcha/js/model/captcha.js":"/**\n * Copyright \u00a9 Magento, Inc. All rights reserved.\n * See COPYING.txt for license details.\n */\n\ndefine([\n 'jquery',\n 'ko',\n 'Magento_Captcha/js/action/refresh'\n], function ($, ko, refreshAction) {\n 'use strict';\n\n return function (captchaData) {\n return {\n formId: captchaData.formId,\n imageSource: ko.observable(captchaData.imageSrc),\n visibility: ko.observable(false),\n captchaValue: ko.observable(null),\n isRequired: ko.observable(captchaData.isRequired),\n isCaseSensitive: captchaData.isCaseSensitive,\n imageHeight: captchaData.imageHeight,\n refreshUrl: captchaData.refreshUrl,\n isLoading: ko.observable(false),\n timestamp: null,\n\n /**\n * @return {String}\n */\n getFormId: function () {\n return this.formId;\n },\n\n /**\n * @param {String} formId\n */\n setFormId: function (formId) {\n this.formId = formId;\n },\n\n /**\n * @return {Boolean}\n */\n getIsVisible: function () {\n return this.visibility();\n },\n\n /**\n * @param {Boolean} flag\n */\n setIsVisible: function (flag) {\n this.visibility(flag);\n },\n\n /**\n * @return {Boolean}\n */\n getIsRequired: function () {\n return this.isRequired();\n },\n\n /**\n * @param {Boolean} flag\n */\n setIsRequired: function (flag) {\n this.isRequired(flag);\n },\n\n /**\n * @return {Boolean}\n */\n getIsCaseSensitive: function () {\n return this.isCaseSensitive;\n },\n\n /**\n * @param {Boolean} flag\n */\n setIsCaseSensitive: function (flag) {\n this.isCaseSensitive = flag;\n },\n\n /**\n * @return {String|Number}\n */\n getImageHeight: function () {\n return this.imageHeight;\n },\n\n /**\n * @param {String|Number}height\n */\n setImageHeight: function (height) {\n this.imageHeight = height;\n },\n\n /**\n * @return {String}\n */\n getImageSource: function () {\n return this.imageSource;\n },\n\n /**\n * @param {String} imageSource\n */\n setImageSource: function (imageSource) {\n this.imageSource(imageSource);\n },\n\n /**\n * @return {String}\n */\n getRefreshUrl: function () {\n return this.refreshUrl;\n },\n\n /**\n * @param {String} url\n */\n setRefreshUrl: function (url) {\n this.refreshUrl = url;\n },\n\n /**\n * @return {*}\n */\n getCaptchaValue: function () {\n return this.captchaValue;\n },\n\n /**\n * @param {*} value\n */\n setCaptchaValue: function (value) {\n this.captchaValue(value);\n },\n\n /**\n * Refresh captcha.\n */\n refresh: function () {\n var refresh,\n self = this;\n\n this.isLoading(true);\n\n refresh = refreshAction(this.getRefreshUrl(), this.getFormId(), this.getImageSource());\n $.when(refresh).done(function () {\n self.isLoading(false);\n });\n }\n };\n };\n});\n","Magento_Sales/js/gift-message.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.giftMessage', {\n options: {\n rowPrefix: '#order-item-row-', // Selector prefix for item's row in the table.\n linkPrefix: '#order-item-gift-message-link-', // Selector prefix for the 'Gift Message' link.\n duration: 100, // Toggle duration.\n expandedClass: 'expanded', // Class added/removed to/from the 'Gift Message' link.\n expandedContentClass: 'expanded-content', // Class added/removed to/from the 'Gift Message' content.\n lastClass: 'last' // Class added/removed to/from the last item's row in the products table.\n },\n\n /**\n * Bind a click handler on the widget's element to toggle the gift message.\n * @private\n */\n _create: function () {\n this.element.on('click', $.proxy(this._toggleGiftMessage, this));\n },\n\n /**\n * Toggle the display of the item's corresponding gift message.\n * @private\n * @param {jQuery.Event} event - Click event.\n */\n _toggleGiftMessage: function (event) {\n var element = $(event.target), // Click target. The 'Gift Message' link or 'Close' button.\n options = this.options, // Cached widget options.\n itemId = element.data('item-id'), // The individual item's numeric id.\n link = $(options.linkPrefix + itemId), // The 'Gift Message' expandable link.\n row = $(options.rowPrefix + itemId), // The item's row in the products table.\n region = $('#' + element.attr('aria-controls')); // The gift message container region.\n\n region.toggleClass(options.expandedContentClass, options.duration, function () {\n if (region.attr('aria-expanded') === 'true') {\n region.attr('aria-expanded', 'false');\n\n if (region.hasClass(options.lastClass)) {\n row.addClass(options.lastClass);\n }\n } else {\n region.attr('aria-expanded', 'true');\n\n if (region.hasClass(options.lastClass)) {\n row.removeClass(options.lastClass);\n }\n }\n link.toggleClass(options.expandedClass);\n });\n event.preventDefault(); // Prevent event propagation and avoid going to the link's href.\n }\n });\n\n return $.mage.giftMessage;\n});\n","Magento_Sales/js/orders-returns.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.ordersReturns', {\n options: {\n zipCode: '#oar-zip', // Search by zip code.\n emailAddress: '#oar-email', // Search by email address.\n searchType: '#quick-search-type-id' // Search element used for choosing between the two.\n },\n\n /** @inheritdoc */\n _create: function () {\n $(this.options.searchType).on('change', $.proxy(this._showIdentifyBlock, this)).trigger('change');\n },\n\n /**\n * Show either the search by zip code option or the search by email address option.\n * @private\n * @param {jQuery.Event} e - Change event. Event target value is either 'zip' or 'email'.\n */\n _showIdentifyBlock: function (e) {\n var value = $(e.target).val();\n\n $(this.options.zipCode).toggle(value === 'zip');\n $(this.options.emailAddress).toggle(value === 'email');\n }\n });\n\n return $.mage.ordersReturns;\n});\n","Magento_Sales/js/view/last-ordered-items.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 'underscore'\n], function (Component, customerData, _) {\n 'use strict';\n\n return Component.extend({\n defaults: {\n isShowAddToCart: false\n },\n\n /** @inheritdoc */\n initialize: function () {\n this._super();\n this.lastOrderedItems = customerData.get('last-ordered-items');\n this.lastOrderedItems.subscribe(this.checkSalableItems.bind(this));\n this.checkSalableItems();\n\n return this;\n },\n\n /** @inheritdoc */\n initObservable: function () {\n this._super()\n .observe('isShowAddToCart');\n\n return this;\n },\n\n /**\n * Check if items is_saleable and change add to cart button visibility.\n */\n checkSalableItems: function () {\n var isShowAddToCart = _.some(this.lastOrderedItems().items, {\n 'is_saleable': true\n });\n\n this.isShowAddToCart(isShowAddToCart);\n }\n });\n});\n","Magento_Customer/js/password-strength-indicator.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/zxcvbn',\n 'mage/translate',\n 'mage/validation'\n], function ($, zxcvbn, $t) {\n 'use strict';\n\n $.widget('mage.passwordStrengthIndicator', {\n options: {\n cache: {},\n passwordSelector: '[type=password]',\n passwordStrengthMeterSelector: '[data-role=password-strength-meter]',\n passwordStrengthMeterLabelSelector: '[data-role=password-strength-meter-label]',\n formSelector: 'form',\n emailSelector: 'input[type=\"email\"]'\n },\n\n /**\n * Widget initialization\n * @private\n */\n _create: function () {\n this.options.cache.input = $(this.options.passwordSelector, this.element);\n this.options.cache.meter = $(this.options.passwordStrengthMeterSelector, this.element);\n this.options.cache.label = $(this.options.passwordStrengthMeterLabelSelector, this.element);\n\n // We need to look outside the module for backward compatibility, since someone can already use the module.\n // @todo Narrow this selector in 2.3 so it doesn't accidentally finds the email field from the\n // newsletter email field or any other \"email\" field.\n this.options.cache.email = $(this.options.formSelector).find(this.options.emailSelector);\n this._bind();\n },\n\n /**\n * Event binding, will monitor change, keyup and paste events.\n * @private\n */\n _bind: function () {\n this._on(this.options.cache.input, {\n 'change': this._calculateStrength,\n 'keyup': this._calculateStrength,\n 'paste': this._calculateStrength\n });\n\n if (this.options.cache.email.length) {\n this._on(this.options.cache.email, {\n 'change': this._calculateStrength,\n 'keyup': this._calculateStrength,\n 'paste': this._calculateStrength\n });\n }\n },\n\n /**\n * Calculate password strength\n * @private\n */\n _calculateStrength: function () {\n var password = this._getPassword(),\n isEmpty = password.length === 0,\n zxcvbnScore,\n displayScore,\n isValid;\n\n // Display score is based on combination of whether password is empty, valid, and zxcvbn strength\n if (isEmpty) {\n displayScore = 0;\n } else {\n this.options.cache.input.rules('add', {\n 'password-not-equal-to-user-name': this.options.cache.email.val()\n });\n\n // We should only perform this check in case there is an email field on screen\n if (this.options.cache.email.length &&\n password.toLowerCase() === this.options.cache.email.val().toLowerCase()) {\n displayScore = 1;\n } else {\n isValid = $.validator.validateSingleElement(this.options.cache.input);\n zxcvbnScore = zxcvbn(password).score;\n displayScore = isValid && zxcvbnScore > 0 ? zxcvbnScore : 1;\n }\n }\n\n // Update label\n this._displayStrength(displayScore);\n },\n\n /**\n * Display strength\n * @param {Number} displayScore\n * @private\n */\n _displayStrength: function (displayScore) {\n var strengthLabel = '',\n className;\n\n switch (displayScore) {\n case 0:\n strengthLabel = $t('No Password');\n className = 'password-none';\n break;\n\n case 1:\n strengthLabel = $t('Weak');\n className = 'password-weak';\n break;\n\n case 2:\n strengthLabel = $t('Medium');\n className = 'password-medium';\n break;\n\n case 3:\n strengthLabel = $t('Strong');\n className = 'password-strong';\n break;\n\n case 4:\n strengthLabel = $t('Very Strong');\n className = 'password-very-strong';\n break;\n }\n\n this.options.cache.meter\n .removeClass()\n .addClass(className);\n this.options.cache.label.text(strengthLabel);\n },\n\n /**\n * Get password value\n * @returns {*}\n * @private\n */\n _getPassword: function () {\n return this.options.cache.input.val();\n }\n });\n\n return $.mage.passwordStrengthIndicator;\n});\n","Magento_Customer/js/checkout-balance.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.checkoutBalance', {\n /**\n * Initialize store credit events\n * @private\n */\n _create: function () {\n this.eventData = {\n price: this.options.balance,\n totalPrice: 0\n };\n this.element.on('change', $.proxy(function (e) {\n if ($(e.target).is(':checked')) {\n this.eventData.price = -1 * this.options.balance;\n } else {\n if (this.options.amountSubstracted) { //eslint-disable-line no-lonely-if\n this.eventData.price = parseFloat(this.options.usedAmount);\n this.options.amountSubstracted = false;\n } else {\n this.eventData.price = parseFloat(this.options.balance);\n }\n }\n this.element.trigger('updateCheckoutPrice', this.eventData);\n }, this));\n }\n });\n\n return $.mage.checkoutBalance;\n});\n","Magento_Customer/js/validation.js":"define([\n 'jquery',\n 'moment',\n 'mageUtils',\n 'jquery/validate',\n 'validation',\n 'mage/translate'\n], function ($, moment, utils) {\n 'use strict';\n\n $.validator.addMethod(\n 'validate-date',\n function (value, element, params) {\n var dateFormat = utils.normalizeDate(params.dateFormat);\n\n if (value === '') {\n return true;\n }\n\n return moment(value, dateFormat, true).isValid();\n },\n $.mage.__('Invalid date')\n );\n\n $.validator.addMethod(\n 'validate-dob',\n function (value, element, params) {\n var dateFormat = utils.convertToMomentFormat(params.dateFormat);\n\n if (value === '') {\n return true;\n }\n\n return moment(value, dateFormat).isBefore(moment());\n },\n $.mage.__('The Date of Birth should not be greater than today.')\n );\n});\n","Magento_Customer/js/customer-global-session-loader.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/customer-data'\n], function ($, customerData) {\n 'use strict';\n\n return function () {\n var customer;\n\n // When the session is available, this customer menu will be available\n if ($('.customer-menu').length > 0) {\n customer = customerData.get('customer');\n\n customerData.getInitCustomerData().done(function () {\n // Check if the customer data is set in local storage, if not reload data from server\n if (!customer().firstname) {\n customerData.reload([], false);\n }\n });\n }\n };\n});\n","Magento_Customer/js/addressValidation.js":"/**\n * Copyright \u00a9 Magento, Inc. All rights reserved.\n * See COPYING.txt for license details.\n */\n\ndefine([\n 'jquery',\n 'underscore',\n 'mageUtils',\n 'mage/translate',\n 'Magento_Checkout/js/model/postcode-validator',\n 'jquery-ui-modules/widget',\n 'validation'\n], function ($, __, utils, $t, postCodeValidator) {\n 'use strict';\n\n $.widget('mage.addressValidation', {\n options: {\n selectors: {\n button: '[data-action=save-address]',\n zip: '#zip',\n country: 'select[name=\"country_id\"]:visible'\n }\n },\n\n zipInput: null,\n countrySelect: null,\n\n /**\n * Validation creation\n *\n * @protected\n */\n _create: function () {\n var button = $(this.options.selectors.button, this.element);\n\n this.zipInput = $(this.options.selectors.zip, this.element);\n this.countrySelect = $(this.options.selectors.country, this.element);\n\n this.element.validation({\n\n /**\n * Submit Handler\n * @param {Element} form - address form\n */\n submitHandler: function (form) {\n\n button.attr('disabled', true);\n form.submit();\n }\n });\n\n this._addPostCodeValidation();\n },\n\n /**\n * Add postcode validation\n *\n * @protected\n */\n _addPostCodeValidation: function () {\n var self = this;\n\n this.zipInput.on('keyup', __.debounce(function (event) {\n var valid = self._validatePostCode(event.target.value);\n\n self._renderValidationResult(valid);\n }, 500)\n );\n\n this.countrySelect.on('change', function () {\n var valid = self._validatePostCode(self.zipInput.val());\n\n self._renderValidationResult(valid);\n });\n },\n\n /**\n * Validate post code value.\n *\n * @protected\n * @param {String} postCode - post code\n * @return {Boolean} Whether is post code valid\n */\n _validatePostCode: function (postCode) {\n var countryId = this.countrySelect.val();\n\n if (postCode === null) {\n return true;\n }\n\n return postCodeValidator.validate(postCode, countryId, this.options.postCodes);\n },\n\n /**\n * Renders warning messages for invalid post code.\n *\n * @protected\n * @param {Boolean} valid\n */\n _renderValidationResult: function (valid) {\n var warnMessage,\n alertDiv = this.zipInput.next();\n\n if (!valid) {\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 }\n\n alertDiv.children(':first').text(warnMessage);\n\n if (valid) {\n alertDiv.hide();\n } else {\n alertDiv.show();\n }\n }\n });\n\n return $.mage.addressValidation;\n});\n","Magento_Customer/js/customer-data.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 'underscore',\n 'ko',\n 'Magento_Customer/js/section-config',\n 'mage/url',\n 'mage/storage',\n 'jquery/jquery-storageapi'\n], function ($, _, ko, sectionConfig, url) {\n 'use strict';\n\n var options = {},\n storage,\n storageInvalidation,\n invalidateCacheBySessionTimeOut,\n invalidateCacheByCloseCookieSession,\n dataProvider,\n buffer,\n customerData,\n deferred = $.Deferred();\n\n url.setBaseUrl(window.BASE_URL);\n options.sectionLoadUrl = url.build('customer/section/load');\n\n /**\n * @param {Object} invalidateOptions\n */\n invalidateCacheBySessionTimeOut = function (invalidateOptions) {\n var date;\n\n if (new Date($.localStorage.get('mage-cache-timeout')) < new Date()) {\n storage.removeAll();\n }\n date = new Date(Date.now() + parseInt(invalidateOptions.cookieLifeTime, 10) * 1000);\n $.localStorage.set('mage-cache-timeout', date);\n };\n\n /**\n * Invalidate Cache By Close Cookie Session\n */\n invalidateCacheByCloseCookieSession = function () {\n if (!$.cookieStorage.isSet('mage-cache-sessid')) {\n storage.removeAll();\n }\n\n $.cookieStorage.set('mage-cache-sessid', true);\n };\n\n dataProvider = {\n\n /**\n * @param {Object} sectionNames\n * @return {Object}\n */\n getFromStorage: function (sectionNames) {\n var result = {};\n\n _.each(sectionNames, function (sectionName) {\n result[sectionName] = storage.get(sectionName);\n });\n\n return result;\n },\n\n /**\n * @param {Object} sectionNames\n * @param {Boolean} forceNewSectionTimestamp\n * @return {*}\n */\n getFromServer: function (sectionNames, forceNewSectionTimestamp) {\n var parameters;\n\n sectionNames = sectionConfig.filterClientSideSections(sectionNames);\n parameters = _.isArray(sectionNames) && sectionNames.indexOf('*') < 0 ? {\n sections: sectionNames.join(',')\n } : [];\n parameters['force_new_section_timestamp'] = forceNewSectionTimestamp;\n\n return $.getJSON(options.sectionLoadUrl, parameters).fail(function (jqXHR) {\n throw new Error(jqXHR);\n });\n }\n };\n\n /**\n * @param {Function} target\n * @param {String} sectionName\n * @return {*}\n */\n ko.extenders.disposableCustomerData = function (target, sectionName) {\n var sectionDataIds, newSectionDataIds = {};\n\n target.subscribe(function () {\n setTimeout(function () {\n storage.remove(sectionName);\n sectionDataIds = $.cookieStorage.get('section_data_ids') || {};\n _.each(sectionDataIds, function (data, name) {\n if (name !== sectionName) {\n newSectionDataIds[name] = data;\n }\n });\n $.cookieStorage.set('section_data_ids', newSectionDataIds);\n }, 3000);\n });\n\n return target;\n };\n\n buffer = {\n data: {},\n\n /**\n * @param {String} sectionName\n */\n bind: function (sectionName) {\n this.data[sectionName] = ko.observable({});\n },\n\n /**\n * @param {String} sectionName\n * @return {Object}\n */\n get: function (sectionName) {\n if (!this.data[sectionName]) {\n this.bind(sectionName);\n }\n\n return this.data[sectionName];\n },\n\n /**\n * @return {Array}\n */\n keys: function () {\n return _.keys(this.data);\n },\n\n /**\n * @param {String} sectionName\n * @param {Object} sectionData\n */\n notify: function (sectionName, sectionData) {\n if (!this.data[sectionName]) {\n this.bind(sectionName);\n }\n this.data[sectionName](sectionData);\n },\n\n /**\n * @param {Object} sections\n */\n update: function (sections) {\n var sectionId = 0,\n sectionDataIds = $.cookieStorage.get('section_data_ids') || {};\n\n _.each(sections, function (sectionData, sectionName) {\n sectionId = sectionData['data_id'];\n sectionDataIds[sectionName] = sectionId;\n storage.set(sectionName, sectionData);\n storageInvalidation.remove(sectionName);\n buffer.notify(sectionName, sectionData);\n });\n $.cookieStorage.set('section_data_ids', sectionDataIds);\n },\n\n /**\n * @param {Object} sections\n */\n remove: function (sections) {\n _.each(sections, function (sectionName) {\n storage.remove(sectionName);\n\n if (!sectionConfig.isClientSideSection(sectionName)) {\n storageInvalidation.set(sectionName, true);\n }\n });\n }\n };\n\n customerData = {\n\n /**\n * Customer data initialization\n */\n init: function () {\n var expiredSectionNames = this.getExpiredSectionNames();\n\n if (expiredSectionNames.length > 0) {\n _.each(dataProvider.getFromStorage(storage.keys()), function (sectionData, sectionName) {\n buffer.notify(sectionName, sectionData);\n });\n this.reload(expiredSectionNames, false);\n } else {\n _.each(dataProvider.getFromStorage(storage.keys()), function (sectionData, sectionName) {\n buffer.notify(sectionName, sectionData);\n });\n\n if (!_.isEmpty(storageInvalidation.keys())) {\n this.reload(storageInvalidation.keys(), false);\n }\n }\n\n if (!_.isEmpty($.cookieStorage.get('section_data_clean'))) {\n this.reload(sectionConfig.getSectionNames(), true);\n $.cookieStorage.set('section_data_clean', '');\n }\n },\n\n /**\n * Storage init\n */\n initStorage: function () {\n $.cookieStorage.setConf({\n path: '/',\n expires: new Date(Date.now() + parseInt(options.cookieLifeTime, 10) * 1000)\n });\n storage = $.initNamespaceStorage('mage-cache-storage').localStorage;\n storageInvalidation = $.initNamespaceStorage('mage-cache-storage-section-invalidation').localStorage;\n },\n\n /**\n * Retrieve the list of sections that has expired since last page reload.\n *\n * Sections can expire due to lifetime constraints or due to inconsistent storage information\n * (validated by cookie data).\n *\n * @return {Array}\n */\n getExpiredSectionNames: function () {\n var expiredSectionNames = [],\n cookieSectionTimestamps = $.cookieStorage.get('section_data_ids') || {},\n sectionLifetime = options.expirableSectionLifetime * 60,\n currentTimestamp = Math.floor(Date.now() / 1000),\n sectionData;\n\n // process sections that can expire due to lifetime constraints\n _.each(options.expirableSectionNames, function (sectionName) {\n sectionData = storage.get(sectionName);\n\n if (typeof sectionData === 'object' && sectionData['data_id'] + sectionLifetime <= currentTimestamp) {\n expiredSectionNames.push(sectionName);\n }\n });\n\n // process sections that can expire due to storage information inconsistency\n _.each(cookieSectionTimestamps, function (cookieSectionTimestamp, sectionName) {\n sectionData = storage.get(sectionName);\n\n if (typeof sectionData === 'undefined' ||\n typeof sectionData === 'object' &&\n cookieSectionTimestamp !== sectionData['data_id']\n ) {\n expiredSectionNames.push(sectionName);\n }\n });\n\n //remove expired section names of previously installed/enable modules\n expiredSectionNames = _.intersection(expiredSectionNames, sectionConfig.getSectionNames());\n\n return _.uniq(expiredSectionNames);\n },\n\n /**\n * Check if some sections have to be reloaded.\n *\n * @deprecated Use getExpiredSectionNames instead.\n *\n * @return {Boolean}\n */\n needReload: function () {\n var expiredSectionNames = this.getExpiredSectionNames();\n\n return expiredSectionNames.length > 0;\n },\n\n /**\n * Retrieve the list of expired keys.\n *\n * @deprecated Use getExpiredSectionNames instead.\n *\n * @return {Array}\n */\n getExpiredKeys: function () {\n return this.getExpiredSectionNames();\n },\n\n /**\n * @param {String} sectionName\n * @return {*}\n */\n get: function (sectionName) {\n return buffer.get(sectionName);\n },\n\n /**\n * @param {String} sectionName\n * @param {Object} sectionData\n */\n set: function (sectionName, sectionData) {\n var data = {};\n\n data[sectionName] = sectionData;\n buffer.update(data);\n },\n\n /**\n * Avoid using this function directly 'cause of possible performance drawbacks.\n * Each customer section reload brings new non-cached ajax request.\n *\n * @param {Array} sectionNames\n * @param {Boolean} forceNewSectionTimestamp\n * @return {*}\n */\n reload: function (sectionNames, forceNewSectionTimestamp) {\n return dataProvider.getFromServer(sectionNames, forceNewSectionTimestamp).done(function (sections) {\n $(document).trigger('customer-data-reload', [sectionNames]);\n buffer.update(sections);\n });\n },\n\n /**\n * @param {Array} sectionNames\n */\n invalidate: function (sectionNames) {\n var sectionDataIds,\n sectionsNamesForInvalidation;\n\n sectionsNamesForInvalidation = _.contains(sectionNames, '*') ? sectionConfig.getSectionNames() :\n sectionNames;\n\n $(document).trigger('customer-data-invalidate', [sectionsNamesForInvalidation]);\n buffer.remove(sectionsNamesForInvalidation);\n sectionDataIds = $.cookieStorage.get('section_data_ids') || {};\n\n // Invalidate section in cookie (increase version of section with 1000)\n _.each(sectionsNamesForInvalidation, function (sectionName) {\n if (!sectionConfig.isClientSideSection(sectionName)) {\n sectionDataIds[sectionName] += 1000;\n }\n });\n $.cookieStorage.set('section_data_ids', sectionDataIds);\n },\n\n /**\n * Checks if customer data is initialized.\n *\n * @returns {jQuery.Deferred}\n */\n getInitCustomerData: function () {\n return deferred.promise();\n },\n\n /**\n * Reload sections on ajax complete\n *\n * @param {Object} jsonResponse\n * @param {Object} settings\n */\n onAjaxComplete: function (jsonResponse, settings) {\n var sections,\n redirects;\n\n if (settings.type.match(/post|put|delete/i)) {\n sections = sectionConfig.getAffectedSections(settings.url);\n\n if (sections && sections.length) {\n this.invalidate(sections);\n redirects = ['redirect', 'backUrl'];\n\n if (_.isObject(jsonResponse) && !_.isEmpty(_.pick(jsonResponse, redirects))) { //eslint-disable-line\n return;\n }\n this.reload(sections, true);\n }\n }\n },\n\n /**\n * @param {Object} settings\n * @constructor\n */\n 'Magento_Customer/js/customer-data': function (settings) {\n options = settings;\n customerData.initStorage();\n invalidateCacheBySessionTimeOut(settings);\n invalidateCacheByCloseCookieSession();\n customerData.init();\n deferred.resolve();\n }\n };\n\n /**\n * Events listener\n */\n $(document).on('ajaxComplete', function (event, xhr, settings) {\n customerData.onAjaxComplete(xhr.responseJSON, settings);\n });\n\n /**\n * Events listener\n */\n $(document).on('submit', function (event) {\n var sections;\n\n if (event.target.method.match(/post|put|delete/i)) {\n sections = sectionConfig.getAffectedSections(event.target.action);\n\n if (sections) {\n customerData.invalidate(sections);\n }\n }\n });\n\n return customerData;\n});\n","Magento_Customer/js/block-submit-on-send.js":"/**\n * Copyright \u00a9 Magento, Inc. All rights reserved.\n * See COPYING.txt for license details.\n */\n\ndefine([\n 'jquery',\n 'mage/mage'\n], function ($) {\n 'use strict';\n\n return function (config) {\n var dataForm = $('#' + config.formId);\n\n dataForm.on('submit', function () {\n $(this).find(':submit').attr('disabled', 'disabled');\n\n if (this.isValid === false) {\n $(this).find(':submit').prop('disabled', false);\n }\n this.isValid = true;\n });\n dataForm.on('invalid-form.validate', function () {\n $(this).find(':submit').prop('disabled', false);\n this.isValid = false;\n });\n };\n});\n","Magento_Customer/js/logout-redirect.js":"/**\n * Copyright \u00a9 Magento, Inc. All rights reserved.\n * See COPYING.txt for license details.\n */\n\ndefine([\n 'jquery',\n 'mage/mage'\n], function ($) {\n 'use strict';\n\n return function (data) {\n $($.mage.redirect(data.url, 'assign', 5000));\n };\n});\n","Magento_Customer/js/change-email-password.js":"/**\n * Copyright \u00a9 Magento, Inc. All rights reserved.\n * See COPYING.txt for license details.\n */\ndefine([\n 'jquery',\n 'jquery-ui-modules/widget'\n], function ($) {\n 'use strict';\n\n $.widget('mage.changeEmailPassword', {\n options: {\n changeEmailSelector: '[data-role=change-email]',\n changePasswordSelector: '[data-role=change-password]',\n mainContainerSelector: '[data-container=change-email-password]',\n titleSelector: '[data-title=change-email-password]',\n emailContainerSelector: '[data-container=change-email]',\n newPasswordContainerSelector: '[data-container=new-password]',\n confirmPasswordContainerSelector: '[data-container=confirm-password]',\n currentPasswordSelector: '[data-input=current-password]',\n emailSelector: '[data-input=change-email]',\n newPasswordSelector: '[data-input=new-password]',\n confirmPasswordSelector: '[data-input=confirm-password]'\n },\n\n /**\n * Create widget\n * @private\n */\n _create: function () {\n this.element.on('change', $.proxy(function () {\n this._checkChoice();\n }, this));\n\n this._checkChoice();\n this._bind();\n },\n\n /**\n * Event binding, will monitor change, keyup and paste events.\n * @private\n */\n _bind: function () {\n this._on($(this.options.emailSelector), {\n 'change': this._updatePasswordFieldWithEmailValue,\n 'keyup': this._updatePasswordFieldWithEmailValue,\n 'paste': this._updatePasswordFieldWithEmailValue\n });\n },\n\n /**\n * Check choice\n * @private\n */\n _checkChoice: function () {\n if ($(this.options.changeEmailSelector).is(':checked') &&\n $(this.options.changePasswordSelector).is(':checked')) {\n this._showAll();\n } else if ($(this.options.changeEmailSelector).is(':checked')) {\n this._showEmail();\n } else if ($(this.options.changePasswordSelector).is(':checked')) {\n this._showPassword();\n } else {\n this._hideAll();\n }\n },\n\n /**\n * Show email and password input fields\n * @private\n */\n _showAll: function () {\n $(this.options.titleSelector).html(this.options.titleChangeEmailAndPassword);\n\n $(this.options.mainContainerSelector).show();\n $(this.options.emailContainerSelector).show();\n $(this.options.newPasswordContainerSelector).show();\n $(this.options.confirmPasswordContainerSelector).show();\n\n $(this.options.currentPasswordSelector).attr('data-validate', '{required:true}').prop('disabled', false);\n $(this.options.emailSelector).attr('data-validate', '{required:true}').prop('disabled', false);\n this._updatePasswordFieldWithEmailValue();\n $(this.options.confirmPasswordSelector).attr(\n 'data-validate',\n '{required:true, equalTo:\"' + this.options.newPasswordSelector + '\"}'\n ).prop('disabled', false);\n },\n\n /**\n * Hide email and password input fields\n * @private\n */\n _hideAll: function () {\n $(this.options.mainContainerSelector).hide();\n $(this.options.emailContainerSelector).hide();\n $(this.options.newPasswordContainerSelector).hide();\n $(this.options.confirmPasswordContainerSelector).hide();\n\n $(this.options.currentPasswordSelector).removeAttr('data-validate').prop('disabled', true);\n $(this.options.emailSelector).removeAttr('data-validate').prop('disabled', true);\n $(this.options.newPasswordSelector).removeAttr('data-validate').prop('disabled', true);\n $(this.options.confirmPasswordSelector).removeAttr('data-validate').prop('disabled', true);\n },\n\n /**\n * Show email input fields\n * @private\n */\n _showEmail: function () {\n this._showAll();\n $(this.options.titleSelector).html(this.options.titleChangeEmail);\n\n $(this.options.newPasswordContainerSelector).hide();\n $(this.options.confirmPasswordContainerSelector).hide();\n\n $(this.options.newPasswordSelector).removeAttr('data-validate').prop('disabled', true);\n $(this.options.confirmPasswordSelector).removeAttr('data-validate').prop('disabled', true);\n },\n\n /**\n * Show password input fields\n * @private\n */\n _showPassword: function () {\n this._showAll();\n $(this.options.titleSelector).html(this.options.titleChangePassword);\n\n $(this.options.emailContainerSelector).hide();\n\n $(this.options.emailSelector).removeAttr('data-validate').prop('disabled', true);\n },\n\n /**\n * Update password validation rules with email input field value\n * @private\n */\n _updatePasswordFieldWithEmailValue: function () {\n $(this.options.newPasswordSelector).attr(\n 'data-validate',\n '{required:true, ' +\n '\\'validate-customer-password\\':true, ' +\n '\\'password-not-equal-to-user-name\\':\\'' + $(this.options.emailSelector).val() + '\\'}'\n ).prop('disabled', false);\n }\n });\n\n return $.mage.changeEmailPassword;\n});\n","Magento_Customer/js/address.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.address', {\n /**\n * Options common to all instances of this widget.\n * @type {Object}\n */\n options: {\n deleteConfirmMessage: $.mage.__('Are you sure you want to delete this address?')\n },\n\n /**\n * Bind event handlers for adding and deleting addresses.\n * @private\n */\n _create: function () {\n var options = this.options,\n addAddress = options.addAddress,\n deleteAddress = options.deleteAddress;\n\n if (addAddress) {\n $(document).on('click', addAddress, this._addAddress.bind(this));\n }\n\n if (deleteAddress) {\n $(document).on('click', deleteAddress, this._deleteAddress.bind(this));\n }\n },\n\n /**\n * Add a new address.\n * @private\n */\n _addAddress: function () {\n window.location = this.options.addAddressLocation;\n },\n\n /**\n * Delete the address whose id is specified in a data attribute after confirmation from the user.\n * @private\n * @param {jQuery.Event} e\n * @return {Boolean}\n */\n _deleteAddress: function (e) {\n var self = this;\n\n confirm({\n content: this.options.deleteConfirmMessage,\n actions: {\n\n /** @inheritdoc */\n confirm: function () {\n if (typeof $(e.target).parent().data('address') !== 'undefined') {\n window.location = self.options.deleteUrlPrefix + $(e.target).parent().data('address') +\n '/form_key/' + $.mage.cookies.get('form_key');\n } else {\n window.location = self.options.deleteUrlPrefix + $(e.target).data('address') +\n '/form_key/' + $.mage.cookies.get('form_key');\n }\n }\n }\n });\n\n return false;\n }\n });\n\n return $.mage.address;\n});\n","Magento_Customer/js/invalidation-processor.js":"/**\n * Copyright \u00a9 Magento, Inc. All rights reserved.\n * See COPYING.txt for license details.\n */\ndefine([\n 'underscore',\n 'uiElement',\n 'Magento_Customer/js/customer-data'\n], function (_, Element, customerData) {\n 'use strict';\n\n return Element.extend({\n /**\n * Initialize object\n */\n initialize: function () {\n this._super();\n this.process(customerData);\n },\n\n /**\n * Process all rules in loop, each rule can invalidate some sections in customer data\n *\n * @param {Object} customerDataObject\n */\n process: function (customerDataObject) {\n _.each(this.invalidationRules, function (rule, ruleName) {\n _.each(rule, function (ruleArgs, rulePath) {\n require([rulePath], function (Rule) {\n var currentRule = new Rule(ruleArgs);\n\n if (!_.isFunction(currentRule.process)) {\n throw new Error('Rule ' + ruleName + ' should implement invalidationProcessor interface');\n }\n currentRule.process(customerDataObject);\n });\n });\n });\n }\n });\n});\n","Magento_Customer/js/show-password.js":"/**\n* Copyright \u00a9 Magento, Inc. All rights reserved.\n* See COPYING.txt for license details.\n*/\n\ndefine([\n 'jquery',\n 'uiComponent'\n], function ($, Component) {\n 'use strict';\n\n return Component.extend({\n passwordSelector: '',\n passwordInputType: 'password',\n textInputType: 'text',\n\n defaults: {\n template: 'Magento_Customer/show-password',\n isPasswordVisible: false\n },\n\n /**\n * @return {Object}\n */\n initObservable: function () {\n this._super()\n .observe(['isPasswordVisible']);\n\n this.isPasswordVisible.subscribe(function (isChecked) {\n this._showPassword(isChecked);\n }.bind(this));\n\n return this;\n },\n\n /**\n * Show/Hide password\n * @private\n */\n _showPassword: function (isChecked) {\n $(this.passwordSelector).attr('type',\n isChecked ? this.textInputType : this.passwordInputType\n );\n }\n });\n});\n","Magento_Customer/js/section-config.js":"/**\n * Copyright \u00a9 Magento, Inc. All rights reserved.\n * See COPYING.txt for license details.\n */\n\ndefine(['underscore'], function (_) {\n 'use strict';\n\n var baseUrls = [],\n sections = [],\n clientSideSections = [],\n sectionNames = [],\n canonize;\n\n /**\n * @param {String} url\n * @return {String}\n */\n canonize = function (url) {\n var route = url;\n\n _.some(baseUrls, function (baseUrl) {\n route = url.replace(baseUrl, '');\n\n return route !== url;\n });\n\n return route.replace(/^\\/?index.php\\/?/, '').toLowerCase();\n };\n\n return {\n /**\n * Returns a list of sections which should be invalidated for given URL.\n * @param {String} url - URL which was requested.\n * @return {Object} - List of sections to invalidate.\n */\n getAffectedSections: function (url) {\n var route = canonize(url),\n actions = _.find(sections, function (val, section) {\n var matched;\n\n // Covers the case where \"*\" works as a glob pattern.\n if (section.indexOf('*') >= 0) {\n section = section.replace(/\\*/g, '[^/]+') + '$';\n matched = route.match(section);\n\n return matched && matched[0] === route;\n }\n\n return route.indexOf(section) === 0;\n });\n\n return _.union(_.toArray(actions), sections['*']);\n },\n\n /**\n * Filters the list of given sections to the ones defined as client side.\n * @param {Object} allSections - List of sections to check.\n * @return {Object} - List of filtered sections.\n */\n filterClientSideSections: function (allSections) {\n return _.difference(allSections, clientSideSections);\n },\n\n /**\n * Tells if section is defined as client side.\n * @param {String} sectionName - Name of the section to check.\n * @return {Boolean}\n */\n isClientSideSection: function (sectionName) {\n return _.contains(clientSideSections, sectionName);\n },\n\n /**\n * Returns array of section names.\n * @returns {Array}\n */\n getSectionNames: function () {\n return sectionNames;\n },\n\n /**\n * @param {Object} options\n * @constructor\n */\n 'Magento_Customer/js/section-config': function (options) {\n baseUrls = options.baseUrls;\n sections = options.sections;\n clientSideSections = options.clientSideSections;\n sectionNames = options.sectionNames;\n }\n };\n});\n","Magento_Customer/js/view/authentication-popup.js":"/**\n * Copyright \u00a9 Magento, Inc. All rights reserved.\n * See COPYING.txt for license details.\n */\n\ndefine([\n 'jquery',\n 'ko',\n 'Magento_Ui/js/form/form',\n 'Magento_Customer/js/action/login',\n 'Magento_Customer/js/customer-data',\n 'Magento_Customer/js/model/authentication-popup',\n 'mage/translate',\n 'mage/url',\n 'Magento_Ui/js/modal/alert',\n 'mage/validation'\n], function ($, ko, Component, loginAction, customerData, authenticationPopup, $t, url, alert) {\n 'use strict';\n\n return Component.extend({\n registerUrl: window.authenticationPopup.customerRegisterUrl,\n forgotPasswordUrl: window.authenticationPopup.customerForgotPasswordUrl,\n autocomplete: window.authenticationPopup.autocomplete,\n modalWindow: null,\n isLoading: ko.observable(false),\n\n defaults: {\n template: 'Magento_Customer/authentication-popup'\n },\n\n /**\n * Init\n */\n initialize: function () {\n var self = this;\n\n this._super();\n url.setBaseUrl(window.authenticationPopup.baseUrl);\n loginAction.registerLoginCallback(function () {\n self.isLoading(false);\n });\n },\n\n /** Init popup login window */\n setModalElement: function (element) {\n if (authenticationPopup.modalWindow == null) {\n authenticationPopup.createPopUp(element);\n }\n },\n\n /** Is login form enabled for current customer */\n isActive: function () {\n var customer = customerData.get('customer');\n\n return customer() == false; //eslint-disable-line eqeqeq\n },\n\n /** Show login popup window */\n showModal: function () {\n if (this.modalWindow) {\n $(this.modalWindow).modal('openModal');\n } else {\n alert({\n content: $t('Guest checkout is disabled.')\n });\n }\n },\n\n /**\n * Provide login action\n *\n * @return {Boolean}\n */\n login: function (formUiElement, event) {\n var loginData = {},\n formElement = $(event.currentTarget),\n formDataArray = formElement.serializeArray();\n\n event.stopPropagation();\n formDataArray.forEach(function (entry) {\n loginData[entry.name] = entry.value;\n });\n loginData['customerLoginUrl'] = window.authenticationPopup.customerLoginUrl;\n if (formElement.validation() &&\n formElement.validation('isValid')\n ) {\n this.isLoading(true);\n loginAction(loginData);\n }\n\n return false;\n }\n });\n});\n","Magento_Customer/js/view/customer.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], function (Component, customerData) {\n 'use strict';\n\n return Component.extend({\n /** @inheritdoc */\n initialize: function () {\n this._super();\n\n this.customer = customerData.get('customer');\n }\n });\n});\n","Magento_Customer/js/action/login.js":"/**\n * Copyright \u00a9 Magento, Inc. All rights reserved.\n * See COPYING.txt for license details.\n */\n\ndefine([\n 'jquery',\n 'mage/storage',\n 'Magento_Ui/js/model/messageList',\n 'Magento_Customer/js/customer-data',\n 'mage/translate'\n], function ($, storage, globalMessageList, customerData, $t) {\n 'use strict';\n\n var callbacks = [],\n\n /**\n * @param {Object} loginData\n * @param {String} redirectUrl\n * @param {*} isGlobal\n * @param {Object} messageContainer\n */\n action = function (loginData, redirectUrl, isGlobal, messageContainer) {\n messageContainer = messageContainer || globalMessageList;\n let customerLoginUrl = 'customer/ajax/login';\n\n if (loginData.customerLoginUrl) {\n customerLoginUrl = loginData.customerLoginUrl;\n delete loginData.customerLoginUrl;\n }\n\n return storage.post(\n customerLoginUrl,\n JSON.stringify(loginData),\n isGlobal\n ).done(function (response) {\n if (response.errors) {\n messageContainer.addErrorMessage(response);\n callbacks.forEach(function (callback) {\n callback(loginData);\n });\n } else {\n callbacks.forEach(function (callback) {\n callback(loginData);\n });\n customerData.invalidate(['customer']);\n\n if (response.redirectUrl) {\n window.location.href = response.redirectUrl;\n } else if (redirectUrl) {\n window.location.href = redirectUrl;\n } else {\n location.reload();\n }\n }\n }).fail(function () {\n messageContainer.addErrorMessage({\n 'message': $t('Could not authenticate. Please try again later')\n });\n callbacks.forEach(function (callback) {\n callback(loginData);\n });\n });\n };\n\n /**\n * @param {Function} callback\n */\n action.registerLoginCallback = function (callback) {\n callbacks.push(callback);\n };\n\n return action;\n});\n","Magento_Customer/js/action/check-email-availability.js":"/**\n * Copyright \u00a9 Magento, Inc. All rights reserved.\n * See COPYING.txt for license details.\n */\n\ndefine([\n 'mage/storage',\n 'Magento_Checkout/js/model/url-builder'\n], function (storage, urlBuilder) {\n 'use strict';\n\n return function (deferred, email) {\n return storage.post(\n urlBuilder.createUrl('/customers/isEmailAvailable', {}),\n JSON.stringify({\n customerEmail: email\n }),\n false\n ).done(function (isEmailAvailable) {\n if (isEmailAvailable) {\n deferred.resolve();\n } else {\n deferred.reject();\n }\n }).fail(function () {\n deferred.reject();\n });\n };\n});\n","Magento_Customer/js/model/address-list.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 './customer-addresses'\n], function (ko, defaultProvider) {\n 'use strict';\n\n return ko.observableArray(defaultProvider.getAddressItems());\n});\n","Magento_Customer/js/model/authentication-popup.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/modal'\n], function ($, modal) {\n 'use strict';\n\n return {\n modalWindow: null,\n\n /**\n * Create popUp window for provided element\n *\n * @param {HTMLElement} element\n */\n createPopUp: function (element) {\n var options = {\n 'type': 'popup',\n 'modalClass': 'popup-authentication',\n 'focus': '[name=username]',\n 'responsive': true,\n 'innerScroll': true,\n 'trigger': '.proceed-to-checkout',\n 'buttons': []\n };\n\n this.modalWindow = element;\n modal(options, $(this.modalWindow));\n },\n\n /** Show login popup window */\n showModal: function () {\n $(this.modalWindow).modal('openModal').trigger('contentUpdated');\n }\n };\n});\n","Magento_Customer/js/model/customer-addresses.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 './customer/address'\n], function ($, ko, Address) {\n 'use strict';\n\n var isLoggedIn = ko.observable(window.isCustomerLoggedIn);\n\n return {\n /**\n * @return {Array}\n */\n getAddressItems: function () {\n var items = [],\n customerData = window.customerData;\n\n if (isLoggedIn()) {\n if (Object.keys(customerData).length) {\n $.each(customerData.addresses, function (key, item) {\n items.push(new Address(item));\n });\n }\n }\n\n return items;\n }\n };\n});\n","Magento_Customer/js/model/customer.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 'underscore',\n './address-list'\n], function ($, ko, _, addressList) {\n 'use strict';\n\n var isLoggedIn = ko.observable(window.isCustomerLoggedIn),\n customerData = {};\n\n if (isLoggedIn()) {\n customerData = window.customerData;\n } else {\n customerData = {};\n }\n\n return {\n customerData: customerData,\n customerDetails: {},\n isLoggedIn: isLoggedIn,\n\n /**\n * @param {Boolean} flag\n */\n setIsLoggedIn: function (flag) {\n isLoggedIn(flag);\n },\n\n /**\n * @return {Array}\n */\n getBillingAddressList: function () {\n return addressList();\n },\n\n /**\n * @return {Array}\n */\n getShippingAddressList: function () {\n return addressList();\n },\n\n /**\n * @param {String} fieldName\n * @param {*} value\n */\n setDetails: function (fieldName, value) {\n if (fieldName) {\n this.customerDetails[fieldName] = value;\n }\n },\n\n /**\n * @param {String} fieldName\n * @return {*}\n */\n getDetails: function (fieldName) {\n if (fieldName) {\n if (this.customerDetails.hasOwnProperty(fieldName)) {\n return this.customerDetails[fieldName];\n }\n\n return undefined;\n }\n\n return this.customerDetails;\n },\n\n /**\n * @param {Array} address\n * @return {Number}\n */\n addCustomerAddress: function (address) {\n var fields = [\n 'customer_id', 'country_id', 'street', 'company', 'telephone', 'fax', 'postcode', 'city',\n 'firstname', 'lastname', 'middlename', 'prefix', 'suffix', 'vat_id', 'default_billing',\n 'default_shipping'\n ],\n customerAddress = {},\n hasAddress = 0,\n existingAddress;\n\n if (!this.customerData.addresses) {\n this.customerData.addresses = [];\n }\n\n customerAddress = _.pick(address, fields);\n\n if (address.hasOwnProperty('region_id')) {\n customerAddress.region = {\n 'region_id': address['region_id'],\n region: address.region\n };\n }\n\n for (existingAddress in this.customerData.addresses) {\n if (this.customerData.addresses.hasOwnProperty(existingAddress)) {\n if (_.isEqual(this.customerData.addresses[existingAddress], customerAddress)) { //eslint-disable-line\n hasAddress = existingAddress;\n break;\n }\n }\n }\n\n if (hasAddress === 0) {\n return this.customerData.addresses.push(customerAddress) - 1;\n }\n\n return hasAddress;\n },\n\n /**\n * @param {*} addressId\n * @return {Boolean}\n */\n setAddressAsDefaultBilling: function (addressId) {\n if (this.customerData.addresses[addressId]) {\n this.customerData.addresses[addressId]['default_billing'] = 1;\n\n return true;\n }\n\n return false;\n },\n\n /**\n * @param {*} addressId\n * @return {Boolean}\n */\n setAddressAsDefaultShipping: function (addressId) {\n if (this.customerData.addresses[addressId]) {\n this.customerData.addresses[addressId]['default_shipping'] = 1;\n\n return true;\n }\n\n return false;\n }\n };\n});\n","Magento_Customer/js/model/customer/address.js":"/**\n * Copyright \u00a9 Magento, Inc. All rights reserved.\n * See COPYING.txt for license details.\n */\n\n/**\n * @api\n */\ndefine(['underscore'], function (_) {\n 'use strict';\n\n /**\n * Returns new address object.\n *\n * @param {Object} addressData\n * @return {Object}\n */\n return function (addressData) {\n var regionId;\n\n if (addressData.region['region_id'] && addressData.region['region_id'] !== '0') {\n regionId = addressData.region['region_id'] + '';\n }\n\n return {\n customerAddressId: addressData.id,\n email: addressData.email,\n countryId: addressData['country_id'],\n regionId: regionId,\n regionCode: addressData.region['region_code'],\n region: addressData.region.region,\n customerId: addressData['customer_id'],\n street: addressData.street,\n company: addressData.company,\n telephone: addressData.telephone,\n fax: addressData.fax,\n postcode: addressData.postcode,\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 sameAsBilling: addressData['same_as_billing'],\n saveInAddressBook: addressData['save_in_address_book'],\n customAttributes: _.toArray(addressData['custom_attributes']).reverse(),\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 {*}\n */\n getAddressInline: function () {\n return addressData.inline;\n },\n\n /**\n * @return {String}\n */\n getType: function () {\n return 'customer-address';\n },\n\n /**\n * @return {String}\n */\n getKey: function () {\n return this.getType() + this.customerAddressId;\n },\n\n /**\n * @return {String}\n */\n getCacheKey: function () {\n return this.getKey();\n },\n\n /**\n * @return {Boolean}\n */\n isEditable: function () {\n return false;\n },\n\n /**\n * @return {Boolean}\n */\n canUseForBilling: function () {\n return true;\n }\n };\n };\n});\n","Magento_Customer/js/invalidation-rules/website-rule.js":"/**\n * Copyright \u00a9 Magento, Inc. All rights reserved.\n * See COPYING.txt for license details.\n */\ndefine([\n 'uiClass'\n], function (Element) {\n 'use strict';\n\n return Element.extend({\n\n defaults: {\n scopeConfig: {}\n },\n\n /**\n * Takes website id from current customer data and compare it with current website id\n * If customer belongs to another scope, we need to invalidate current section\n *\n * @param {Object} customerData\n */\n process: function (customerData) {\n var customer = customerData.get('customer');\n\n if (this.scopeConfig && customer() &&\n ~~customer().websiteId !== ~~this.scopeConfig.websiteId && ~~customer().websiteId !== 0) {\n customerData.reload(['customer']);\n }\n }\n });\n});\n","Magento_Directory/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.directoryRegionUpdater', {\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('[generated]').remove();\n $(this.options.regionListId).removeClass('mage-error').parent().find('[generated]').remove();\n $(this.options.postcodeId).removeClass('mage-error').parent().find('[generated]').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 $.each(regionsEntries, $.proxy(function (key, value) {\n regionData = value[1];\n regionId = regionData.id;\n this._renderSelectOption(regionList, regionId.toString(), 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').removeAttr('disabled');\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.removeAttr('disabled').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').removeAttr('disabled');\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\"]').removeAttr('disabled').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.directoryRegionUpdater;\n});\n","Magento_Theme/js/cookie-status.js":"define([\n 'jquery',\n 'Magento_Ui/js/modal/modal',\n 'mage/translate'\n], function ($, modal) {\n 'use strict';\n\n $.widget('mage.cookieStatus', {\n options: {\n type: 'popup',\n responsive: true,\n innerScroll: true,\n autoOpen: true,\n buttons: [{\n text: $.mage.__('Close'),\n class: 'cookie-status',\n\n /**\n * Callback for click event\n */\n click: function () {\n this.closeModal();\n }\n }]\n },\n\n /**\n * Init object\n * @private\n */\n _init: function () {\n\n if (!navigator.cookieEnabled) {\n modal(this.options, $('#cookie-status'));\n }\n }\n });\n\n return $.mage.cookieStatus;\n});\n","Magento_Theme/js/row-builder.js":"/**\n * Copyright \u00a9 Magento, Inc. All rights reserved.\n * See COPYING.txt for license details.\n */\n\n/**\n * JQuery UI Widget declaration: 'mage.rowBuilder'\n *\n * @api\n */\ndefine([\n 'jquery',\n 'mage/template',\n 'jquery-ui-modules/widget'\n], function ($, mageTemplate) {\n 'use strict';\n\n $.widget('mage.rowBuilder', {\n\n /**\n * options with default values for setting up the template\n */\n options: {\n //Default template options\n rowTemplate: '#template-registrant',\n rowContainer: '#registrant-container',\n //Row index used by the template rows.\n rowIndex: 0,\n //Row count: Should not be set externally\n rowCount: 0,\n rowParentElem: '<li></li>',\n rowContainerClass: 'fields',\n addRowBtn: '#add-registrant-button',\n btnRemoveIdPrefix: 'btn-remove',\n btnRemoveSelector: '.btn-remove',\n rowIdPrefix: 'row',\n //This class is added to rows added after the first one. Adds the dotted separator\n additionalRowClass: 'add-row',\n\n /*\n This is provided during widget instantiation. eg :\n formDataPost : {\"formData\":formData,\"templateFields\":['field1-name','field2-name'] }\n -\"formData\" is the multi-dimensional array of form field values : [['a','b'],['c','b']]\n received from the server and encoded\n -\"templateFields\" are the input fields in the template with index suffixed after the field name\n eg field1-name{index}\n */\n formDataPost: null,\n //Default selectors for add element of a template\n addEventSelector: 'button',\n //Default selectors for remove markup elements of a template\n remEventSelector: 'a',\n //This option allows adding first row delete option and a row separator\n hideFirstRowAddSeparator: true,\n //Max rows - This option should be set when instantiating the widget\n maxRows: 1000,\n maxRowsMsg: '#max-registrant-message'\n },\n\n /**\n * Initialize create\n * @private\n */\n _create: function () {\n this.rowTemplate = mageTemplate(this.options.rowTemplate);\n\n this.options.rowCount = this.options.rowIndex = 0;\n\n //On document ready related tasks\n $($.proxy(this.ready, this));\n\n //Binding template-wide events handlers for adding and removing rows\n this.element.on(\n 'click',\n this.options.addEventSelector + this.options.addRowBtn,\n $.proxy(this.handleAdd, this)\n );\n this.element.on(\n 'click',\n this.options.remEventSelector + this.options.btnRemoveSelector,\n $.proxy(this.handleRemove, this)\n );\n },\n\n /**\n * Initialize template\n * @public\n */\n ready: function () {\n if (this.options.formDataPost &&\n this.options.formDataPost.formData &&\n this.options.formDataPost.formData.length\n ) {\n this.processFormDataArr(this.options.formDataPost);\n } else if (this.options.rowIndex === 0 && this.options.maxRows !== 0) {\n //If no form data , then add default row\n this.addRow(0);\n }\n },\n\n /**\n * Process and loop through all row data to create preselected values. This is used for any error on submit.\n * For complex implementations the inheriting widget can override this behavior\n * @public\n * @param {Object} formDataArr\n */\n processFormDataArr: function (formDataArr) {\n var formData = formDataArr.formData,\n templateFields = formDataArr.templateFields,\n formRow,\n i, j;\n\n for (i = this.options.rowIndex = 0; i < formData.length; this.options.rowIndex = i++) {\n this.addRow(i);\n\n formRow = formData[i];\n\n for (j = 0; j < formRow.length; j++) {\n this.setFieldById(templateFields[j] + i, formRow[j]);\n }\n }\n\n },\n\n /**\n * Initialize and create markup for template row. Add it to the parent container.\n * The template processing will substitute row index at all places marked with _index_ in the template\n * using the template\n * @public\n * @param {Number} index - current index/count of the created template. This will be used as the id\n * @return {*}\n */\n addRow: function (index) {\n var row = $(this.options.rowParentElem),\n tmpl;\n\n row.addClass(this.options.rowContainerClass).attr('id', this.options.rowIdPrefix + index);\n\n tmpl = this.rowTemplate({\n data: {\n _index_: index\n }\n });\n\n $(tmpl).appendTo(row);\n\n $(this.options.rowContainer).append(row).trigger('contentUpdated');\n\n row.addClass(this.options.additionalRowClass);\n\n //Remove 'delete' link and additionalRowClass for first row\n if (this.options.rowIndex === 0 && this.options.hideFirstRowAddSeparator) {\n $('#' + this._esc(this.options.btnRemoveIdPrefix) + '0').remove();\n $('#' + this._esc(this.options.rowIdPrefix) + '0').removeClass(this.options.additionalRowClass);\n }\n\n this.maxRowCheck(++this.options.rowCount);\n\n return row;\n },\n\n /**\n * Remove return item information row\n * @public\n * @param {*} rowIndex - return item information row index\n * @return {Boolean}\n */\n removeRow: function (rowIndex) {\n $('#' + this._esc(this.options.rowIdPrefix) + rowIndex).remove();\n this.maxRowCheck(--this.options.rowCount);\n\n return false;\n },\n\n /**\n * Function to check if maximum rows are exceeded and render/hide maxMsg and Add btn\n * @public\n * @param {Number} rowIndex\n */\n maxRowCheck: function (rowIndex) {\n var addRowBtn = $(this.options.addRowBtn),\n maxRowMsg = $(this.options.maxRowsMsg);\n\n //liIndex starts from 0\n if (rowIndex >= this.options.maxRows) {\n addRowBtn.hide();\n maxRowMsg.show();\n } else if (addRowBtn.is(':hidden')) {\n addRowBtn.show();\n maxRowMsg.hide();\n }\n },\n\n /**\n * Set the value on given element\n * @public\n * @param {String} domId\n * @param {String} value\n */\n setFieldById: function (domId, value) {\n var x = $('#' + this._esc(domId));\n\n if (x.length) {\n\n if (x.is(':checkbox')) {\n x.attr('checked', true);\n } else if (x.is('option')) {\n x.attr('selected', 'selected');\n } else {\n x.val(value);\n }\n }\n },\n\n /**\n * Delegated handler for adding a row\n * @public\n * @return {Boolean}\n */\n handleAdd: function () {\n this.addRow(++this.options.rowIndex);\n\n return false;\n },\n\n /**\n * Delegated handler for removing a selected row\n * @public\n * @param {Object} e - Native event object\n * @return {Boolean}\n */\n handleRemove: function (e) {\n this.removeRow($(e.currentTarget).closest('[id^=\"' + this.options.btnRemoveIdPrefix + '\"]')\n .attr('id').replace(this.options.btnRemoveIdPrefix, ''));\n\n return false;\n },\n\n /**\n * Utility function to add escape chars for jquery selector strings\n * @private\n * @param {String} str - String to be processed\n * @return {String}\n */\n _esc: function (str) {\n return str ? str.replace(/([ ;&,.+*~\\':\"!\\^$\\[\\]()=>|\\/@])/g, '\\\\$1') : str;\n }\n });\n\n return $.mage.rowBuilder;\n});\n","Magento_Theme/js/theme.js":"/**\n * Copyright \u00a9 2015 Magento. All rights reserved.\n * See COPYING.txt for license details.\n */\nrequire([\n 'jquery',\n 'mage/smart-keyboard-handler',\n 'mage/mage',\n 'domReady!'\n], function ($, keyboardHandler) {\n 'use strict';\n $(document).ready(function(){\n $('.cart-summary').mage('sticky', {\n container: '#maincontent'\n });\n\n $('.panel.header .header.links').clone().appendTo('#store\\\\.links');\n });\n keyboardHandler.apply();\n});\nrequire([\n 'jquery'\n], function ($) {\n (function() {\n var ev = new $.Event('classadded'),\n orig = $.fn.addClass;\n $.fn.addClass = function() {\n $(this).trigger(ev, arguments);\n return orig.apply(this, arguments);\n }\n })();\n $.fn.extend({\n scrollToMe: function(){\n if($(this).length){\n var top = $(this).offset().top - 100;\n $('html,body').animate({scrollTop: top}, 300);\n }\n },\n scrollToJustMe: function(){\n if($(this).length){\n var top = jQuery(this).offset().top;\n $('html,body').animate({scrollTop: top}, 300);\n }\n }\n });\n $(document).ready(function(){\n var windowScroll_t;\n $(window).scroll(function(){\n clearTimeout(windowScroll_t);\n windowScroll_t = setTimeout(function(){\n if(jQuery(this).scrollTop() > 100){\n $('#totop').fadeIn();\n }else{\n $('#totop').fadeOut();\n }\n }, 500);\n });\n $('#totop').off(\"click\").on(\"click\",function(){\n $('html, body').animate({scrollTop: 0}, 600);\n });\n if ($('body').hasClass('checkout-cart-index')) {\n if ($('#co-shipping-method-form .fieldset.rates').length > 0 && $('#co-shipping-method-form .fieldset.rates :checked').length === 0) {\n $('#block-shipping').on('collapsiblecreate', function () {\n $('#block-shipping').collapsible('forceActivate');\n });\n }\n }\n $(\".products-grid .weltpixel-quickview\").each(function(){\n $(this).parent().parent().addClass('has-quickview');\n if($(this).parents('.product-type-advanced').find(\".product-item-photo.porto-tb-featured-image .icon-absolute\").length > 0){\n $(this).appendTo($(this).parents('.product-type-advanced').find(\".product-item-photo .porto-tb-featured-image .product-item-inner .product-item-actions\"));\n }else{\n $(this).appendTo($(this).parent().parent().children(\".product-item-photo\"));\n }\n });\n $(\".word-rotate\").each(function() {\n\n var $this = $(this),\n itemsWrapper = $(this).find(\".word-rotate-items\"),\n items = itemsWrapper.find(\"> span\"),\n firstItem = items.eq(0),\n firstItemClone = firstItem.clone(),\n itemHeight = 0,\n currentItem = 1,\n currentTop = 0;\n\n itemHeight = firstItem.height();\n\n itemsWrapper.append(firstItemClone);\n\n $this\n .height(itemHeight)\n .addClass(\"active\");\n\n setInterval(function() {\n currentTop = (currentItem * itemHeight);\n\n itemsWrapper.animate({\n top: -(currentTop) + \"px\"\n }, 300, function() {\n currentItem++;\n if(currentItem > items.length) {\n itemsWrapper.css(\"top\", 0);\n currentItem = 1;\n }\n });\n\n }, 2000);\n\n });\n $(\".top-links-icon\").off(\"click\").on(\"click\", function(e){\n if($(this).parent().children(\"ul.links\").hasClass(\"show\")) {\n $(this).parent().children(\"ul.links\").removeClass(\"show\");\n } else {\n $(this).parent().children(\"ul.links\").addClass(\"show\");\n }\n e.stopPropagation();\n });\n $(\".top-links-icon\").parent().click(function(e){\n e.stopPropagation();\n });\n $(\".search-toggle-icon\").click(function(e){\n if($(this).parent().children(\".block-search\").hasClass(\"show\")) {\n $(this).parent().children(\".block-search\").removeClass(\"show\");\n $(this).removeClass('open');\n } else {\n $(this).parent().children(\".block-search\").addClass(\"show\");\n $(this).addClass('open');\n }\n e.stopPropagation();\n });\n $(\".search-toggle-icon\").parent().click(function(e){\n e.stopPropagation();\n });\n $(\"html,body\").click(function(){\n $(\".search-toggle-icon\").parent().children(\".block-search\").removeClass(\"show\");\n $('.autocomplete-suggestions').hide();\n $(\".search-toggle-icon\").removeClass('open');\n $(\".top-links-icon\").parent().children(\"ul.links\").removeClass(\"show\");\n });\n\n /********************* Qty Holder **************************/\n $(document).on(\"click\", \".qtyplus\", function(e) {\n // Stop acting like a button\n e.preventDefault();\n // Get its current value\n var currentVal = parseInt($(this).parents('form').find('input[name=\"qty\"]').val());\n // If is not undefined\n if (!isNaN(currentVal)) {\n // Increment\n $(this).parents('form').find('input[name=\"qty\"]').val(currentVal + 1);\n } else {\n // Otherwise put a 0 there\n $(this).parents('form').find('input[name=\"qty\"]').val(0);\n }\n });\n // This button will decrement the value till 0\n $(document).on(\"click\", \".qtyminus\", function(e) {\n // Stop acting like a button\n e.preventDefault();\n // Get the field name\n fieldName = $(this).attr('field');\n // Get its current value\n var currentVal = parseInt($(this).parents('form').find('input[name=\"qty\"]').val());\n // If it isn't undefined or its greater than 0\n if (!isNaN(currentVal) && currentVal > 0) {\n // Decrement one\n $(this).parents('form').find('input[name=\"qty\"]').val(currentVal - 1);\n } else {\n // Otherwise put a 0 there\n $(this).parents('form').find('input[name=\"qty\"]').val(0);\n }\n });\n $(\".qty-inc\").unbind('click').click(function(){\n if($(this).parents('.field.qty,.control.qty').find(\"input.input-text.qty\").is(':enabled')){\n $(this).parents('.field.qty,.control.qty').find(\"input.input-text.qty\").val((+$(this).parents('.field.qty,.control.qty').find(\"input.input-text.qty\").val() + 1) || 0);\n $(this).parents('.field.qty,.control.qty').find(\"input.input-text.qty\").trigger('change');\n $(this).focus();\n }\n });\n $(\".qty-dec\").unbind('click').click(function(){\n if($(this).parents('.field.qty,.control.qty').find(\"input.input-text.qty\").is(':enabled')){\n $(this).parents('.field.qty,.control.qty').find(\"input.input-text.qty\").val(($(this).parents('.field.qty,.control.qty').find(\"input.input-text.qty\").val() - 1 > 0) ? ($(this).parents('.field.qty,.control.qty').find(\"input.input-text.qty\").val() - 1) : 0);\n $(this).parents('.field.qty,.control.qty').find(\"input.input-text.qty\").trigger('change');\n $(this).focus();\n }\n });\n });\n});\nrequire([\n 'jquery',\n 'lazyload'\n], function ($) {\n $(document).ready(function(){\n $(\"img.porto-lazyload:not(.porto-lazyload-loaded)\").lazyload({effect:\"fadeIn\", effect_speed: 400 });\n if ($('.porto-lazyload:not(.porto-lazyload-loaded)').closest('.owl-carousel').length) {\n $('.porto-lazyload:not(.porto-lazyload-loaded)').closest('.owl-carousel').on('initialized.owl.carousel', function() {\n $(this).find('.porto-lazyload:not(.porto-lazyload-loaded)').trigger('appear');\n });\n $('.porto-lazyload:not(.porto-lazyload-loaded)').closest('.owl-carousel').on('changed.owl.carousel', function() {\n $(this).find('.porto-lazyload:not(.porto-lazyload-loaded)').trigger('appear');\n });\n }\n window.setTimeout(function(){\n $('.sidebar-filterproducts').find('.porto-lazyload:not(.porto-lazyload-loaded)').trigger('appear');\n },500);\n });\n});\n","Magento_Theme/js/view/add-home-breadcrumb.js":"/**\n * Copyright \u00a9 Magento, Inc. All rights reserved.\n * See COPYING.txt for license details.\n */\n/* eslint-disable max-nested-callbacks, no-undef */\ndefine([\n 'jquery',\n 'Magento_Theme/js/model/breadcrumb-list',\n 'mage/translate'\n], function ($, breadcrumbList) {\n 'use strict';\n\n /**\n * @return {Object}\n */\n var homeCrumb = function () {\n return {\n name: 'home',\n label: $.mage.__('Home'),\n title: $.mage.__('Go to Home Page'),\n link: BASE_URL || ''\n };\n };\n\n return function (breadcrumb) {\n\n breadcrumbList.unshift(homeCrumb());\n\n return breadcrumb;\n };\n});\n","Magento_Theme/js/view/breadcrumbs.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 'Magento_Theme/js/model/breadcrumb-list',\n 'text!Magento_Theme/templates/breadcrumbs.html',\n 'jquery-ui-modules/widget'\n], function ($, mageTemplate, breadcrumbList, tpl) {\n 'use strict';\n\n /**\n * Breadcrumb Widget.\n */\n $.widget('mage.breadcrumbs', {\n\n /** @inheritdoc */\n _init: function () {\n this._super();\n this._render();\n },\n\n /**\n * Render breadcrumb.\n *\n * @private\n */\n _render: function () {\n var html,\n crumbs = breadcrumbList,\n template = mageTemplate(tpl);\n\n this._decorate(crumbs);\n\n html = template({\n 'breadcrumbs': crumbs\n });\n\n if (html.length) {\n $(this.element).html(html);\n }\n },\n\n /**\n * Decorate list.\n *\n * @param {Array} list\n * @private\n */\n _decorate: function (list) {\n\n if (list.length) {\n list[0].first = true;\n }\n\n if (list.length > 1) {\n list[list.length - 1].last = true;\n }\n }\n });\n\n return $.mage.breadcrumbs;\n});\n","Magento_Theme/js/view/messages.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 'uiComponent',\n 'Magento_Customer/js/customer-data',\n 'underscore',\n 'escaper',\n 'jquery/jquery-storageapi'\n], function ($, Component, customerData, _, escaper) {\n 'use strict';\n\n return Component.extend({\n defaults: {\n cookieMessages: [],\n messages: [],\n allowedTags: ['div', 'span', 'b', 'strong', 'i', 'em', 'u', 'a']\n },\n\n /**\n * Extends Component object by storage observable messages.\n */\n initialize: function () {\n this._super();\n\n this.cookieMessages = _.unique($.cookieStorage.get('mage-messages'), 'text');\n this.messages = customerData.get('messages').extend({\n disposableCustomerData: 'messages'\n });\n\n // Force to clean obsolete messages\n if (!_.isEmpty(this.messages().messages)) {\n customerData.set('messages', {});\n }\n\n $.mage.cookies.set('mage-messages', '', {\n samesite: 'strict',\n domain: ''\n });\n },\n\n /**\n * Prepare the given message to be rendered as HTML\n *\n * @param {String} message\n * @return {String}\n */\n prepareMessageForHtml: function (message) {\n return escaper.escapeHtml(message, this.allowedTags);\n }\n });\n});\n","Magento_Theme/js/model/breadcrumb-list.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","Magento_Wishlist/js/wishlist.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 'mage/template',\n 'Magento_Ui/js/modal/alert',\n 'jquery-ui-modules/widget',\n 'mage/validation/validation',\n 'mage/dataPost'\n], function ($, mageTemplate, alert) {\n 'use strict';\n\n $.widget('mage.wishlist', {\n options: {\n dataAttribute: 'item-id',\n nameFormat: 'qty[{0}]',\n btnRemoveSelector: '[data-role=remove]',\n qtySelector: '[data-role=qty]',\n addToCartSelector: '[data-role=tocart]',\n addAllToCartSelector: '[data-role=all-tocart]',\n commentInputType: 'textarea',\n infoList: false\n },\n\n /**\n * Bind handlers to events.\n */\n _create: function () {\n var _this = this;\n\n if (!this.options.infoList) {\n this.element\n .on('addToCart', function (event, context) {\n var urlParams;\n\n event.stopPropagation(event);\n $(context).data('stop-processing', true);\n urlParams = _this._getItemsToCartParams(\n $(context).parents('[data-row=product-item]').find(_this.options.addToCartSelector)\n );\n $.mage.dataPost().postData(urlParams);\n\n return false;\n })\n .on('click', this.options.btnRemoveSelector, $.proxy(function (event) {\n event.preventDefault();\n $.mage.dataPost().postData($(event.currentTarget).data('post-remove'));\n }, this))\n .on('click', this.options.addToCartSelector, $.proxy(this._beforeAddToCart, this))\n .on('click', this.options.addAllToCartSelector, $.proxy(this._addAllWItemsToCart, this))\n .on('focusin focusout', this.options.commentInputType, $.proxy(this._focusComment, this));\n }\n\n // Setup validation for the form\n this.element.mage('validation', {\n /** @inheritdoc */\n errorPlacement: function (error, element) {\n error.insertAfter(element.next());\n }\n });\n },\n\n /**\n * Process data before add to cart\n *\n * - update item's qty value.\n *\n * @param {Event} event\n * @private\n */\n _beforeAddToCart: function (event) {\n var elem = $(event.currentTarget),\n itemId = elem.data(this.options.dataAttribute),\n qtyName = $.validator.format(this.options.nameFormat, itemId),\n qtyValue = elem.parents().find('[name=\"' + qtyName + '\"]').val(),\n params = elem.data('post');\n\n if (params) {\n params.data = $.extend({}, params.data, {\n 'qty': qtyValue\n });\n elem.data('post', params);\n }\n },\n\n /**\n * Add wish list items to cart.\n * @private\n * @param {jQuery} elem - clicked 'add to cart' button\n */\n _getItemsToCartParams: function (elem) {\n var itemId, url, qtyName, qtyValue;\n\n if (elem.data(this.options.dataAttribute)) {\n itemId = elem.data(this.options.dataAttribute);\n url = this.options.addToCartUrl;\n qtyName = $.validator.format(this.options.nameFormat, itemId);\n qtyValue = elem.parents().find('[name=\"' + qtyName + '\"]').val();\n url.data.item = itemId;\n url.data.qty = qtyValue;\n\n return url;\n }\n },\n\n /**\n * Add all wish list items to cart\n * @private\n */\n _addAllWItemsToCart: function () {\n var urlParams = this.options.addAllToCartUrl,\n separator = urlParams.action.indexOf('?') >= 0 ? '&' : '?';\n\n this.element.find(this.options.qtySelector).each(function (index, element) {\n urlParams.action += separator + $(element).prop('name') + '=' + encodeURIComponent($(element).val());\n separator = '&';\n });\n $.mage.dataPost().postData(urlParams);\n },\n\n /**\n * Toggle comment string.\n * @private\n * @param {Event} e\n */\n _focusComment: function (e) {\n var commentInput = e.currentTarget;\n\n if (commentInput.value === '' || commentInput.value === this.options.commentString) {\n commentInput.value = commentInput.value === this.options.commentString ?\n '' : this.options.commentString;\n }\n }\n });\n\n // Extension for mage.wishlist - Select All checkbox\n $.widget('mage.wishlist', $.mage.wishlist, {\n options: {\n selectAllCheckbox: '#select-all',\n parentContainer: '#wishlist-table'\n },\n\n /** @inheritdoc */\n _create: function () {\n var selectAllCheckboxParent, checkboxCount;\n\n this._super();\n selectAllCheckboxParent = $(this.options.selectAllCheckbox).parents(this.options.parentContainer);\n checkboxCount = selectAllCheckboxParent\n .find('input:checkbox:not(' + this.options.selectAllCheckbox + ')').length;\n // If Select all checkbox is checked, check all item checkboxes, if unchecked, uncheck all item checkboxes\n $(this.options.selectAllCheckbox).on('click', function () {\n selectAllCheckboxParent.find('input:checkbox').attr('checked', $(this).is(':checked'));\n });\n // If all item checkboxes are checked, check select all checkbox,\n // if not all item checkboxes are checked, uncheck select all checkbox\n selectAllCheckboxParent.on(\n 'click',\n 'input:checkbox:not(' + this.options.selectAllCheckbox + ')',\n $.proxy(function () {\n var checkedCount = selectAllCheckboxParent\n .find('input:checkbox:checked:not(' + this.options.selectAllCheckbox + ')').length;\n\n $(this.options.selectAllCheckbox).attr('checked', checkboxCount === checkedCount);\n }, this)\n );\n }\n });\n // Extension for mage.wishlist info add to cart\n $.widget('mage.wishlist', $.mage.wishlist, {\n /** @inheritdoc */\n _create: function () {\n this._super();\n\n if (this.options.infoList) {\n this.element.on('addToCart', $.proxy(function (event, context) {\n this.element.find('input:checkbox').attr('checked', false);\n $(context).closest('tr').find('input:checkbox').attr('checked', true);\n this.element.trigger('submit');\n }, this));\n this._checkBoxValidate();\n }\n },\n\n /**\n * validate checkbox selection.\n * @private\n */\n _checkBoxValidate: function () {\n this.element.validation({\n submitHandler: $.proxy(function (form) {\n if ($(form).find('input:checkbox:checked').length) {\n form.submit();\n } else {\n alert({\n content: this.options.checkBoxValidationMessage\n });\n }\n }, this)\n });\n }\n });\n\n // Extension for mage.wishlist - Add Wishlist item to Gift Registry\n $.widget('mage.wishlist', $.mage.wishlist, {\n options: {\n formTmplSelector: '#form-tmpl',\n formTmplId: '#wishlist-hidden-form'\n },\n\n /** @inheritdoc */\n _create: function () {\n var _this = this;\n\n this._super();\n this.element.on('click', '[data-wishlist-to-giftregistry]', function () {\n var json = $(this).data('wishlist-to-giftregistry'),\n tmplJson = {\n item: json.itemId,\n entity: json.entity,\n url: json.url\n },\n html = mageTemplate(_this.options.formTmplSelector, {\n data: tmplJson\n });\n\n $(html).appendTo('body');\n $(_this.options.formTmplId).trigger('submit');\n });\n }\n });\n\n return $.mage.wishlist;\n});\n","Magento_Wishlist/js/search.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.wishlistSearch', {\n\n /**\n * Bind handlers to events\n */\n _create: function () {\n this.element.on('change', $.proxy(this._toggleForm, this));\n },\n\n /**\n * Toggle Form\n * @private\n */\n _toggleForm: function () {\n switch (this.element.val()) {\n case 'name':\n $(this.options.emailFormSelector).hide();\n $(this.options.nameFormSelector).show();\n break;\n\n case 'email':\n $(this.options.nameFormSelector).hide();\n $(this.options.emailFormSelector).show();\n break;\n default:\n $(this.options.emailFormSelector).add(this.options.nameFormSelector).hide();\n }\n }\n });\n\n return $.mage.wishlistSearch;\n});\n","Magento_Wishlist/js/add-to-wishlist.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.addToWishlist', {\n options: {\n bundleInfo: 'div.control [name^=bundle_option]',\n configurableInfo: '.super-attribute-select',\n groupedInfo: '#super-product-table input',\n downloadableInfo: '#downloadable-links-list input',\n customOptionsInfo: '.product-custom-option',\n qtyInfo: '#qty',\n actionElement: '[data-action=\"add-to-wishlist\"]',\n productListWrapper: '.product-item-info',\n productPageWrapper: '.product-info-main'\n },\n\n /** @inheritdoc */\n _create: function () {\n this._bind();\n },\n\n /**\n * @private\n */\n _bind: function () {\n var options = this.options,\n dataUpdateFunc = '_updateWishlistData',\n validateProductQty = '_validateWishlistQty',\n changeCustomOption = 'change ' + options.customOptionsInfo,\n changeQty = 'change ' + options.qtyInfo,\n updateWishlist = 'click ' + options.actionElement,\n events = {},\n key;\n\n if ('productType' in options) {\n if (typeof options.productType === 'string') {\n options.productType = [options.productType];\n }\n } else {\n options.productType = [];\n }\n\n events[changeCustomOption] = dataUpdateFunc;\n events[changeQty] = dataUpdateFunc;\n events[updateWishlist] = validateProductQty;\n\n for (key in options.productType) {\n if (options.productType.hasOwnProperty(key) && options.productType[key] + 'Info' in options) {\n events['change ' + options[options.productType[key] + 'Info']] = dataUpdateFunc;\n }\n }\n this._on(events);\n },\n\n /**\n * @param {jQuery.Event} event\n * @private\n */\n _updateWishlistData: function (event) {\n var dataToAdd = {},\n isFileUploaded = false,\n handleObjSelector = null,\n self = this;\n\n if (event.handleObj.selector == this.options.qtyInfo) { //eslint-disable-line eqeqeq\n this._updateAddToWishlistButton({}, event);\n event.stopPropagation();\n\n return;\n }\n\n handleObjSelector = $(event.currentTarget).closest('form').find(event.handleObj.selector);\n\n handleObjSelector.each(function (index, element) {\n if ($(element).is('input[type=text]') ||\n $(element).is('input[type=email]') ||\n $(element).is('input[type=number]') ||\n $(element).is('input[type=hidden]') ||\n $(element).is('input[type=checkbox]:checked') ||\n $(element).is('input[type=radio]:checked') ||\n $(element).is('textarea') ||\n $('#' + element.id + ' option:selected').length\n ) {\n if ($(element).data('selector') || $(element).attr('name')) {\n dataToAdd = $.extend({}, dataToAdd, self._getElementData(element));\n }\n\n return;\n }\n\n if ($(element).is('input[type=file]') && $(element).val()) {\n isFileUploaded = true;\n }\n });\n\n if (isFileUploaded) {\n this.bindFormSubmit();\n }\n this._updateAddToWishlistButton(dataToAdd, event);\n event.stopPropagation();\n },\n\n /**\n * @param {Object} dataToAdd\n * @param {jQuery.Event} event\n * @private\n */\n _updateAddToWishlistButton: function (dataToAdd, event) {\n var self = this,\n buttons = this._getAddToWishlistButton(event);\n\n buttons.each(function (index, element) {\n var params = $(element).data('post'),\n currentTarget = event.currentTarget,\n targetElement,\n targetValue;\n\n if (!params) {\n params = {\n 'data': {}\n };\n } else if ($(currentTarget).data('selector') || $(currentTarget).attr('name')) {\n targetElement = self._getElementData(currentTarget);\n targetValue = Object.keys(targetElement)[0];\n\n if (params.data.hasOwnProperty(targetValue) && !dataToAdd.hasOwnProperty(targetValue)) {\n delete params.data[targetValue];\n }\n }\n\n params.data = $.extend({}, params.data, dataToAdd, {\n 'qty': $(self.options.qtyInfo).val()\n });\n $(element).data('post', params);\n });\n },\n\n /**\n * @param {jQuery.Event} event\n * @private\n */\n _getAddToWishlistButton: function (event) {\n var productListWrapper = $(event.currentTarget).closest(this.options.productListWrapper);\n\n if (productListWrapper.length) {\n return productListWrapper.find(this.options.actionElement);\n }\n\n return $(this.options.actionElement);\n },\n\n /**\n * @param {Object} array1\n * @param {Object} array2\n * @return {Object}\n * @private\n * @deprecated\n */\n _arrayDiffByKeys: function (array1, array2) {\n var result = {};\n\n $.each(array1, function (key, value) {\n if (key.indexOf('option') === -1) {\n return;\n }\n\n if (!array2[key]) {\n result[key] = value;\n }\n });\n\n return result;\n },\n\n /**\n * @param {HTMLElement} element\n * @return {Object}\n * @private\n */\n _getElementData: function (element) {\n var data, elementName, elementValue;\n\n element = $(element);\n data = {};\n elementName = element.data('selector') ? element.data('selector') : element.attr('name');\n elementValue = element.val();\n\n if (element.is('select[multiple]') && elementValue !== null) {\n if (elementName.substr(elementName.length - 2) == '[]') { //eslint-disable-line eqeqeq\n elementName = elementName.substring(0, elementName.length - 2);\n }\n $.each(elementValue, function (key, option) {\n data[elementName + '[' + option + ']'] = option;\n });\n } else if (elementName.substr(elementName.length - 2) == '[]') { //eslint-disable-line eqeqeq, max-depth\n elementName = elementName.substring(0, elementName.length - 2);\n\n data[elementName + '[' + elementValue + ']'] = elementValue;\n } else {\n data[elementName] = elementValue;\n }\n\n return data;\n },\n\n /**\n * @param {Object} params\n * @param {Object} dataToAdd\n * @private\n * @deprecated\n */\n _removeExcessiveData: function (params, dataToAdd) {\n var dataToRemove = this._arrayDiffByKeys(params.data, dataToAdd);\n\n $.each(dataToRemove, function (key) {\n delete params.data[key];\n });\n },\n\n /**\n * Bind form submit.\n */\n bindFormSubmit: function () {\n var self = this;\n\n $('[data-action=\"add-to-wishlist\"]').on('click', function (event) {\n var element, params, form, action;\n\n event.stopPropagation();\n event.preventDefault();\n\n element = $('input[type=file]' + self.options.customOptionsInfo);\n params = $(event.currentTarget).data('post');\n form = $(element).closest('form');\n action = params.action;\n\n if (params.data.id) {\n $('<input>', {\n type: 'hidden',\n name: 'id',\n value: params.data.id\n }).appendTo(form);\n }\n\n if (params.data.uenc) {\n action += 'uenc/' + params.data.uenc;\n }\n\n $(form).attr('action', action).trigger('submit');\n });\n },\n\n /**\n * Validate product quantity before updating Wish List\n *\n * @param {jQuery.Event} event\n * @private\n */\n _validateWishlistQty: function (event) {\n var element = $(this.options.qtyInfo);\n\n if (!(element.validation() && element.validation('isValid'))) {\n event.preventDefault();\n event.stopPropagation();\n\n return;\n }\n }\n });\n\n return $.mage.addToWishlist;\n});\n","Magento_Wishlist/js/view/wishlist.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], function (Component, customerData) {\n 'use strict';\n\n return Component.extend({\n /** @inheritdoc */\n initialize: function () {\n this._super();\n\n this.wishlist = customerData.get('wishlist');\n }\n });\n});\n","Magento_Wishlist/js/product/addtowishlist-button.js":"/**\n * Copyright \u00a9 Magento, Inc. All rights reserved.\n * See COPYING.txt for license details.\n */\n\ndefine([\n 'Magento_Ui/js/grid/columns/column',\n 'Magento_Catalog/js/product/uenc-processor',\n 'Magento_Catalog/js/product/list/column-status-validator'\n], function (Element, uencProcessor, columnStatusValidator) {\n 'use strict';\n\n return Element.extend({\n defaults: {\n label: ''\n },\n\n /**\n * Get request POST data.\n *\n * @param {Object} row\n * @return {String}\n */\n getDataPost: function (row) {\n return uencProcessor(row['extension_attributes']['wishlist_button'].url);\n },\n\n /**\n * Check if component must be shown.\n *\n * @return {Boolean}\n */\n isAllowed: function () {\n return columnStatusValidator.isValid(this.source(), 'add_to_wishlist', 'show_buttons');\n },\n\n /**\n * Get button label.\n *\n * @return {String}\n */\n getLabel: function () {\n return this.label;\n }\n });\n});\n","Magento_Downloadable/js/downloadable.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 'jquery-ui-modules/widget',\n 'Magento_Catalog/js/price-box'\n], function ($) {\n 'use strict';\n\n /**\n * Downloadable widget\n */\n $.widget('mage.downloadable', {\n options: {\n priceHolderSelector: '.price-box',\n linkElement: '',\n allElements: ''\n },\n\n /**\n * @inheritdoc\n */\n _init: function initLinks() {\n var element = this.element,\n options = $(this.options.linkElement, element);\n\n options.trigger('change');\n },\n\n /**\n * @inheritdoc\n */\n _create: function () {\n var self = this;\n\n this.element.find(this.options.linkElement).on('change', $.proxy(function () {\n this._reloadPrice();\n }, this));\n\n this.element.find(this.options.allElements).on('change', function () {\n if (this.checked) {\n $('label[for=\"' + this.id + '\"] > span').text($(this).attr('data-checked'));\n self.element.find(self.options.linkElement + ':not(:checked)').each(function () {\n $(this).trigger('click');\n });\n } else {\n $('[for=\"' + this.id + '\"] > span').text($(this).attr('data-notchecked'));\n self.element.find(self.options.linkElement + ':checked').each(function () {\n $(this).trigger('click');\n });\n }\n });\n\n this._reloadPrice();\n },\n\n /**\n * Reload product price with selected link price included\n * @private\n */\n _reloadPrice: function () {\n var finalPrice = 0,\n basePrice = 0;\n\n this.element.find(this.options.linkElement + ':checked').each($.proxy(function (index, element) {\n finalPrice += this.options.config.links[$(element).val()].finalPrice;\n basePrice += this.options.config.links[$(element).val()].basePrice;\n }, this));\n\n $(this.options.priceHolderSelector).trigger('updatePrice', {\n 'prices': {\n 'finalPrice': {\n 'amount': finalPrice\n },\n 'basePrice': {\n 'amount': basePrice\n }\n }\n });\n\n this.reloadAllCheckText();\n },\n\n /**\n * Reload all-elements-checkbox's label\n * @private\n */\n reloadAllCheckText: function () {\n var allChecked = true,\n allElementsCheck = $(this.options.allElements),\n allElementsLabel = $('label[for=\"' + allElementsCheck.attr('id') + '\"] > span');\n\n $(this.options.linkElement).each(function () {\n if (!this.checked) {\n allChecked = false;\n }\n });\n\n if (allChecked) {\n allElementsLabel.text(allElementsCheck.attr('data-checked'));\n allElementsCheck.prop('checked', true);\n } else {\n allElementsLabel.text(allElementsCheck.attr('data-notchecked'));\n allElementsCheck.prop('checked', false);\n }\n }\n });\n\n return $.mage.downloadable;\n});\n","Magento_Newsletter/js/newsletter-sign-up.js":"/**\n * Copyright \u00a9 Magento, Inc. All rights reserved.\n * See COPYING.txt for license details.\n */\n\ndefine([\n 'jquery',\n 'uiElement',\n 'mage/url',\n 'subscriptionStatusResolver',\n 'mage/validation'\n], function ($, Component, urlBuilder, subscriptionStatusResolver) {\n 'use strict';\n\n return Component.extend({\n\n defaults: {\n signUpElement: '',\n submitButton: '',\n element: null\n },\n\n /** @inheritdoc */\n initialize: function (config, element) {\n this._super();\n this.element = element;\n $(element).on('change', $.proxy(this.updateSignUpStatus, this));\n this.updateSignUpStatus();\n },\n\n /**\n * Send status request and update subscription element according to result.\n */\n updateSignUpStatus: function () {\n var element = $(this.element),\n email = element.val(),\n self = this,\n newsletterSubscription;\n\n if ($(self.signUpElement).is(':checked')) {\n return;\n }\n\n if (!email || !$.validator.methods['validate-email'].call(this, email, element)) {\n return;\n }\n\n newsletterSubscription = $.Deferred();\n\n $(self.submitButton).prop('disabled', true);\n\n subscriptionStatusResolver(email, newsletterSubscription);\n\n $.when(newsletterSubscription).done(function (isSubscribed) {\n if (isSubscribed) {\n $(self.signUpElement).prop('checked', true);\n }\n }).always(function () {\n $(self.submitButton).prop('disabled', false);\n });\n }\n });\n});\n","Magento_Newsletter/js/subscription-status-resolver.js":"/**\n * Copyright \u00a9 Magento, Inc. All rights reserved.\n * See COPYING.txt for license details.\n */\n\ndefine([\n 'jquery',\n 'mage/url'\n], function ($, urlBuilder) {\n 'use strict';\n\n return function (email, deferred) {\n return $.getJSON(\n urlBuilder.build('newsletter/ajax/status'),\n {\n email: email\n }\n ).done(function (response) {\n if (response.errors) {\n deferred.reject();\n } else {\n deferred.resolve(response.subscribed);\n }\n }).fail(function () {\n deferred.reject();\n });\n };\n});\n","Magento_Review/js/process-reviews.js":"/**\n * Copyright \u00a9 Magento, Inc. All rights reserved.\n * See COPYING.txt for license details.\n */\n\ndefine([\n 'jquery',\n 'tabs',\n 'collapsible'\n], function ($) {\n 'use strict';\n\n /**\n * @param {String} url\n * @param {*} fromPages\n */\n function processReviews(url, fromPages) {\n $.ajax({\n url: url,\n cache: true,\n dataType: 'html',\n showLoader: false,\n loaderContext: $('.product.data.items')\n }).done(function (data) {\n $('#product-review-container').html(data).trigger('contentUpdated'); \n if($('.product.info.detailed').hasClass('vertical')) {\n $('#product-review-container').parent().parent().css(\"min-height\",$('#product-review-container').parent().outerHeight()+\"px\");\n }\n\n $('[data-role=\"product-review\"] .pages a').each(function (index, element) {\n $(element).on('click', function (event) { //eslint-disable-line max-nested-callbacks\n processReviews($(element).attr('href'), true);\n event.preventDefault();\n });\n });\n }).always(function () {\n if (fromPages == true) { //eslint-disable-line eqeqeq\n $('html, body').animate({\n scrollTop: $('#reviews').offset().top - 50\n }, 300);\n }\n });\n }\n\n return function (config) {\n var reviewTab = $(config.reviewsTabSelector),\n requiredReviewTabRole = 'tab';\n\n if (reviewTab.attr('role') === requiredReviewTabRole && reviewTab.hasClass('active')) {\n processReviews(config.productReviewUrl, location.hash === '#reviews');\n } else {\n reviewTab.one('beforeOpen', function () {\n processReviews(config.productReviewUrl);\n });\n }\n\n $(function () {\n $('.product-info-main .reviews-actions a').on('click', function (event) {\n var anchor, addReviewBlock;\n\n event.preventDefault();\n anchor = $(this).attr('href').replace(/^.*?(#|$)/, '');\n addReviewBlock = $('#' + anchor);\n\n if (addReviewBlock.length) {\n $('.product.data.items [data-role=\"content\"]').each(function (index) { //eslint-disable-line\n if (this.id == 'reviews') { //eslint-disable-line eqeqeq\n $('.product.data.items').tabs('activate', index);\n }\n });\n $('html, body').animate({\n scrollTop: addReviewBlock.offset().top - 50\n }, 300);\n }\n\n });\n });\n };\n});\n","Magento_Review/js/validate-review.js":"/**\n * Copyright \u00a9 Magento, Inc. All rights reserved.\n * See COPYING.txt for license details.\n */\n\ndefine([\n 'jquery',\n 'jquery/validate',\n 'mage/translate'\n], function ($) {\n 'use strict';\n\n $.validator.addMethod(\n 'rating-required', function (value) {\n return value !== undefined;\n }, $.mage.__('Please select one of each of the ratings above.'));\n});\n","Magento_Review/js/error-placement.js":"/**\n * Copyright \u00a9 Magento, Inc. All rights reserved.\n * See COPYING.txt for license details.\n */\n\ndefine([\n 'jquery',\n 'mage/mage'\n], function ($) {\n 'use strict';\n\n return function (config, element) {\n $(element).mage('validation', {\n /** @inheritdoc */\n errorPlacement: function (error, el) {\n\n if (el.parents('#product-review-table').length) {\n $('#product-review-table').siblings(this.errorElement + '.' + this.errorClass).remove();\n $('#product-review-table').after(error);\n } else {\n el.after(error);\n }\n }\n });\n };\n});\n","Magento_Review/js/submit-review.js":"/**\n * Copyright \u00a9 Magento, Inc. All rights reserved.\n * See COPYING.txt for license details.\n */\n\ndefine([\n 'jquery'\n], function ($) {\n 'use strict';\n\n return function (config, element) {\n $(element).on('submit', function () {\n if ($(this).valid()) {\n $(this).find('.submit').attr('disabled', true);\n }\n });\n };\n});\n","Magento_Review/js/view/review.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 'Magento_Customer/js/view/customer'\n], function (Component, customerData) {\n 'use strict';\n\n return Component.extend({\n /** @inheritdoc */\n initialize: function () {\n this._super();\n\n this.review = customerData.get('review').extend({\n disposableCustomerData: 'review'\n });\n },\n\n /**\n * @return {*}\n */\n nickname: function () {\n return this.review().nickname || customerData.get('customer')().firstname;\n }\n });\n});\n","Magento_Reports/js/recently-viewed.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], function ($) {\n 'use strict';\n\n $.widget('mage.recentlyViewedProducts', {\n options: {\n localStorageKey: 'recently-viewed-products',\n productBlock: '#widget_viewed_item',\n viewedContainer: 'ol'\n },\n\n /**\n * Bind events to the appropriate handlers.\n * @private\n */\n _create: function () {\n var productHtml = $(this.options.productBlock).html(),\n productSku = $(this.options.productBlock).data('sku'),\n products = JSON.parse(window.localStorage.getItem(this.options.localStorageKey)),\n productsLength, maximum, showed, index;\n\n if (products) {\n productsLength = products.sku.length;\n maximum = $(this.element).data('count');\n showed = 0;\n\n for (index = 0; index <= productsLength; index++) {\n if (products.sku[index] == productSku || showed >= maximum) { //eslint-disable-line\n products.sku.splice(index, 1);\n products.html.splice(index, 1);\n } else {\n $(this.element).find(this.options.viewedContainer).append(products.html[index]);\n $(this.element).show();\n showed++;\n }\n }\n $(this.element).find(this.options.productBlock).show();\n } else {\n products = {};\n products.sku = [];\n products.html = [];\n }\n products.sku.unshift(productSku);\n products.html.unshift(productHtml);\n window.localStorage.setItem(this.options.localStorageKey, JSON.stringify(products));\n }\n });\n\n return $.mage.recentlyViewedProducts;\n});\n","Magento_PageCache/js/page-cache.js":"/**\n * Copyright \u00a9 Magento, Inc. All rights reserved.\n * See COPYING.txt for license details.\n */\n\ndefine([\n 'jquery',\n 'domReady',\n 'consoleLogger',\n 'Magento_PageCache/js/form-key-provider',\n 'jquery-ui-modules/widget',\n 'mage/cookies'\n], function ($, domReady, consoleLogger, formKeyInit) {\n 'use strict';\n\n /**\n * Helper. Generate random string\n * TODO: Merge with mage/utils\n * @param {String} chars - list of symbols\n * @param {Number} length - length for need string\n * @returns {String}\n */\n function generateRandomString(chars, length) {\n var result = '';\n\n length = length > 0 ? length : 1;\n\n while (length--) {\n result += chars[Math.round(Math.random() * (chars.length - 1))];\n }\n\n return result;\n }\n\n /**\n * Nodes tree to flat list converter\n * @returns {Array}\n */\n $.fn.comments = function () {\n var elements = [],\n contents,\n elementContents;\n\n /**\n * @param {jQuery} element - Comment holder\n */\n (function lookup(element) {\n var iframeHostName;\n\n // prevent cross origin iframe content reading\n if ($(element).prop('tagName') === 'IFRAME') {\n iframeHostName = $('<a>').prop('href', $(element).prop('src'))\n .prop('hostname');\n\n if (window.location.hostname !== iframeHostName) {\n return [];\n }\n }\n\n /**\n * Rewrite jQuery contents().\n *\n * @param {jQuery} elem\n */\n contents = function (elem) {\n return $.map(elem, function (el) {\n try {\n return el.nodeName.toLowerCase() === 'iframe' ?\n el.contentDocument || (el.contentWindow ? el.contentWindow.document : []) :\n $.merge([], el.childNodes);\n } catch (e) {\n consoleLogger.error(e);\n\n return [];\n }\n });\n };\n\n elementContents = contents($(element));\n\n $.each(elementContents, function (index, el) {\n switch (el.nodeType) {\n case 1: // ELEMENT_NODE\n lookup(el);\n break;\n\n case 8: // COMMENT_NODE\n elements.push(el);\n break;\n\n case 9: // DOCUMENT_NODE\n lookup($(el).find('body'));\n break;\n }\n });\n })(this);\n\n return elements;\n };\n\n /**\n * FormKey Widget - this widget is generating from key, saves it to cookie and\n * @deprecated see Magento/PageCache/view/frontend/web/js/form-key-provider.js\n */\n $.widget('mage.formKey', {\n options: {\n inputSelector: 'input[name=\"form_key\"]',\n allowedCharacters: '0123456789abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ',\n length: 16\n },\n\n /**\n * Creates widget 'mage.formKey'\n * @private\n */\n _create: function () {\n var formKey = $.mage.cookies.get('form_key'),\n options = {\n secure: window.cookiesConfig ? window.cookiesConfig.secure : false\n };\n\n if (!formKey) {\n formKey = generateRandomString(this.options.allowedCharacters, this.options.length);\n $.mage.cookies.set('form_key', formKey, options);\n }\n $(this.options.inputSelector).val(formKey);\n }\n });\n\n /**\n * PageCache Widget\n * Handles additional ajax request for rendering user private content.\n */\n $.widget('mage.pageCache', {\n options: {\n url: '/',\n patternPlaceholderOpen: /^ BLOCK (.+) $/,\n patternPlaceholderClose: /^ \\/BLOCK (.+) $/,\n versionCookieName: 'private_content_version',\n handles: []\n },\n\n /**\n * Creates widget 'mage.pageCache'\n * @private\n */\n _create: function () {\n var placeholders,\n version = $.mage.cookies.get(this.options.versionCookieName);\n\n if (!version) {\n return;\n }\n placeholders = this._searchPlaceholders(this.element.comments());\n\n if (placeholders && placeholders.length) {\n this._ajax(placeholders, version);\n }\n },\n\n /**\n * Parse page for placeholders.\n * @param {Array} elements\n * @returns {Array}\n * @private\n */\n _searchPlaceholders: function (elements) {\n var placeholders = [],\n tmp = {},\n ii,\n len,\n el, matches, name;\n\n if (!(elements && elements.length)) {\n return placeholders;\n }\n\n for (ii = 0, len = elements.length; ii < len; ii++) {\n el = elements[ii];\n matches = this.options.patternPlaceholderOpen.exec(el.nodeValue);\n name = null;\n\n if (matches) {\n name = matches[1];\n tmp[name] = {\n name: name,\n openElement: el\n };\n } else {\n matches = this.options.patternPlaceholderClose.exec(el.nodeValue);\n\n if (matches) { //eslint-disable-line max-depth\n name = matches[1];\n\n if (tmp[name]) { //eslint-disable-line max-depth\n tmp[name].closeElement = el;\n placeholders.push(tmp[name]);\n delete tmp[name];\n }\n }\n }\n }\n\n return placeholders;\n },\n\n /**\n * Parse for page and replace placeholders\n * @param {Object} placeholder\n * @param {Object} html\n * @protected\n */\n _replacePlaceholder: function (placeholder, html) {\n var startReplacing = false,\n prevSibling = null,\n parent, contents, yy, len, element;\n\n if (!placeholder || !html) {\n return;\n }\n\n parent = $(placeholder.openElement).parent();\n contents = parent.contents();\n\n for (yy = 0, len = contents.length; yy < len; yy++) {\n element = contents[yy];\n\n if (element == placeholder.openElement) { //eslint-disable-line eqeqeq\n startReplacing = true;\n }\n\n if (startReplacing) {\n $(element).remove();\n } else if (element.nodeType != 8) { //eslint-disable-line eqeqeq\n //due to comment tag doesn't have siblings we try to find it manually\n prevSibling = element;\n }\n\n if (element == placeholder.closeElement) { //eslint-disable-line eqeqeq\n break;\n }\n }\n\n if (prevSibling) {\n $(prevSibling).after(html);\n } else {\n $(parent).prepend(html);\n }\n\n // trigger event to use mage-data-init attribute\n $(parent).trigger('contentUpdated');\n },\n\n /**\n * AJAX helper\n * @param {Object} placeholders\n * @param {String} version\n * @private\n */\n _ajax: function (placeholders, version) {\n var ii,\n data = {\n blocks: [],\n handles: this.options.handles,\n originalRequest: this.options.originalRequest,\n version: version\n };\n\n for (ii = 0; ii < placeholders.length; ii++) {\n data.blocks.push(placeholders[ii].name);\n }\n data.blocks = JSON.stringify(data.blocks.sort());\n data.handles = JSON.stringify(data.handles);\n data.originalRequest = JSON.stringify(data.originalRequest);\n $.ajax({\n url: this.options.url,\n data: data,\n type: 'GET',\n cache: true,\n dataType: 'json',\n context: this,\n\n /**\n * Response handler\n * @param {Object} response\n */\n success: function (response) {\n var placeholder, i;\n\n for (i = 0; i < placeholders.length; i++) {\n placeholder = placeholders[i];\n\n if (response.hasOwnProperty(placeholder.name)) {\n this._replacePlaceholder(placeholder, response[placeholder.name]);\n }\n }\n }\n });\n }\n });\n\n domReady(function () {\n formKeyInit();\n });\n\n return {\n 'pageCache': $.mage.pageCache,\n 'formKey': $.mage.formKey\n };\n});\n","Magento_PageCache/js/form-key-provider.js":"/**\n * Copyright \u00a9 Magento, Inc. All rights reserved.\n * See COPYING.txt for license details.\n */\ndefine(function () {\n 'use strict';\n\n return function (settings) {\n var formKey,\n inputElements,\n inputSelector = 'input[name=\"form_key\"]';\n\n /**\n * Set form_key cookie\n * @private\n */\n function setFormKeyCookie(value) {\n var expires,\n secure,\n date = new Date(),\n cookiesConfig = window.cookiesConfig || {},\n isSecure = !!cookiesConfig.secure,\n samesite = cookiesConfig.samesite || 'lax';\n\n date.setTime(date.getTime() + 86400000);\n expires = '; expires=' + date.toUTCString();\n secure = isSecure ? '; secure' : '';\n samesite = '; samesite=' + samesite;\n\n document.cookie = 'form_key=' + (value || '') + expires + secure + '; path=/' + samesite;\n }\n\n /**\n * Retrieves form key from cookie\n * @private\n */\n function getFormKeyCookie() {\n var cookie,\n i,\n nameEQ = 'form_key=',\n cookieArr = document.cookie.split(';');\n\n for (i = 0; i < cookieArr.length; i++) {\n cookie = cookieArr[i];\n\n while (cookie.charAt(0) === ' ') {\n cookie = cookie.substring(1, cookie.length);\n }\n\n if (cookie.indexOf(nameEQ) === 0) {\n return cookie.substring(nameEQ.length, cookie.length);\n }\n }\n\n return null;\n }\n\n /**\n * Get form key from UI input hidden\n * @private\n */\n function getFormKeyFromUI() {\n return document.querySelector(inputSelector).value;\n }\n\n /**\n * Generate form key string\n * @private\n */\n function generateFormKeyString() {\n var result = '',\n length = 16,\n chars = '0123456789abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ';\n\n while (length--) {\n result += chars[Math.round(Math.random() * (chars.length - 1))];\n }\n\n return result;\n }\n\n /**\n * Init form_key inputs with value\n * @private\n */\n function initFormKey() {\n formKey = getFormKeyCookie();\n\n if (settings && settings.isPaginationCacheEnabled && !formKey) {\n formKey = getFormKeyFromUI();\n setFormKeyCookie(formKey);\n }\n\n if (!formKey) {\n formKey = generateFormKeyString();\n setFormKeyCookie(formKey);\n }\n inputElements = document.querySelectorAll(inputSelector);\n\n if (inputElements.length) {\n Array.prototype.forEach.call(inputElements, function (element) {\n element.setAttribute('value', formKey);\n });\n }\n }\n\n initFormKey();\n };\n});\n","Magento_ConfigurableProduct/js/configurable.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 'underscore',\n 'mage/template',\n 'mage/translate',\n 'priceUtils',\n 'priceBox',\n 'jquery-ui-modules/widget',\n 'jquery/jquery.parsequery',\n 'fotoramaVideoEvents'\n], function ($, _, mageTemplate, $t, priceUtils) {\n 'use strict';\n\n $.widget('mage.configurable', {\n options: {\n superSelector: '.super-attribute-select',\n selectSimpleProduct: '[name=\"selected_configurable_option\"]',\n priceHolderSelector: '.price-box',\n spConfig: {},\n state: {},\n priceFormat: {},\n optionTemplate: '<%- data.label %>' +\n '<% if (typeof data.finalPrice.value !== \"undefined\") { %>' +\n ' <%- data.finalPrice.formatted %>' +\n '<% } %>',\n mediaGallerySelector: '[data-gallery-role=gallery-placeholder]',\n mediaGalleryInitial: null,\n slyOldPriceSelector: '.sly-old-price',\n normalPriceLabelSelector: '.product-info-main .normal-price .price-label',\n\n /**\n * Defines the mechanism of how images of a gallery should be\n * updated when user switches between configurations of a product.\n *\n * As for now value of this option can be either 'replace' or 'prepend'.\n *\n * @type {String}\n */\n gallerySwitchStrategy: 'replace',\n tierPriceTemplateSelector: '#tier-prices-template',\n tierPriceBlockSelector: '[data-role=\"tier-price-block\"]',\n tierPriceTemplate: '',\n selectorProduct: '.product-info-main',\n selectorProductPrice: '[data-role=priceBox]',\n qtyInfo: '#qty'\n },\n\n /**\n * Creates widget\n * @private\n */\n _create: function () {\n // Initial setting of various option values\n this._initializeOptions();\n\n // Override defaults with URL query parameters and/or inputs values\n this._overrideDefaults();\n\n // Change events to check select reloads\n this._setupChangeEvents();\n\n // Fill state\n this._fillState();\n\n // Setup child and prev/next settings\n this._setChildSettings();\n\n // Setup/configure values to inputs\n this._configureForValues();\n\n $(this.element).trigger('configurable.initialized');\n $(this.options.qtyInfo).on('input', this._reloadPrice.bind(this));\n },\n\n /**\n * Initialize tax configuration, initial settings, and options values.\n * @private\n */\n _initializeOptions: function () {\n var options = this.options,\n gallery = $(options.mediaGallerySelector),\n priceBoxOptions = $(this.options.priceHolderSelector).priceBox('option').priceConfig || null;\n\n if (priceBoxOptions && priceBoxOptions.optionTemplate) {\n options.optionTemplate = priceBoxOptions.optionTemplate;\n }\n\n if (priceBoxOptions && priceBoxOptions.priceFormat) {\n options.priceFormat = priceBoxOptions.priceFormat;\n }\n options.optionTemplate = mageTemplate(options.optionTemplate);\n options.tierPriceTemplate = $(this.options.tierPriceTemplateSelector).html();\n\n options.settings = options.spConfig.containerId ?\n $(options.spConfig.containerId).find(options.superSelector) :\n $(options.superSelector);\n\n options.values = options.spConfig.defaultValues || {};\n options.parentImage = $('[data-role=base-image-container] img').attr('src');\n\n this.inputSimpleProduct = this.element.find(options.selectSimpleProduct);\n\n gallery.data('gallery') ?\n this._onGalleryLoaded(gallery) :\n gallery.on('gallery:loaded', this._onGalleryLoaded.bind(this, gallery));\n\n },\n\n /**\n * Override default options values settings with either URL query parameters or\n * initialized inputs values.\n * @private\n */\n _overrideDefaults: function () {\n var hashIndex = window.location.href.indexOf('#');\n\n if (hashIndex !== -1) {\n this._parseQueryParams(window.location.href.substr(hashIndex + 1));\n }\n\n if (this.options.spConfig.inputsInitialized) {\n this._setValuesByAttribute();\n }\n\n this._setInitialOptionsLabels();\n },\n\n /**\n * Parse query parameters from a query string and set options values based on the\n * key value pairs of the parameters.\n * @param {*} queryString - URL query string containing query parameters.\n * @private\n */\n _parseQueryParams: function (queryString) {\n var queryParams = $.parseQuery({\n query: queryString\n });\n\n $.each(queryParams, $.proxy(function (key, value) {\n if (this.options.spConfig.attributes[key] !== undefined &&\n _.find(this.options.spConfig.attributes[key].options, function (element) {\n return element.id === value;\n })) {\n this.options.values[key] = value;\n }\n }, this));\n },\n\n /**\n * Override default options values with values based on each element's attribute\n * identifier.\n * @private\n */\n _setValuesByAttribute: function () {\n this.options.values = {};\n $.each(this.options.settings, $.proxy(function (index, element) {\n var attributeId;\n\n if (element.value) {\n attributeId = element.id.replace(/[a-z]*/, '');\n\n if (this.options.spConfig.attributes[attributeId] !== undefined &&\n _.find(this.options.spConfig.attributes[attributeId].options, function (optionElement) {\n return optionElement.id === element.value;\n })) {\n this.options.values[attributeId] = element.value;\n }\n }\n }, this));\n },\n\n /**\n * Set additional field with initial label to be used when switching between options with different prices.\n * @private\n */\n _setInitialOptionsLabels: function () {\n $.each(this.options.spConfig.attributes, $.proxy(function (index, element) {\n $.each(element.options, $.proxy(function (optIndex, optElement) {\n this.options.spConfig.attributes[index].options[optIndex].initialLabel = optElement.label;\n }, this));\n }, this));\n },\n\n /**\n * Set up .on('change') events for each option element to configure the option.\n * @private\n */\n _setupChangeEvents: function () {\n $.each(this.options.settings, $.proxy(function (index, element) {\n $(element).on('change', this, this._configure);\n }, this));\n },\n\n /**\n * Iterate through the option settings and set each option's element configuration,\n * attribute identifier. Set the state based on the attribute identifier.\n * @private\n */\n _fillState: function () {\n $.each(this.options.settings, $.proxy(function (index, element) {\n var attributeId = element.id.replace(/[a-z]*/, '');\n\n if (attributeId && this.options.spConfig.attributes[attributeId]) {\n element.config = this.options.spConfig.attributes[attributeId];\n element.attributeId = attributeId;\n this.options.state[attributeId] = false;\n }\n }, this));\n },\n\n /**\n * Set each option's child settings, and next/prev option setting. Fill (initialize)\n * an option's list of selections as needed or disable an option's setting.\n * @private\n */\n _setChildSettings: function () {\n var childSettings = [],\n settings = this.options.settings,\n index = settings.length,\n option;\n\n while (index--) {\n option = settings[index];\n\n if (index) {\n option.disabled = true;\n } else {\n this._fillSelect(option);\n }\n\n _.extend(option, {\n childSettings: childSettings.slice(),\n prevSetting: settings[index - 1],\n nextSetting: settings[index + 1]\n });\n\n childSettings.push(option);\n }\n },\n\n /**\n * Setup for all configurable option settings. Set the value of the option and configure\n * the option, which sets its state, and initializes the option's choices, etc.\n * @private\n */\n _configureForValues: function () {\n if (this.options.values) {\n this.options.settings.each($.proxy(function (index, element) {\n var attributeId = element.attributeId;\n\n element.value = this.options.values[attributeId] || '';\n this._configureElement(element);\n }, this));\n }\n },\n\n /**\n * Event handler for configuring an option.\n * @private\n * @param {Object} event - Event triggered to configure an option.\n */\n _configure: function (event) {\n event.data._configureElement(this);\n },\n\n /**\n * Configure an option, initializing it's state and enabling related options, which\n * populates the related option's selection and resets child option selections.\n * @private\n * @param {*} element - The element associated with a configurable option.\n */\n _configureElement: function (element) {\n this.simpleProduct = this._getSimpleProductId(element);\n\n if (element.value) {\n this.options.state[element.config.id] = element.value;\n\n if (element.nextSetting) {\n element.nextSetting.disabled = false;\n this._fillSelect(element.nextSetting);\n this._resetChildren(element.nextSetting);\n } else {\n if (!!document.documentMode) { //eslint-disable-line\n this.inputSimpleProduct.val(element.options[element.selectedIndex].config.allowedProducts[0]);\n } else {\n this.inputSimpleProduct.val(element.selectedOptions[0].config.allowedProducts[0]);\n }\n }\n } else {\n this._resetChildren(element);\n }\n\n this._reloadPrice();\n this._displayRegularPriceBlock(this.simpleProduct);\n this._displayTierPriceBlock(this.simpleProduct);\n this._displayNormalPriceLabel();\n this._changeProductImage();\n },\n\n /**\n * Change displayed product image according to chosen options of configurable product\n *\n * @private\n */\n _changeProductImage: function () {\n var images,\n initialImages = this.options.mediaGalleryInitial,\n gallery = $(this.options.mediaGallerySelector).data('gallery');\n\n if (_.isUndefined(gallery)) {\n $(this.options.mediaGallerySelector).on('gallery:loaded', function () {\n this._changeProductImage();\n }.bind(this));\n\n return;\n }\n\n images = this.options.spConfig.images[this.simpleProduct];\n\n if (images) {\n images = this._sortImages(images);\n\n if (this.options.gallerySwitchStrategy === 'prepend') {\n images = images.concat(initialImages);\n }\n\n images = $.extend(true, [], images);\n images = this._setImageIndex(images);\n\n gallery.updateData(images);\n this._addFotoramaVideoEvents(false);\n } else {\n gallery.updateData(initialImages);\n this._addFotoramaVideoEvents(true);\n }\n },\n\n /**\n * Add video events\n *\n * @param {Boolean} isInitial\n * @private\n */\n _addFotoramaVideoEvents: function (isInitial) {\n if (_.isUndefined($.mage.AddFotoramaVideoEvents)) {\n return;\n }\n\n if (isInitial) {\n $(this.options.mediaGallerySelector).AddFotoramaVideoEvents();\n\n return;\n }\n\n $(this.options.mediaGallerySelector).AddFotoramaVideoEvents({\n selectedOption: this.simpleProduct,\n dataMergeStrategy: this.options.gallerySwitchStrategy\n });\n },\n\n /**\n * Sorting images array\n *\n * @private\n */\n _sortImages: function (images) {\n return _.sortBy(images, function (image) {\n return image.position;\n });\n },\n\n /**\n * Set correct indexes for image set.\n *\n * @param {Array} images\n * @private\n */\n _setImageIndex: function (images) {\n var length = images.length,\n i;\n\n for (i = 0; length > i; i++) {\n images[i].i = i + 1;\n }\n\n return images;\n },\n\n /**\n * For a given option element, reset all of its selectable options. Clear any selected\n * index, disable the option choice, and reset the option's state if necessary.\n * @private\n * @param {*} element - The element associated with a configurable option.\n */\n _resetChildren: function (element) {\n if (element.childSettings) {\n _.each(element.childSettings, function (set) {\n set.selectedIndex = 0;\n set.disabled = true;\n });\n\n if (element.config) {\n this.options.state[element.config.id] = false;\n }\n }\n },\n\n /**\n * Populates an option's selectable choices.\n * @private\n * @param {*} element - Element associated with a configurable option.\n */\n _fillSelect: function (element) {\n var attributeId = element.id.replace(/[a-z]*/, ''),\n options = this._getAttributeOptions(attributeId),\n prevConfig,\n index = 1,\n allowedProducts,\n allowedProductsByOption,\n allowedProductsAll,\n i,\n j,\n finalPrice = parseFloat(this.options.spConfig.prices.finalPrice.amount),\n optionFinalPrice,\n optionPriceDiff,\n optionPrices = this.options.spConfig.optionPrices,\n allowedOptions = [],\n indexKey,\n allowedProductMinPrice,\n allowedProductsAllMinPrice,\n canDisplayOutOfStockProducts = false,\n filteredSalableProducts;\n\n this._clearSelect(element);\n element.options[0] = new Option('', '');\n element.options[0].innerHTML = this.options.spConfig.chooseText;\n prevConfig = false;\n\n if (element.prevSetting) {\n prevConfig = element.prevSetting.options[element.prevSetting.selectedIndex];\n }\n\n if (options) {\n for (indexKey in this.options.spConfig.index) {\n /* eslint-disable max-depth */\n if (this.options.spConfig.index.hasOwnProperty(indexKey)) {\n allowedOptions = allowedOptions.concat(_.values(this.options.spConfig.index[indexKey]));\n }\n }\n\n if (prevConfig) {\n allowedProductsByOption = {};\n allowedProductsAll = [];\n\n for (i = 0; i < options.length; i++) {\n /* eslint-disable max-depth */\n for (j = 0; j < options[i].products.length; j++) {\n // prevConfig.config can be undefined\n if (prevConfig.config &&\n prevConfig.config.allowedProducts &&\n prevConfig.config.allowedProducts.indexOf(options[i].products[j]) > -1) {\n if (!allowedProductsByOption[i]) {\n allowedProductsByOption[i] = [];\n }\n allowedProductsByOption[i].push(options[i].products[j]);\n allowedProductsAll.push(options[i].products[j]);\n }\n }\n }\n\n if (typeof allowedProductsAll[0] !== 'undefined' &&\n typeof optionPrices[allowedProductsAll[0]] !== 'undefined') {\n allowedProductsAllMinPrice = this._getAllowedProductWithMinPrice(allowedProductsAll);\n finalPrice = parseFloat(optionPrices[allowedProductsAllMinPrice].finalPrice.amount);\n }\n }\n\n for (i = 0; i < options.length; i++) {\n if (prevConfig && typeof allowedProductsByOption[i] === 'undefined') {\n continue; //jscs:ignore disallowKeywords\n }\n\n allowedProducts = prevConfig ? allowedProductsByOption[i] : options[i].products.slice(0);\n optionPriceDiff = 0;\n\n if (typeof allowedProducts[0] !== 'undefined' &&\n typeof optionPrices[allowedProducts[0]] !== 'undefined') {\n allowedProductMinPrice = this._getAllowedProductWithMinPrice(allowedProducts);\n optionFinalPrice = parseFloat(optionPrices[allowedProductMinPrice].finalPrice.amount);\n optionPriceDiff = optionFinalPrice - finalPrice;\n options[i].label = options[i].initialLabel;\n\n if (optionPriceDiff !== 0) {\n options[i].label += ' ' + priceUtils.formatPriceLocale(\n optionPriceDiff,\n this.options.priceFormat,\n true\n );\n }\n }\n\n if (allowedProducts.length > 0 || _.include(allowedOptions, options[i].id)) {\n options[i].allowedProducts = allowedProducts;\n element.options[index] = new Option(this._getOptionLabel(options[i]), options[i].id);\n\n if (this.options.spConfig.canDisplayShowOutOfStockStatus) {\n filteredSalableProducts = $(this.options.spConfig.salable[attributeId][options[i].id]).\n filter(options[i].allowedProducts);\n canDisplayOutOfStockProducts = filteredSalableProducts.length === 0;\n }\n\n if (typeof options[i].price !== 'undefined') {\n element.options[index].setAttribute('price', options[i].price);\n }\n\n if (allowedProducts.length === 0 || canDisplayOutOfStockProducts) {\n element.options[index].disabled = true;\n }\n\n element.options[index].config = options[i];\n index++;\n }\n\n /* eslint-enable max-depth */\n }\n }\n },\n\n /**\n * Generate the label associated with a configurable option. This includes the option's\n * label or value and the option's price.\n * @private\n * @param {*} option - A single choice among a group of choices for a configurable option.\n * @return {String} The option label with option value and price (e.g. Black +1.99)\n */\n _getOptionLabel: function (option) {\n return option.label;\n },\n\n /**\n * Removes an option's selections.\n * @private\n * @param {*} element - The element associated with a configurable option.\n */\n _clearSelect: function (element) {\n var i;\n\n for (i = element.options.length - 1; i >= 0; i--) {\n element.remove(i);\n }\n },\n\n /**\n * Retrieve the attribute options associated with a specific attribute Id.\n * @private\n * @param {Number} attributeId - The id of the attribute whose configurable options are sought.\n * @return {Object} Object containing the attribute options.\n */\n _getAttributeOptions: function (attributeId) {\n if (this.options.spConfig.attributes[attributeId]) {\n return this.options.spConfig.attributes[attributeId].options;\n }\n },\n\n /**\n * Reload the price of the configurable product incorporating the prices of all of the\n * configurable product's option selections.\n */\n _reloadPrice: function () {\n $(this.options.priceHolderSelector).trigger('updatePrice', this._getPrices());\n },\n\n /**\n * Get product various prices\n * @returns {{}}\n * @private\n */\n _getPrices: function () {\n var prices = {},\n elements = _.toArray(this.options.settings),\n allowedProduct;\n\n _.each(elements, function (element) {\n var selected = element.options[element.selectedIndex],\n config = selected && selected.config,\n priceValue = this._calculatePrice({});\n\n if (config && config.allowedProducts.length === 1) {\n priceValue = this._calculatePrice(config);\n } else if (element.value) {\n allowedProduct = this._getAllowedProductWithMinPrice(config.allowedProducts);\n priceValue = this._calculatePrice({\n 'allowedProducts': [\n allowedProduct\n ]\n });\n }\n\n if (!_.isEmpty(priceValue)) {\n prices.prices = priceValue;\n }\n }, this);\n\n return prices;\n },\n\n /**\n * Get product with minimum price from selected options.\n *\n * @param {Array} allowedProducts\n * @returns {String}\n * @private\n */\n _getAllowedProductWithMinPrice: function (allowedProducts) {\n var optionPrices = this.options.spConfig.optionPrices,\n product = {},\n optionMinPrice, optionFinalPrice;\n\n _.each(allowedProducts, function (allowedProduct) {\n optionFinalPrice = parseFloat(optionPrices[allowedProduct].finalPrice.amount);\n\n if (_.isEmpty(product) || optionFinalPrice < optionMinPrice) {\n optionMinPrice = optionFinalPrice;\n product = allowedProduct;\n }\n }, this);\n\n return product;\n },\n\n /**\n * Returns prices for configured products\n *\n * @param {*} config - Products configuration\n * @returns {*}\n * @private\n */\n _calculatePrice: function (config) {\n var displayPrices = $(this.options.priceHolderSelector).priceBox('option').prices,\n newPrices = this.options.spConfig.optionPrices[_.first(config.allowedProducts)] || {};\n\n _.each(displayPrices, function (price, code) {\n displayPrices[code].amount = newPrices[code] ? newPrices[code].amount - displayPrices[code].amount : 0;\n });\n\n return displayPrices;\n },\n\n /**\n * Returns Simple product Id\n * depending on current selected option.\n *\n * @private\n * @param {HTMLElement} element\n * @returns {String|undefined}\n */\n _getSimpleProductId: function (element) {\n // TODO: Rewrite algorithm. It should return ID of\n // simple product based on selected options.\n var allOptions = element.config.options,\n value = element.value,\n config;\n\n config = _.filter(allOptions, function (option) {\n return option.id === value;\n });\n config = _.first(config);\n\n return _.isEmpty(config) ?\n undefined :\n _.first(config.allowedProducts);\n\n },\n\n /**\n * Show or hide regular price block\n *\n * @param {*} optionId\n * @private\n */\n _displayRegularPriceBlock: function (optionId) {\n var shouldBeShown = true,\n $priceBox = this.element.parents(this.options.selectorProduct)\n .find(this.options.selectorProductPrice);\n\n _.each(this.options.settings, function (element) {\n if (element.value === '') {\n shouldBeShown = false;\n }\n });\n\n if (shouldBeShown &&\n this.options.spConfig.optionPrices[optionId].oldPrice.amount !==\n this.options.spConfig.optionPrices[optionId].finalPrice.amount\n ) {\n $(this.options.slyOldPriceSelector).show();\n } else {\n $(this.options.slyOldPriceSelector).hide();\n }\n\n $(document).trigger('updateMsrpPriceBlock',\n [\n optionId,\n this.options.spConfig.optionPrices,\n $priceBox\n ]\n );\n },\n\n /**\n * Show or hide normal price label\n *\n * @private\n */\n _displayNormalPriceLabel: function () {\n var shouldBeShown = false;\n\n _.each(this.options.settings, function (element) {\n if (element.value === '') {\n shouldBeShown = true;\n }\n });\n\n if (shouldBeShown) {\n $(this.options.normalPriceLabelSelector).show();\n } else {\n $(this.options.normalPriceLabelSelector).hide();\n }\n },\n\n /**\n * Callback which fired after gallery gets initialized.\n *\n * @param {HTMLElement} element - DOM element associated with gallery.\n */\n _onGalleryLoaded: function (element) {\n var galleryObject = element.data('gallery');\n\n this.options.mediaGalleryInitial = galleryObject.returnCurrentImages();\n },\n\n /**\n * Show or hide tier price block\n *\n * @param {*} optionId\n * @private\n */\n _displayTierPriceBlock: function (optionId) {\n var tierPrices = typeof optionId != 'undefined' && this.options.spConfig.optionPrices[optionId].tierPrices;\n\n if (_.isArray(tierPrices) && tierPrices.length > 0) {\n\n if (this.options.tierPriceTemplate) {\n $(this.options.tierPriceBlockSelector).html(\n mageTemplate(this.options.tierPriceTemplate, {\n 'tierPrices': tierPrices,\n '$t': $t,\n 'currencyFormat': this.options.spConfig.currencyFormat,\n 'priceUtils': priceUtils\n })\n ).show();\n }\n } else {\n $(this.options.tierPriceBlockSelector).hide();\n }\n }\n });\n\n return $.mage.configurable;\n});\n","Magento_ConfigurableProduct/js/catalog-add-to-cart.js":"/**\n * Copyright \u00a9 Magento, Inc. All rights reserved.\n * See COPYING.txt for license details.\n */\nrequire([\n 'jquery'\n], function ($) {\n 'use strict';\n\n /**\n * Add selected configurable attributes to redirect url\n *\n * @see Magento_Catalog/js/catalog-add-to-cart\n */\n $('body').on('catalogCategoryAddToCartRedirect', function (event, data) {\n $(data.form).find('select[name*=\"super\"]').each(function (index, item) {\n data.redirectParameters.push(item.config.id + '=' + $(item).val());\n });\n });\n});\n","Magento_ConfigurableProduct/js/catalog-add-to-cart-mixin.js":"/**\n * Copyright \u00a9 Magento, Inc. All rights reserved.\n * See COPYING.txt for license details.\n */\ndefine([\n 'underscore',\n 'jquery',\n 'Magento_ConfigurableProduct/js/product/view/product-info-resolver'\n], function (_, $, productInfoResolver) {\n 'use strict';\n\n return function (widget) {\n\n $.widget('mage.catalogAddToCart', widget, {\n /**\n * @param {jQuery} form\n */\n ajaxSubmit: function (form) {\n var isConfigurable = !!_.find(form.serializeArray(), function (item) {\n return item.name.indexOf('super_attribute') !== -1;\n });\n\n if (isConfigurable) {\n this.options.productInfoResolver = productInfoResolver;\n }\n\n return this._super(form);\n }\n });\n\n return $.mage.catalogAddToCart;\n };\n});\n","Magento_ConfigurableProduct/js/configurable-customer-data.js":"require([\n 'jquery',\n 'Magento_ConfigurableProduct/js/options-updater'\n], function ($, Updater) {\n 'use strict';\n\n var selectors = {\n formSelector: '#product_addtocart_form'\n },\n configurableWidgetName = 'mageConfigurable',\n widgetInitEvent = 'configurable.initialized',\n\n /**\n * Sets all configurable attribute's selected values\n */\n updateConfigurableOptions = function () {\n var configurableWidget = $(selectors.formSelector).data(configurableWidgetName);\n\n if (!configurableWidget) {\n return;\n }\n configurableWidget.options.values = this.productOptions || {};\n configurableWidget._configureForValues();\n },\n updater = new Updater(widgetInitEvent, updateConfigurableOptions);\n\n updater.listen();\n});\n","Magento_ConfigurableProduct/js/options-updater.js":"define([\n 'jquery',\n 'underscore',\n 'Magento_Customer/js/customer-data',\n 'domReady!'\n], function ($, _, customerData) {\n 'use strict';\n\n var selectors = {\n formSelector: '#product_addtocart_form',\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\n /**\n * set productOptions according to cart data from customer-data\n *\n * @param {Object} data - cart data from customer-data\n * @returns {Boolean} - whether the new options differ from previous\n */\n setProductOptions = function (data) {\n var changedProductOptions;\n\n if (!(data && data.items && data.items.length && productId)) {\n return false;\n }\n changedProductOptions = _.find(data.items, function (item) {\n if (item['item_id'] === itemId) {\n return item['product_id'] === productId;\n }\n });\n changedProductOptions = changedProductOptions && changedProductOptions.options &&\n changedProductOptions.options.reduce(function (obj, val) {\n obj[val['option_id']] = val['option_value'];\n\n return obj;\n }, {});\n\n if (JSON.stringify(this.productOptions || {}) === JSON.stringify(changedProductOptions || {})) {\n return false;\n }\n\n this.productOptions = changedProductOptions;\n\n return true;\n },\n\n /**\n * Listens to update of cart data or options initialization and update selected option according to customer data\n *\n */\n listen = function () {\n cartData.subscribe(function (updateCartData) {\n if (this.setProductOptions(updateCartData)) {\n this.updateOptions();\n }\n }.bind(this));\n $(selectors.formSelector).on(this.eventName, function () {\n this.setProductOptions(cartData());\n this.updateOptions();\n }.bind(this));\n },\n\n /**\n * Updater constructor function\n *\n */\n Updater = function (eventName, updateOptionsCallback) {\n if (this instanceof Updater) {\n this.eventName = eventName;\n this.updateOptions = updateOptionsCallback;\n this.productOptions = {};\n }\n };\n\n Updater.prototype.setProductOptions = setProductOptions;\n Updater.prototype.listen = listen;\n\n return Updater;\n});\n","Magento_ConfigurableProduct/js/product/view/product-info-resolver.js":"/**\n * Copyright \u00a9 Magento, Inc. All rights reserved.\n * See COPYING.txt for license details.\n */\ndefine([\n 'underscore',\n 'Magento_Catalog/js/product/view/product-info'\n], function (_, productInfo) {\n 'use strict';\n\n /**\n * Returns info about configurable products in form.\n *\n * @param {jQuery} $form\n * @return {Array}\n */\n return function ($form) {\n var optionValues = [],\n product = _.findWhere($form.serializeArray(), {\n name: 'product'\n }),\n productId;\n\n if (!_.isUndefined(product)) {\n productId = product.value;\n _.each($form.serializeArray(), function (item) {\n if (item.name.indexOf('super_attribute') !== -1) {\n optionValues.push(item.value);\n }\n });\n optionValues.sort();\n productInfo().push(\n {\n 'id': productId,\n 'optionValues': optionValues\n }\n );\n }\n\n return _.uniq(productInfo(), function (item) {\n var optionValuesStr = item.optionValues ? item.optionValues.join() : '';\n\n return item.id + optionValuesStr;\n });\n };\n});\n\n","Magento_CatalogSearch/js/search-terms-log.js":"/**\n * Copyright \u00a9 Magento, Inc. All rights reserved.\n * See COPYING.txt for license details.\n */\n\ndefine([\n 'jquery',\n 'mageUtils'\n], function ($, utils) {\n 'use strict';\n\n return function (data) {\n $.ajax({\n method: 'GET',\n url: data.url,\n data: {\n 'q': utils.getUrlParameters(window.location.href).q\n }\n });\n };\n});\n","Magento_Shipping/js/view/checkout/shipping/shipping-policy.js":"/**\n * Copyright \u00a9 Magento, Inc. All rights reserved.\n * See COPYING.txt for license details.\n */\n\ndefine([\n 'uiComponent',\n 'Magento_Shipping/js/model/config'\n\n], function (Component, config) {\n 'use strict';\n\n return Component.extend({\n defaults: {\n template: 'Magento_Shipping/checkout/shipping/shipping-policy'\n },\n config: config()\n });\n});\n","Magento_Shipping/js/model/config.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 () {\n return window.checkoutConfig.shippingPolicy;\n };\n});\n","Magento_Search/js/form-mini.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 'underscore',\n 'mage/template',\n 'matchMedia',\n 'jquery-ui-modules/widget',\n 'jquery-ui-modules/core',\n 'mage/translate'\n], function ($, _, mageTemplate, mediaCheck) {\n 'use strict';\n\n /**\n * Check whether the incoming string is not empty or if doesn't consist of spaces.\n *\n * @param {String} value - Value to check.\n * @returns {Boolean}\n */\n function isEmpty(value) {\n return value.length === 0 || value == null || /^\\s+$/.test(value);\n }\n\n $.widget('mage.quickSearch', {\n options: {\n autocomplete: 'off',\n minSearchLength: 3,\n responseFieldElements: 'ul li',\n selectClass: 'selected',\n template:\n '<li class=\"<%- data.row_class %>\" id=\"qs-option-<%- data.index %>\" role=\"option\">' +\n '<span class=\"qs-option-name\">' +\n ' <%- data.title %>' +\n '</span>' +\n '<span aria-hidden=\"true\" class=\"amount\">' +\n '<%- data.num_results %>' +\n '</span>' +\n '</li>',\n submitBtn: 'button[type=\"submit\"]',\n searchLabel: '[data-role=minisearch-label]',\n isExpandable: null,\n suggestionDelay: 300\n },\n\n /** @inheritdoc */\n _create: function () {\n this.responseList = {\n indexList: null,\n selected: null\n };\n this.autoComplete = $(this.options.destinationSelector);\n this.searchForm = $(this.options.formSelector);\n this.submitBtn = this.searchForm.find(this.options.submitBtn)[0];\n this.searchLabel = this.searchForm.find(this.options.searchLabel);\n this.isExpandable = this.options.isExpandable;\n\n _.bindAll(this, '_onKeyDown', '_onPropertyChange', '_onSubmit');\n\n this.submitBtn.disabled = true;\n\n this.element.attr('autocomplete', this.options.autocomplete);\n\n mediaCheck({\n media: '(max-width: 768px)',\n entry: function () {\n this.isExpandable = true;\n }.bind(this),\n exit: function () {\n this.isExpandable = true;\n }.bind(this)\n });\n\n this.searchLabel.on('click', function (e) {\n // allow input to lose its' focus when clicking on label\n if (this.isExpandable && this.isActive()) {\n e.preventDefault();\n }\n }.bind(this));\n\n this.element.on('blur', $.proxy(function () {\n if (!this.searchLabel.hasClass('active')) {\n return;\n }\n\n setTimeout($.proxy(function () {\n if (this.autoComplete.is(':hidden')) {\n this.setActiveState(false);\n } else {\n this.element.trigger('focus');\n }\n this.autoComplete.hide();\n this._updateAriaHasPopup(false);\n }, this), 250);\n }, this));\n\n if (this.element.get(0) === document.activeElement) {\n this.setActiveState(true);\n }\n\n this.element.on('focus', this.setActiveState.bind(this, true));\n this.element.on('keydown', this._onKeyDown);\n // Prevent spamming the server with requests by waiting till the user has stopped typing for period of time\n this.element.on('input propertychange', _.debounce(this._onPropertyChange, this.options.suggestionDelay));\n\n this.searchForm.on('submit', $.proxy(function (e) {\n this._onSubmit(e);\n this._updateAriaHasPopup(false);\n }, this));\n },\n\n /**\n * Checks if search field is active.\n *\n * @returns {Boolean}\n */\n isActive: function () {\n return this.searchLabel.hasClass('active');\n },\n\n /**\n * Sets state of the search field to provided value.\n *\n * @param {Boolean} isActive\n */\n setActiveState: function (isActive) {\n var searchValue;\n\n this.searchForm.toggleClass('active', isActive);\n this.searchLabel.toggleClass('active', isActive);\n\n if (this.isExpandable) {\n this.element.attr('aria-expanded', isActive);\n searchValue = this.element.val();\n this.element.val('');\n this.element.val(searchValue);\n }\n },\n\n /**\n * @private\n * @return {Element} The first element in the suggestion list.\n */\n _getFirstVisibleElement: function () {\n return this.responseList.indexList ? this.responseList.indexList.first() : false;\n },\n\n /**\n * @private\n * @return {Element} The last element in the suggestion list.\n */\n _getLastElement: function () {\n return this.responseList.indexList ? this.responseList.indexList.last() : false;\n },\n\n /**\n * @private\n * @param {Boolean} show - Set attribute aria-haspopup to \"true/false\" for element.\n */\n _updateAriaHasPopup: function (show) {\n if (show) {\n this.element.attr('aria-haspopup', 'true');\n } else {\n this.element.attr('aria-haspopup', 'false');\n }\n },\n\n /**\n * Clears the item selected from the suggestion list and resets the suggestion list.\n * @private\n * @param {Boolean} all - Controls whether to clear the suggestion list.\n */\n _resetResponseList: function (all) {\n this.responseList.selected = null;\n\n if (all === true) {\n this.responseList.indexList = null;\n }\n },\n\n /**\n * Executes when the search box is submitted. Sets the search input field to the\n * value of the selected item.\n * @private\n * @param {Event} e - The submit event\n */\n _onSubmit: function (e) {\n var value = this.element.val();\n\n if (isEmpty(value)) {\n e.preventDefault();\n }\n\n if (this.responseList.selected) {\n this.element.val(this.responseList.selected.find('.qs-option-name').text());\n }\n },\n\n /**\n * Executes when keys are pressed in the search input field. Performs specific actions\n * depending on which keys are pressed.\n * @private\n * @param {Event} e - The key down event\n * @return {Boolean} Default return type for any unhandled keys\n */\n _onKeyDown: function (e) {\n var keyCode = e.keyCode || e.which;\n\n switch (keyCode) {\n case $.ui.keyCode.HOME:\n if (this._getFirstVisibleElement()) {\n this._getFirstVisibleElement().addClass(this.options.selectClass);\n this.responseList.selected = this._getFirstVisibleElement();\n }\n break;\n\n case $.ui.keyCode.END:\n if (this._getLastElement()) {\n this._getLastElement().addClass(this.options.selectClass);\n this.responseList.selected = this._getLastElement();\n }\n break;\n\n case $.ui.keyCode.ESCAPE:\n this._resetResponseList(true);\n this.autoComplete.hide();\n break;\n\n case $.ui.keyCode.ENTER:\n if (this.element.val().length >= parseInt(this.options.minSearchLength, 10)) {\n this.searchForm.trigger('submit');\n e.preventDefault();\n }\n break;\n\n case $.ui.keyCode.DOWN:\n if (this.responseList.indexList) {\n if (!this.responseList.selected) { //eslint-disable-line max-depth\n this._getFirstVisibleElement().addClass(this.options.selectClass);\n this.responseList.selected = this._getFirstVisibleElement();\n } else if (!this._getLastElement().hasClass(this.options.selectClass)) {\n this.responseList.selected = this.responseList.selected\n .removeClass(this.options.selectClass).next().addClass(this.options.selectClass);\n } else {\n this.responseList.selected.removeClass(this.options.selectClass);\n this._getFirstVisibleElement().addClass(this.options.selectClass);\n this.responseList.selected = this._getFirstVisibleElement();\n }\n this.element.val(this.responseList.selected.find('.qs-option-name').text());\n this.element.attr('aria-activedescendant', this.responseList.selected.attr('id'));\n this._updateAriaHasPopup(true);\n this.autoComplete.show();\n }\n break;\n\n case $.ui.keyCode.UP:\n if (this.responseList.indexList !== null) {\n if (!this._getFirstVisibleElement().hasClass(this.options.selectClass)) {\n this.responseList.selected = this.responseList.selected\n .removeClass(this.options.selectClass).prev().addClass(this.options.selectClass);\n\n } else {\n this.responseList.selected.removeClass(this.options.selectClass);\n this._getLastElement().addClass(this.options.selectClass);\n this.responseList.selected = this._getLastElement();\n }\n this.element.val(this.responseList.selected.find('.qs-option-name').text());\n this.element.attr('aria-activedescendant', this.responseList.selected.attr('id'));\n this._updateAriaHasPopup(true);\n this.autoComplete.show();\n }\n break;\n default:\n return true;\n }\n },\n\n /**\n * Executes when the value of the search input field changes. Executes a GET request\n * to populate a suggestion list based on entered text. Handles click (select), hover,\n * and mouseout events on the populated suggestion list dropdown.\n * @private\n */\n _onPropertyChange: function () {\n var searchField = this.element,\n clonePosition = {\n position: 'absolute',\n // Removed to fix display issues\n // left: searchField.offset().left,\n // top: searchField.offset().top + searchField.outerHeight(),\n width: searchField.outerWidth()\n },\n source = this.options.template,\n template = mageTemplate(source),\n dropdown = $('<ul role=\"listbox\"></ul>'),\n value = this.element.val();\n\n this.submitBtn.disabled = true;\n\n if (value.length >= parseInt(this.options.minSearchLength, 10)) {\n this.submitBtn.disabled = false;\n\n if (this.options.url !== '') { //eslint-disable-line eqeqeq\n $.getJSON(this.options.url, {\n q: value\n }, $.proxy(function (data) {\n if (data.length) {\n $.each(data, function (index, element) {\n var html;\n\n element.index = index;\n html = template({\n data: element\n });\n dropdown.append(html);\n });\n\n this._resetResponseList(true);\n\n this.responseList.indexList = this.autoComplete.html(dropdown)\n .css(clonePosition)\n .show()\n .find(this.options.responseFieldElements + ':visible');\n\n this.element.removeAttr('aria-activedescendant');\n\n if (this.responseList.indexList.length) {\n this._updateAriaHasPopup(true);\n } else {\n this._updateAriaHasPopup(false);\n }\n\n this.responseList.indexList\n .on('click', function (e) {\n this.responseList.selected = $(e.currentTarget);\n this.searchForm.trigger('submit');\n }.bind(this))\n .on('mouseenter mouseleave', function (e) {\n this.responseList.indexList.removeClass(this.options.selectClass);\n $(e.target).addClass(this.options.selectClass);\n this.responseList.selected = $(e.target);\n this.element.attr('aria-activedescendant', $(e.target).attr('id'));\n }.bind(this))\n .on('mouseout', function (e) {\n if (!this._getLastElement() &&\n this._getLastElement().hasClass(this.options.selectClass)) {\n $(e.target).removeClass(this.options.selectClass);\n this._resetResponseList(false);\n }\n }.bind(this));\n } else {\n this._resetResponseList(true);\n this.autoComplete.hide();\n this._updateAriaHasPopup(false);\n this.element.removeAttr('aria-activedescendant');\n }\n }, this));\n }\n } else {\n this._resetResponseList(true);\n this.autoComplete.hide();\n this._updateAriaHasPopup(false);\n this.element.removeAttr('aria-activedescendant');\n }\n }\n });\n\n return $.mage.quickSearch;\n});\n","Magento_Vault/js/view/payment/vault.js":"/**\n * Copyright \u00a9 Magento, Inc. All rights reserved.\n * See COPYING.txt for license details.\n */\n/*browser:true*/\n\n/* @api */\ndefine([\n 'underscore',\n 'uiComponent',\n 'Magento_Checkout/js/model/payment/renderer-list',\n 'uiLayout',\n 'uiRegistry'\n], function (_, Component, rendererList, layout, registry) {\n 'use strict';\n\n var vaultGroupName = 'vaultGroup';\n\n layout([{\n name: vaultGroupName,\n component: 'Magento_Checkout/js/model/payment/method-group',\n alias: 'vault',\n sortOrder: 10\n }]);\n\n registry.get(vaultGroupName, function (vaultGroup) {\n _.each(window.checkoutConfig.payment.vault, function (config, index) {\n rendererList.push(\n {\n type: index,\n config: config.config,\n component: config.component,\n group: vaultGroup,\n\n /**\n * Custom payment method types comparator\n * @param {String} typeA\n * @param {String} typeB\n * @return {Boolean}\n */\n typeComparatorCallback: function (typeA, typeB) {\n // vault token items have the same name as vault payment without index\n return typeA.substring(0, typeA.lastIndexOf('_')) === typeB;\n }\n }\n );\n });\n });\n\n /**\n * Add view logic here if needed\n */\n return Component.extend({});\n});\n","Magento_Vault/js/view/payment/vault-enabler.js":"/**\n * Copyright \u00a9 Magento, Inc. All rights reserved.\n * See COPYING.txt for license details.\n */\n/*browser:true*/\n\n/* @api */\ndefine(\n [\n 'uiElement'\n ],\n function (\n Component\n ) {\n 'use strict';\n\n return Component.extend({\n defaults: {\n isActivePaymentTokenEnabler: true\n },\n\n /**\n * @param {String} paymentCode\n */\n setPaymentCode: function (paymentCode) {\n this.paymentCode = paymentCode;\n },\n\n /**\n * @returns {Object}\n */\n initObservable: function () {\n this._super()\n .observe([\n 'isActivePaymentTokenEnabler'\n ]);\n\n return this;\n },\n\n /**\n * @param {Object} data\n */\n visitAdditionalData: function (data) {\n if (!this.isVaultEnabled()) {\n return;\n }\n\n if (!('additional_data' in data)) {\n data['additional_data'] = {};\n }\n\n data['additional_data']['is_active_payment_token_enabler'] = this.isActivePaymentTokenEnabler();\n },\n\n /**\n * @returns {Boolean}\n */\n isVaultEnabled: function () {\n return typeof window.checkoutConfig.vault[this.paymentCode] !== 'undefined' &&\n window.checkoutConfig.vault[this.paymentCode]['is_enabled'] === true;\n }\n });\n }\n);\n","Magento_Vault/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*/\n\ndefine(\n [\n 'Magento_Checkout/js/view/payment/default',\n 'Magento_Checkout/js/action/select-payment-method',\n 'Magento_Checkout/js/checkout-data'\n ],\n function (Component, selectPaymentMethod, checkoutData) {\n 'use strict';\n\n return Component.extend({\n defaults: {\n template: 'Magento_Vault/payment/form'\n },\n\n /**\n * @returns {exports.initObservable}\n */\n initObservable: function () {\n this._super()\n .observe([]);\n\n return this;\n },\n\n /**\n * @returns\n */\n selectPaymentMethod: function () {\n selectPaymentMethod(\n {\n method: this.getId()\n }\n );\n checkoutData.setSelectedPaymentMethod(this.getId());\n\n return true;\n },\n\n /**\n * @returns {String}\n */\n getTitle: function () {\n return '';\n },\n\n /**\n * @returns {String}\n */\n getToken: function () {\n return '';\n },\n\n /**\n * @returns {String}\n */\n getId: function () {\n return this.index;\n },\n\n /**\n * @returns {String}\n */\n getCode: function () {\n return this.code;\n },\n\n /**\n * Get last 4 digits of card\n * @returns {String}\n */\n getMaskedCard: function () {\n return '';\n },\n\n /**\n * Get expiration date\n * @returns {String}\n */\n getExpirationDate: function () {\n return '';\n },\n\n /**\n * Get card type\n * @returns {String}\n */\n getCardType: function () {\n return '';\n },\n\n /**\n * @param {String} type\n * @returns {Boolean}\n */\n getIcons: function (type) {\n return window.checkoutConfig.payment.ccform.icons.hasOwnProperty(type) ?\n window.checkoutConfig.payment.ccform.icons[type]\n : false;\n },\n\n /**\n * Return state of place order button.\n *\n * @return {Boolean}\n */\n isButtonActive: function () {\n return this.isActive() && this.isPlaceOrderActionAllowed();\n },\n\n /**\n * Check if payment is active.\n *\n * @return {Boolean}\n */\n isActive: function () {\n return this.isChecked() === this.getId();\n },\n\n /**\n * @returns {*}\n */\n getData: function () {\n var data = {\n method: this.getCode()\n };\n\n data['additional_data'] = {};\n data['additional_data']['public_hash'] = this.getToken();\n\n return data;\n }\n });\n }\n);\n","Magento_Vault/js/customer_account/deleteWidget.js":"/**\n * Copyright \u00a9 Magento, Inc. All rights reserved.\n * See COPYING.txt for license details.\n */\ndefine([\n 'jquery',\n 'Magento_Ui/js/modal/modalToggle',\n 'mage/translate'\n], function ($, modalToggle) {\n 'use strict';\n\n return function (config, deleteButton) {\n config.buttons = [\n {\n text: $.mage.__('Cancel'),\n class: 'action secondary cancel'\n }, {\n text: $.mage.__('Delete'),\n class: 'action primary',\n\n /**\n * Default action on button click\n */\n click: function (event) { //eslint-disable-line no-unused-vars\n $(deleteButton.form).trigger('submit');\n }\n }\n ];\n\n modalToggle(config, deleteButton);\n };\n});\n","Magento_GiftMessage/js/gift-options.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.giftOptions', {\n options: {\n mageError: 'mage-error',\n noDisplay: 'no-display',\n requiredEntry: 'required-entry'\n },\n\n /**\n * Initial toggle of the various gift options after widget instantiation.\n * @private\n */\n _init: function () {\n this._toggleVisibility();\n },\n\n /**\n * Bind a click handler to the widget's context element.\n * @private\n */\n _create: function () {\n this.element.on('click', $.proxy(this._toggleVisibility, this));\n $(this.element.data('selector').id).find('.giftmessage-area')\n .on('change', $.proxy(this._toggleRequired, this));\n },\n\n /**\n * Toggle the visibility of the widget's context element's selector(s).\n * @private\n * @param {jQuery.Event} event - Click event. Target is a checkbox.\n */\n _toggleVisibility: function (event) {\n var checkbox = event ? $(event.target) : this.element,\n container = $(checkbox.data('selector').id),\n _this;\n\n if (checkbox.is(':checked')) {\n container.show()\n .find('.giftmessage-area:not(:visible)').each(function (x, element) {\n if ($(element).val().length > 0) {\n $(element).trigger('change');\n container.find('a').trigger('click');\n }\n });\n } else {\n _this = this;\n container.hide()\n .find('.input-text:not(.giftmessage-area)').each(function (x, element) {\n $(element).val(element.defaultValue).removeClass(_this.options.mageError)\n .next('div.' + _this.options.mageError).remove();\n }).end()\n .find('.giftmessage-area').val('').change().end()\n .find('.select').val('').change().end()\n .find('.checkbox:checked').prop('checked', false).trigger('click').prop('checked', false).end()\n .find('.price-box').addClass(this.options.noDisplay).end();\n }\n },\n\n /**\n * Make the From and To input fields required if a gift message has been written.\n * @private\n * @param {jQuery.Event} event - Change event. Target is a textarea.\n */\n _toggleRequired: function (event) {\n var textArea = $(event.target),\n length = textArea.val().length;\n\n textArea.closest('li').prev('.fields')\n .find('.input-text').toggleClass(this.options.requiredEntry, length > 0);\n }\n });\n\n return $.mage.giftOptions;\n});\n","Magento_GiftMessage/js/view/gift-message.js":"/**\n * Copyright \u00a9 Magento, Inc. All rights reserved.\n * See COPYING.txt for license details.\n */\n\ndefine([\n 'uiComponent',\n 'Magento_GiftMessage/js/model/gift-message',\n 'Magento_GiftMessage/js/model/gift-options',\n 'Magento_GiftMessage/js/action/gift-options'\n], function (Component, GiftMessage, giftOptions, giftOptionsService) {\n 'use strict';\n\n return Component.extend({\n formBlockVisibility: null,\n resultBlockVisibility: null,\n model: {},\n\n /**\n * Component init\n */\n initialize: function () {\n var self = this,\n model;\n\n this._super()\n .observe('formBlockVisibility')\n .observe({\n 'resultBlockVisibility': false\n });\n\n this.itemId = this.itemId || 'orderLevel';\n model = new GiftMessage(this.itemId);\n this.model = model;\n this.isResultBlockVisible();\n giftOptions.addOption(model);\n\n this.model.getObservable('isClear').subscribe(function (value) {\n if (value == true) { //eslint-disable-line eqeqeq\n self.formBlockVisibility(false);\n self.model.getObservable('alreadyAdded')(true);\n }\n });\n },\n\n /**\n * Is reslt block visible\n */\n isResultBlockVisible: function () {\n var self = this;\n\n if (this.model.getObservable('alreadyAdded')()) {\n this.resultBlockVisibility(true);\n }\n this.model.getObservable('additionalOptionsApplied').subscribe(function (value) {\n if (value == true) { //eslint-disable-line eqeqeq\n self.resultBlockVisibility(true);\n }\n });\n },\n\n /**\n * @param {String} key\n * @return {*}\n */\n getObservable: function (key) {\n return this.model.getObservable(key);\n },\n\n /**\n * Hide\\Show form block\n */\n toggleFormBlockVisibility: function () {\n if (!this.model.getObservable('alreadyAdded')()) {\n this.formBlockVisibility(!this.formBlockVisibility());\n } else {\n this.resultBlockVisibility(!this.resultBlockVisibility());\n }\n },\n\n /**\n * Edit options\n */\n editOptions: function () {\n this.resultBlockVisibility(false);\n this.formBlockVisibility(true);\n },\n\n /**\n * Delete options\n */\n deleteOptions: function () {\n giftOptionsService(this.model, true);\n },\n\n /**\n * Hide form block\n */\n hideFormBlock: function () {\n this.formBlockVisibility(false);\n\n if (this.model.getObservable('alreadyAdded')()) {\n this.resultBlockVisibility(true);\n }\n },\n\n /**\n * @return {Boolean}\n */\n hasActiveOptions: function () {\n var regionData = this.getRegion('additionalOptions'),\n options = regionData(),\n i;\n\n for (i = 0; i < options.length; i++) {\n if (options[i].isActive()) {\n return true;\n }\n }\n\n return false;\n },\n\n /**\n * @return {Boolean}\n */\n isActive: function () {\n return this.model.isGiftMessageAvailable();\n },\n\n /**\n * Submit options\n */\n submitOptions: function () {\n giftOptionsService(this.model);\n }\n });\n});\n","Magento_GiftMessage/js/action/gift-options.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_GiftMessage/js/model/url-builder',\n 'mage/storage',\n 'Magento_Ui/js/model/messageList',\n 'Magento_Checkout/js/model/error-processor',\n 'mage/url',\n 'Magento_Checkout/js/model/quote',\n 'underscore'\n], function (urlBuilder, storage, messageList, errorProcessor, url, quote, _) {\n 'use strict';\n\n return function (giftMessage, remove) {\n var serviceUrl;\n\n url.setBaseUrl(giftMessage.getConfigValue('baseUrl'));\n\n if (giftMessage.getConfigValue('isCustomerLoggedIn')) {\n serviceUrl = urlBuilder.createUrl('/carts/mine/gift-message', {});\n\n if (giftMessage.itemId != 'orderLevel') { //eslint-disable-line eqeqeq\n serviceUrl = urlBuilder.createUrl('/carts/mine/gift-message/:itemId', {\n itemId: giftMessage.itemId\n });\n }\n } else {\n serviceUrl = urlBuilder.createUrl('/guest-carts/:cartId/gift-message', {\n cartId: quote.getQuoteId()\n });\n\n if (giftMessage.itemId != 'orderLevel') { //eslint-disable-line eqeqeq\n serviceUrl = urlBuilder.createUrl(\n '/guest-carts/:cartId/gift-message/:itemId',\n {\n cartId: quote.getQuoteId(), itemId: giftMessage.itemId\n }\n );\n }\n }\n messageList.clear();\n\n storage.post(\n serviceUrl,\n JSON.stringify({\n 'gift_message': giftMessage.getSubmitParams(remove)\n })\n ).done(function () {\n giftMessage.reset();\n _.each(giftMessage.getAfterSubmitCallbacks(), function (callback) {\n if (_.isFunction(callback)) {\n callback();\n }\n });\n }).fail(function (response) {\n errorProcessor.process(response);\n });\n };\n});\n","Magento_GiftMessage/js/model/gift-message.js":"/**\n * Copyright \u00a9 Magento, Inc. All rights reserved.\n * See COPYING.txt for license details.\n */\n\n/**\n * @api\n */\ndefine([\n 'uiElement',\n 'underscore',\n 'mage/url'\n], function (uiElement, _, url) {\n 'use strict';\n\n var provider = uiElement();\n\n return function (itemId) {\n var model = {\n id: 'message-' + itemId,\n itemId: itemId,\n observables: {},\n additionalOptions: [],\n submitParams: [\n 'recipient',\n 'sender',\n 'message'\n ],\n\n /**\n * Initialize.\n */\n initialize: function () {\n var message = false;\n\n this.getObservable('alreadyAdded')(false);\n\n if (this.itemId == 'orderLevel') { //eslint-disable-line eqeqeq\n message = window.giftOptionsConfig.giftMessage.hasOwnProperty(this.itemId) ?\n window.giftOptionsConfig.giftMessage[this.itemId] :\n null;\n } else {\n message =\n window.giftOptionsConfig.giftMessage.hasOwnProperty('itemLevel') &&\n window.giftOptionsConfig.giftMessage.itemLevel.hasOwnProperty(this.itemId) ?\n window.giftOptionsConfig.giftMessage.itemLevel[this.itemId].message :\n null;\n }\n\n if (_.isObject(message)) {\n this.getObservable('recipient')(message.recipient);\n this.getObservable('sender')(message.sender);\n this.getObservable('message')(message.message);\n this.getObservable('alreadyAdded')(true);\n }\n },\n\n /**\n * @param {String} key\n * @return {*}\n */\n getObservable: function (key) {\n this.initObservable(this.id, key);\n\n return provider[this.getUniqueKey(this.id, key)];\n },\n\n /**\n * @param {String} node\n * @param {String} key\n */\n initObservable: function (node, key) {\n if (node && !this.observables.hasOwnProperty(node)) {\n this.observables[node] = [];\n }\n\n if (key && this.observables[node].indexOf(key) === -1) {\n this.observables[node].push(key);\n provider.observe(this.getUniqueKey(node, key));\n }\n },\n\n /**\n * @param {String} node\n * @param {String} key\n * @return {String}\n */\n getUniqueKey: function (node, key) {\n return node + '-' + key;\n },\n\n /**\n * @param {String} key\n * @return {null}\n */\n getConfigValue: function (key) {\n return window.giftOptionsConfig.hasOwnProperty(key) ?\n window.giftOptionsConfig[key]\n : null;\n },\n\n /**\n * Reset.\n */\n reset: function () {\n this.getObservable('isClear')(true);\n },\n\n /**\n * @return {Array}\n */\n getAfterSubmitCallbacks: function () {\n var callbacks = [];\n\n callbacks.push(this.afterSubmit);\n _.each(this.additionalOptions, function (option) {\n if (_.isFunction(option.afterSubmit)) {\n callbacks.push(option.afterSubmit);\n }\n });\n\n return callbacks;\n },\n\n /**\n * After submit.\n */\n afterSubmit: function () {\n window.location.href = url.build('checkout/cart/updatePost') +\n '?form_key=' + window.checkoutConfig.formKey +\n '&cart[]';\n },\n\n /**\n * @param {Boolean} remove\n * @return {Object}\n */\n getSubmitParams: function (remove) {\n var params = {},\n self = this;\n\n _.each(this.submitParams, function (key) {\n var observable = provider[self.getUniqueKey(self.id, key)];\n\n if (_.isFunction(observable)) {\n params[key] = remove ? null : observable();\n }\n });\n\n if (this.additionalOptions.length) {\n params['extension_attributes'] = {};\n }\n _.each(this.additionalOptions, function (option) {\n if (_.isFunction(option.getSubmitParams)) {\n params['extension_attributes'] = _.extend(\n params['extension_attributes'],\n option.getSubmitParams(remove)\n );\n }\n });\n\n return params;\n },\n\n /**\n * Check if gift message can be displayed\n *\n * @returns {Boolean}\n */\n isGiftMessageAvailable: function () {\n var isGloballyAvailable,\n giftMessageConfig,\n itemConfig;\n\n // itemId represent gift message level: 'orderLevel' constant or cart item ID\n if (this.itemId === 'orderLevel') {\n return this.getConfigValue('isOrderLevelGiftOptionsEnabled');\n }\n\n // gift message product configuration must override system configuration\n isGloballyAvailable = this.getConfigValue('isItemLevelGiftOptionsEnabled');\n giftMessageConfig = window.giftOptionsConfig.giftMessage;\n itemConfig = giftMessageConfig.hasOwnProperty('itemLevel') &&\n giftMessageConfig.itemLevel.hasOwnProperty(this.itemId) ?\n giftMessageConfig.itemLevel[this.itemId] :\n {};\n\n return itemConfig.hasOwnProperty('is_available') ? itemConfig['is_available'] : isGloballyAvailable;\n }\n };\n\n model.initialize();\n\n return model;\n };\n});\n","Magento_GiftMessage/js/model/gift-options.js":"/**\n * Copyright \u00a9 Magento, Inc. All rights reserved.\n * See COPYING.txt for license details.\n */\n\n/**\n * @api\n */\ndefine([\n 'underscore',\n 'ko'\n], function (_, ko) {\n 'use strict';\n\n return {\n options: ko.observableArray([]),\n\n /**\n * @param {Object} option\n */\n addOption: function (option) {\n if (!this.options().hasOwnProperty(option.itemId)) {\n this.options.push({\n id: option.itemId, value: option\n }\n );\n }\n },\n\n /**\n * @param {*} itemId\n * @return {*}\n */\n getOptionByItemId: function (itemId) {\n var option = null;\n\n _.each(this.options(), function (data) {\n if (data.id === itemId) {\n option = data.value;\n\n return false;\n }\n });\n\n return option;\n }\n };\n});\n","Magento_GiftMessage/js/model/url-builder.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/url-builder'\n], function ($, urlBuilder) {\n 'use strict';\n\n return $.extend(urlBuilder, {\n storeCode: window.giftOptionsConfig.storeCode\n });\n});\n","Magento_ReCaptchaFrontendUi/js/nonInlineReCaptchaRenderer.js":"/**\n * Copyright \u00a9 Magento, Inc. All rights reserved.\n * See COPYING.txt for license details.\n */\n\n/* global grecaptcha */\ndefine([\n 'jquery',\n 'jquery/z-index'\n], function ($) {\n 'use strict';\n\n var reCaptchaEntities = [],\n initialized = false,\n rendererRecaptchaId = 'recaptcha-invisible',\n rendererReCaptcha = null;\n\n return {\n /**\n * Add reCaptcha entity to checklist.\n *\n * @param {jQuery} reCaptchaEntity\n * @param {Object} parameters\n */\n add: function (reCaptchaEntity, parameters) {\n if (!initialized) {\n this.init();\n grecaptcha.render(rendererRecaptchaId, parameters);\n setInterval(this.resolveVisibility, 100);\n initialized = true;\n }\n\n reCaptchaEntities.push(reCaptchaEntity);\n },\n\n /**\n * Show additional reCaptcha instance if any other should be visible, otherwise hide it.\n */\n resolveVisibility: function () {\n reCaptchaEntities.some(function (entity) {\n return entity.is(':visible') &&\n // 900 is some magic z-index value of modal popups.\n (entity.closest('[data-role=\\'modal\\']').length === 0 || entity.zIndex() > 900);\n }) ? rendererReCaptcha.show() : rendererReCaptcha.hide();\n },\n\n /**\n * Initialize additional reCaptcha instance.\n */\n init: function () {\n rendererReCaptcha = $('<div/>', {\n 'id': rendererRecaptchaId\n });\n rendererReCaptcha.hide();\n $('body').append(rendererReCaptcha);\n }\n };\n});\n","Magento_ReCaptchaFrontendUi/js/reCaptcha.js":"/**\n * Copyright \u00a9 Magento, Inc. All rights reserved.\n * See COPYING.txt for license details.\n */\n\n/* global grecaptcha */\ndefine(\n [\n 'uiComponent',\n 'jquery',\n 'ko',\n 'underscore',\n 'Magento_ReCaptchaFrontendUi/js/registry',\n 'Magento_ReCaptchaFrontendUi/js/reCaptchaScriptLoader',\n 'Magento_ReCaptchaFrontendUi/js/nonInlineReCaptchaRenderer'\n ], function (Component, $, ko, _, registry, reCaptchaLoader, nonInlineReCaptchaRenderer) {\n 'use strict';\n\n return Component.extend({\n\n defaults: {\n template: 'Magento_ReCaptchaFrontendUi/reCaptcha',\n reCaptchaId: 'recaptcha'\n },\n\n /**\n * @inheritdoc\n */\n initialize: function () {\n this._super();\n this._loadApi();\n },\n\n /**\n * Loads recaptchaapi API and triggers event, when loaded\n * @private\n */\n _loadApi: function () {\n if (this._isApiRegistered !== undefined) {\n if (this._isApiRegistered === true) {\n $(window).trigger('recaptchaapiready');\n }\n\n return;\n }\n this._isApiRegistered = false;\n\n // global function\n window.globalOnRecaptchaOnLoadCallback = function () {\n this._isApiRegistered = true;\n $(window).trigger('recaptchaapiready');\n }.bind(this);\n\n reCaptchaLoader.addReCaptchaScriptTag();\n },\n\n /**\n * Checking that reCAPTCHA is invisible type\n * @returns {Boolean}\n */\n getIsInvisibleRecaptcha: function () {\n if (this.settings ===\n\n void 0) {\n return false;\n }\n\n return this.settings.invisible;\n },\n\n /**\n * reCAPTCHA callback\n * @param {String} token\n */\n reCaptchaCallback: function (token) {\n if (this.getIsInvisibleRecaptcha()) {\n this.tokenField.value = token;\n this.$parentForm.submit();\n }\n },\n\n /**\n * Initialize reCAPTCHA after first rendering\n */\n initCaptcha: function () {\n var $parentForm,\n $wrapper,\n $reCaptcha,\n widgetId,\n parameters;\n\n if (this.captchaInitialized || this.settings ===\n\n void 0) {\n return;\n }\n\n this.captchaInitialized = true;\n\n /*\n * Workaround for data-bind issue:\n * We cannot use data-bind to link a dynamic id to our component\n * See:\n * https://stackoverflow.com/questions/46657573/recaptcha-the-bind-parameter-must-be-an-element-or-id\n *\n * We create a wrapper element with a wrapping id and we inject the real ID with jQuery.\n * In this way we have no data-bind attribute at all in our reCAPTCHA div\n */\n $wrapper = $('#' + this.getReCaptchaId() + '-wrapper');\n $reCaptcha = $wrapper.find('.g-recaptcha');\n $reCaptcha.attr('id', this.getReCaptchaId());\n\n $parentForm = $wrapper.parents('form');\n\n if (this.settings === undefined) {\n\n return;\n }\n\n parameters = _.extend(\n {\n 'callback': function (token) { // jscs:ignore jsDoc\n this.reCaptchaCallback(token);\n this.validateReCaptcha(true);\n }.bind(this),\n 'expired-callback': function () {\n this.validateReCaptcha(false);\n }.bind(this)\n },\n this.settings.rendering\n );\n\n if (parameters.size === 'invisible' && parameters.badge !== 'inline') {\n nonInlineReCaptchaRenderer.add($reCaptcha, parameters);\n }\n\n // eslint-disable-next-line no-undef\n widgetId = grecaptcha.render(this.getReCaptchaId(), parameters);\n this.initParentForm($parentForm, widgetId);\n\n registry.ids.push(this.getReCaptchaId());\n registry.captchaList.push(widgetId);\n registry.tokenFields.push(this.tokenField);\n\n },\n\n /**\n * Initialize parent form.\n *\n * @param {Object} parentForm\n * @param {String} widgetId\n */\n initParentForm: function (parentForm, widgetId) {\n var listeners;\n\n if (this.getIsInvisibleRecaptcha() && parentForm.length > 0) {\n parentForm.submit(function (event) {\n if (!this.tokenField.value) {\n // eslint-disable-next-line no-undef\n grecaptcha.execute(widgetId);\n event.preventDefault(event);\n event.stopImmediatePropagation();\n }\n }.bind(this));\n\n // Move our (last) handler topmost. We need this to avoid submit bindings with ko.\n listeners = $._data(parentForm[0], 'events').submit;\n listeners.unshift(listeners.pop());\n\n // Create a virtual token field\n this.tokenField = $('<input type=\"text\" name=\"token\" style=\"display: none\" />')[0];\n this.$parentForm = parentForm;\n parentForm.append(this.tokenField);\n } else {\n this.tokenField = null;\n }\n if ($('#send2').length > 0) {$('#send2').prop('disabled', false);}\n },\n\n /**\n * Validates reCAPTCHA\n * @param {*} state\n * @returns {jQuery}\n */\n validateReCaptcha: function (state) {\n if (!this.getIsInvisibleRecaptcha()) {\n return $(document).find('input[type=checkbox].required-captcha').prop('checked', state);\n }\n },\n\n /**\n * Render reCAPTCHA\n */\n renderReCaptcha: function () {\n if (window.grecaptcha && window.grecaptcha.render) { // Check if reCAPTCHA is already loaded\n this.initCaptcha();\n } else { // Wait for reCAPTCHA to be loaded\n $(window).on('recaptchaapiready', function () {\n this.initCaptcha();\n }.bind(this));\n }\n },\n\n /**\n * Get reCAPTCHA ID\n * @returns {String}\n */\n getReCaptchaId: function () {\n return this.reCaptchaId;\n }\n });\n });\n","Magento_ReCaptchaFrontendUi/js/registry.js":"/**\n * Copyright \u00a9 Magento, Inc. All rights reserved.\n * See COPYING.txt for license details.\n */\n\ndefine(['ko'], function (ko) {\n 'use strict';\n\n return {\n ids: ko.observableArray([]),\n captchaList: ko.observableArray([]),\n tokenFields: ko.observableArray([])\n };\n});\n","Magento_ReCaptchaFrontendUi/js/reCaptchaScriptLoader.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 scriptTagAdded = false;\n\n return {\n /**\n * Add script tag. Script tag should be added once\n */\n addReCaptchaScriptTag: function () {\n var element, scriptTag;\n\n if (!scriptTagAdded) {\n element = document.createElement('script');\n scriptTag = document.getElementsByTagName('script')[0];\n\n element.async = true;\n element.src = 'https://www.google.com/recaptcha/api.js' +\n '?onload=globalOnRecaptchaOnLoadCallback&render=explicit';\n\n scriptTag.parentNode.insertBefore(element, scriptTag);\n scriptTagAdded = true;\n }\n }\n };\n});\n","Magento_ReCaptchaFrontendUi/js/ui-messages-mixin.js":"/**\n * Copyright \u00a9 Magento, Inc. All rights reserved.\n * See COPYING.txt for license details.\n */\n\ndefine(['Magento_ReCaptchaFrontendUi/js/registry'], function (registry) {\n 'use strict';\n\n return function (originalComponent) {\n return originalComponent.extend({\n /**\n * Initialize reset on messages\n * @returns {initialize}\n */\n initialize: function () {\n this._super();\n\n this.messageContainer.errorMessages.subscribe(function () {\n var\n i,\n captchaList = registry.captchaList(),\n tokenFieldsList = registry.tokenFields();\n\n for (i = 0; i < captchaList.length; i++) {\n // eslint-disable-next-line no-undef\n grecaptcha.reset(captchaList[i]);\n\n if (tokenFieldsList[i]) {\n tokenFieldsList[i].value = '';\n }\n }\n }, null, 'arrayChange');\n\n return this;\n }\n });\n };\n});\n","Magento_InstantPurchase/js/view/instant-purchase.js":"/**\n * Copyright \u00a9 Magento, Inc. All rights reserved.\n * See COPYING.txt for license details.\n */\ndefine([\n 'ko',\n 'jquery',\n 'underscore',\n 'uiComponent',\n 'Magento_Ui/js/modal/confirm',\n 'Magento_Customer/js/customer-data',\n 'mage/url',\n 'mage/template',\n 'mage/translate',\n 'text!Magento_InstantPurchase/template/confirmation.html',\n 'mage/validation'\n], function (ko, $, _, Component, confirm, customerData, urlBuilder, mageTemplate, $t, confirmationTemplate) {\n 'use strict';\n\n return Component.extend({\n defaults: {\n template: 'Magento_InstantPurchase/instant-purchase',\n buttonText: $t('Instant Purchase'),\n purchaseUrl: urlBuilder.build('instantpurchase/button/placeOrder'),\n showButton: false,\n paymentToken: null,\n shippingAddress: null,\n billingAddress: null,\n shippingMethod: null,\n productFormSelector: '#product_addtocart_form',\n confirmationTitle: $t('Instant Purchase Confirmation'),\n confirmationData: {\n message: $t('Are you sure you want to place order and pay?'),\n shippingAddressTitle: $t('Shipping Address'),\n billingAddressTitle: $t('Billing Address'),\n paymentMethodTitle: $t('Payment Method'),\n shippingMethodTitle: $t('Shipping Method')\n }\n },\n\n /** @inheritdoc */\n initialize: function () {\n var instantPurchase = customerData.get('instant-purchase');\n\n this._super();\n\n this.setPurchaseData(instantPurchase());\n instantPurchase.subscribe(this.setPurchaseData, this);\n },\n\n /** @inheritdoc */\n initObservable: function () {\n this._super()\n .observe('showButton paymentToken shippingAddress billingAddress shippingMethod');\n\n return this;\n },\n\n /**\n * Set data from customerData.\n *\n * @param {Object} data\n */\n setPurchaseData: function (data) {\n this.showButton(data.available);\n this.paymentToken(data.paymentToken);\n this.shippingAddress(data.shippingAddress);\n this.billingAddress(data.billingAddress);\n this.shippingMethod(data.shippingMethod);\n },\n\n /**\n * Confirmation method\n */\n instantPurchase: function () {\n var form = $(this.productFormSelector),\n confirmTemplate = mageTemplate(confirmationTemplate),\n confirmData = _.extend({}, this.confirmationData, {\n paymentToken: this.paymentToken().summary,\n shippingAddress: this.shippingAddress().summary,\n billingAddress: this.billingAddress().summary,\n shippingMethod: this.shippingMethod().summary\n });\n\n if (!(form.validation() && form.validation('isValid'))) {\n return;\n }\n\n confirm({\n title: this.confirmationTitle,\n content: confirmTemplate({\n data: confirmData\n }),\n actions: {\n /** @inheritdoc */\n confirm: function () {\n $.ajax({\n url: this.purchaseUrl,\n data: form.serialize(),\n type: 'post',\n dataType: 'json',\n\n /** Show loader before send */\n beforeSend: function () {\n $('body').trigger('processStart');\n }\n }).always(function () {\n $('body').trigger('processStop');\n });\n }.bind(this)\n }\n });\n }\n });\n});\n","Magento_ReCaptchaWebapiUi/js/webapiReCaptcha.js":"/**\n * Copyright \u00a9 Magento, Inc. All rights reserved.\n * See COPYING.txt for license details.\n */\n\n// jscs:disable jsDoc\n\n/* global grecaptcha */\ndefine(\n [\n 'Magento_ReCaptchaFrontendUi/js/reCaptcha',\n 'Magento_ReCaptchaWebapiUi/js/webapiReCaptchaRegistry'\n ],\n function (Component, registry) {\n 'use strict';\n\n return Component.extend({\n defaults: {\n autoTrigger: false\n },\n\n /**\n * Provide the token to the registry.\n *\n * @param {String} token\n */\n reCaptchaCallback: function (token) {\n //Make the token retrievable in other UI components.\n registry.tokens[this.getReCaptchaId()] = token;\n\n if (typeof registry._listeners[this.getReCaptchaId()] !== 'undefined') {\n registry._listeners[this.getReCaptchaId()](token);\n }\n },\n\n /**\n * Register this ReCaptcha.\n *\n * @param {Object} parentForm\n * @param {String} widgetId\n */\n initParentForm: function (parentForm, widgetId) {\n var self = this,\n trigger;\n\n trigger = function () {\n self.reCaptchaCallback(grecaptcha.getResponse(widgetId));\n };\n registry._isInvisibleType[this.getReCaptchaId()] = false;\n\n if (this.getIsInvisibleRecaptcha()) {\n trigger = function () {\n grecaptcha.execute(widgetId);\n };\n registry._isInvisibleType[this.getReCaptchaId()] = true;\n }\n\n if (this.autoTrigger) {\n //Validate ReCaptcha when initiated\n trigger();\n registry.triggers[this.getReCaptchaId()] = new Function();\n } else {\n registry.triggers[this.getReCaptchaId()] = trigger;\n }\n this.tokenField = null;\n }\n });\n }\n);\n","Magento_ReCaptchaWebapiUi/js/webapiReCaptchaRegistry.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 * recaptchaId: token map.\n *\n * Tokens for already verified recaptcha.\n */\n tokens: {},\n\n /**\n * recaptchaId: triggerFn map.\n *\n * Call a trigger to initiate a recaptcha verification.\n */\n triggers: {},\n\n /**\n * recaptchaId: callback map\n */\n _listeners: {},\n\n /**\n * recaptchaId: bool map\n */\n _isInvisibleType: {},\n\n /**\n * Add a listener to when the ReCaptcha finishes verification\n * @param {String} id - ReCaptchaId\n * @param {Function} func - Will be called back with the token\n */\n addListener: function (id, func) {\n if (this.tokens.hasOwnProperty(id)) {\n func(this.tokens[id]);\n } else {\n this._listeners[id] = func;\n }\n },\n\n /**\n * Remove a listener\n *\n * @param id\n */\n removeListener: function (id) {\n this._listeners[id] = undefined;\n }\n };\n});\n","Magento_ReCaptchaWebapiUi/js/jquery-mixin.js":"/**\n * Copyright \u00a9 Magento, Inc. All rights reserved.\n * See COPYING.txt for license details.\n */\n\n// jscs:disable requireDotNotation\n\ndefine([\n 'mage/utils/wrapper'\n], function (wrapper) {\n 'use strict';\n\n return function (jQuery) {\n jQuery.ajax = wrapper.wrapSuper(jQuery.ajax, function () {\n //Moving ReCaptcha value from payload to the header for requests to web API\n var settings,\n payload;\n\n if (arguments.length !== 0) {\n settings = arguments.length === 1 ? arguments[0] : arguments[1];\n }\n\n if (settings && settings.hasOwnProperty('data')) {\n //The request has a body, trying to parse JSON data\n try {\n payload = JSON.parse(settings.data);\n } catch (e) {\n //Not JSON\n }\n }\n\n if (payload && payload.hasOwnProperty('xReCaptchaValue')) {\n if (!settings.hasOwnProperty('headers')) {\n settings.headers = {};\n }\n settings.headers['X-ReCaptcha'] = payload.xReCaptchaValue;\n delete payload['xReCaptchaValue'];\n settings.data = JSON.stringify(payload);\n }\n\n return this._super.apply(this, arguments);\n });\n\n return jQuery;\n };\n});\n","Magento_CheckoutAgreements/js/view/checkout-agreements.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_CheckoutAgreements/js/model/agreements-modal'\n], function (ko, $, Component, agreementsModal) {\n 'use strict';\n\n var checkoutConfig = window.checkoutConfig,\n agreementManualMode = 1,\n agreementsConfig = checkoutConfig ? checkoutConfig.checkoutAgreements : {};\n\n return Component.extend({\n defaults: {\n template: 'Magento_CheckoutAgreements/checkout/checkout-agreements'\n },\n isVisible: agreementsConfig.isEnabled,\n agreements: agreementsConfig.agreements,\n modalTitle: ko.observable(null),\n modalContent: ko.observable(null),\n contentHeight: ko.observable(null),\n modalWindow: null,\n\n /**\n * Checks if agreement required\n *\n * @param {Object} element\n */\n isAgreementRequired: function (element) {\n return element.mode == agreementManualMode; //eslint-disable-line eqeqeq\n },\n\n /**\n * Show agreement content in modal\n *\n * @param {Object} element\n */\n showContent: function (element) {\n this.modalTitle(element.checkboxText);\n this.modalContent(element.content);\n this.contentHeight(element.contentHeight ? element.contentHeight : 'auto');\n agreementsModal.showModal();\n },\n\n /**\n * build a unique id for the term checkbox\n *\n * @param {Object} context - the ko context\n * @param {Number} agreementId\n */\n getCheckboxId: function (context, agreementId) {\n var paymentMethodName = '',\n paymentMethodRenderer = context.$parents[1];\n\n // corresponding payment method fetched from parent context\n if (paymentMethodRenderer) {\n // item looks like this: {title: \"Check / Money order\", method: \"checkmo\"}\n paymentMethodName = paymentMethodRenderer.item ?\n paymentMethodRenderer.item.method : '';\n }\n\n return 'agreement_' + paymentMethodName + '_' + agreementId;\n },\n\n /**\n * Init modal window for rendered element\n *\n * @param {Object} element\n */\n initModal: function (element) {\n agreementsModal.createModal(element);\n }\n });\n});\n","Magento_CheckoutAgreements/js/view/agreement-validation.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/payment/additional-validators',\n 'Magento_CheckoutAgreements/js/model/agreement-validator'\n], function (Component, additionalValidators, agreementValidator) {\n 'use strict';\n\n additionalValidators.registerValidator(agreementValidator);\n\n return Component.extend({});\n});\n","Magento_CheckoutAgreements/js/model/agreements-assigner.js":"/**\n * Copyright \u00a9 Magento, Inc. All rights reserved.\n * See COPYING.txt for license details.\n */\n\ndefine([\n 'jquery'\n], function ($) {\n 'use strict';\n\n var agreementsConfig = window.checkoutConfig.checkoutAgreements;\n\n /** Override default place order action and add agreement_ids to request */\n return function (paymentData) {\n var agreementForm,\n agreementData,\n agreementIds;\n\n if (!agreementsConfig.isEnabled) {\n return;\n }\n\n agreementForm = $('.payment-method._active div[data-role=checkout-agreements] input');\n agreementData = agreementForm.serializeArray();\n agreementIds = [];\n\n agreementData.forEach(function (item) {\n agreementIds.push(item.value);\n });\n\n if (paymentData['extension_attributes'] === undefined) {\n paymentData['extension_attributes'] = {};\n }\n\n paymentData['extension_attributes']['agreement_ids'] = agreementIds;\n };\n});\n","Magento_CheckoutAgreements/js/model/place-order-mixin.js":"/**\n * Copyright \u00a9 Magento, Inc. All rights reserved.\n * See COPYING.txt for license details.\n */\n\ndefine([\n 'jquery',\n 'mage/utils/wrapper',\n 'Magento_CheckoutAgreements/js/model/agreements-assigner'\n], function ($, wrapper, agreementsAssigner) {\n 'use strict';\n\n return function (placeOrderAction) {\n\n /** Override default place order action and add agreement_ids to request */\n return wrapper.wrap(placeOrderAction, function (originalAction, paymentData, messageContainer) {\n agreementsAssigner(paymentData);\n\n return originalAction(paymentData, messageContainer);\n });\n };\n});\n","Magento_CheckoutAgreements/js/model/agreement-validator.js":"/**\n * Copyright \u00a9 Magento, Inc. All rights reserved.\n * See COPYING.txt for license details.\n */\n\ndefine([\n 'jquery',\n 'mage/validation'\n], function ($) {\n 'use strict';\n\n var checkoutConfig = window.checkoutConfig,\n agreementsConfig = checkoutConfig ? checkoutConfig.checkoutAgreements : {},\n agreementsInputPath = '.payment-method._active div.checkout-agreements input';\n\n return {\n /**\n * Validate checkout agreements\n *\n * @returns {Boolean}\n */\n validate: function (hideError) {\n var isValid = true;\n\n if (!agreementsConfig.isEnabled || $(agreementsInputPath).length === 0) {\n return true;\n }\n\n $(agreementsInputPath).each(function (index, element) {\n if (!$.validator.validateSingleElement(element, {\n errorElement: 'div',\n hideError: hideError || false\n })) {\n isValid = false;\n }\n });\n\n return isValid;\n }\n };\n});\n","Magento_CheckoutAgreements/js/model/agreements-modal.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/modal',\n 'mage/translate'\n], function ($, modal, $t) {\n 'use strict';\n\n return {\n modalWindow: null,\n\n /**\n * Create popUp window for provided element.\n *\n * @param {HTMLElement} element\n */\n createModal: function (element) {\n var options;\n\n this.modalWindow = element;\n options = {\n 'type': 'popup',\n 'modalClass': 'agreements-modal',\n 'responsive': true,\n 'innerScroll': true,\n 'trigger': '.show-modal',\n 'buttons': [\n {\n text: $t('Close'),\n class: 'action secondary action-hide-popup',\n\n /** @inheritdoc */\n click: function () {\n this.closeModal();\n }\n }\n ]\n };\n modal(options, $(this.modalWindow));\n },\n\n /** Show login popup window */\n showModal: function () {\n $(this.modalWindow).modal('openModal');\n }\n };\n});\n","Magento_CheckoutAgreements/js/model/set-payment-information-mixin.js":"/**\n * Copyright \u00a9 Magento, Inc. All rights reserved.\n * See COPYING.txt for license details.\n */\n\ndefine([\n 'jquery',\n 'mage/utils/wrapper',\n 'Magento_CheckoutAgreements/js/model/agreements-assigner'\n], function ($, wrapper, agreementsAssigner) {\n 'use strict';\n\n return function (placeOrderAction) {\n\n /** Override place-order-mixin for set-payment-information action as they differs only by method signature */\n return wrapper.wrap(placeOrderAction, function (originalAction, messageContainer, paymentData) {\n agreementsAssigner(paymentData);\n\n return originalAction(messageContainer, paymentData);\n });\n };\n});\n"} }});