diff --git a/modules.local/ppcp-button/assets/js/button.js b/modules.local/ppcp-button/assets/js/button.js index 617dab257..5e0a8e44b 100644 --- a/modules.local/ppcp-button/assets/js/button.js +++ b/modules.local/ppcp-button/assets/js/button.js @@ -1,449 +1,2 @@ -/******/ (function (modules) { - // webpackBootstrap -/******/ // The module cache -/******/ var installedModules = {}; -/******/ -/******/ // The require function -/******/ function __webpack_require__(moduleId) - { -/******/ -/******/ // Check if module is in cache -/******/ if (installedModules[moduleId]) { -/******/ return installedModules[moduleId].exports; -/******/ } -/******/ // Create a new module (and put it into the cache) -/******/ var module = installedModules[moduleId] = { -/******/ i: moduleId, -/******/ l: false, -/******/ exports: {} -/******/ }; -/******/ -/******/ // Execute the module function -/******/ modules[moduleId].call(module.exports, module, module.exports, __webpack_require__); -/******/ -/******/ // Flag the module as loaded -/******/ module.l = true; -/******/ -/******/ // Return the exports of the module -/******/ return module.exports; -/******/ } -/******/ -/******/ -/******/ // expose the modules object (__webpack_modules__) -/******/ __webpack_require__.m = modules; -/******/ -/******/ // expose the module cache -/******/ __webpack_require__.c = installedModules; -/******/ -/******/ // define getter function for harmony exports -/******/ __webpack_require__.d = function (exports, name, getter) { -/******/ if (!__webpack_require__.o(exports, name)) { -/******/ Object.defineProperty(exports, name, { enumerable: true, get: getter }); -/******/ } -/******/ }; -/******/ -/******/ // define __esModule on exports -/******/ __webpack_require__.r = function (exports) { -/******/ if (typeof Symbol !== 'undefined' && Symbol.toStringTag) { -/******/ Object.defineProperty(exports, Symbol.toStringTag, { value: 'Module' }); -/******/ } -/******/ Object.defineProperty(exports, '__esModule', { value: true }); -/******/ }; -/******/ -/******/ // create a fake namespace object -/******/ // mode & 1: value is a module id, require it -/******/ // mode & 2: merge all properties of value into the ns -/******/ // mode & 4: return value when already ns object -/******/ // mode & 8|1: behave like require -/******/ __webpack_require__.t = function (value, mode) { -/******/ if (mode & 1) { - value = __webpack_require__(value); -} -/******/ if (mode & 8) { - return value; -} -/******/ if ((mode & 4) && typeof value === 'object' && value && value.__esModule) { - return value; -} -/******/ var ns = Object.create(null); -/******/ __webpack_require__.r(ns); -/******/ Object.defineProperty(ns, 'default', { enumerable: true, value: value }); -/******/ if (mode & 2 && typeof value != 'string') { - for (var key in value) { - __webpack_require__.d(ns, key, function (key) { - return value[key]; }.bind(null, key)); - } -} -/******/ return ns; -/******/ }; -/******/ -/******/ // getDefaultExport function for compatibility with non-harmony modules -/******/ __webpack_require__.n = function (module) { -/******/ var getter = module && module.__esModule ? -/******/ function getDefault() - { - return module['default']; } : -/******/ function getModuleExports() -{ - return module; }; -/******/ __webpack_require__.d(getter, 'a', getter); -/******/ return getter; -/******/ }; -/******/ -/******/ // Object.prototype.hasOwnProperty.call -/******/ __webpack_require__.o = function (object, property) { - return Object.prototype.hasOwnProperty.call(object, property); }; -/******/ -/******/ // __webpack_public_path__ -/******/ __webpack_require__.p = ""; -/******/ -/******/ -/******/ // Load entry module and return exports -/******/ return __webpack_require__(__webpack_require__.s = "./resources/js/button.js"); -/******/ })({ - - /***/ "./resources/js/button.js": - /*!********************************!*\ - !*** ./resources/js/button.js ***! - \********************************/ - /*! no exports provided */ - /***/ (function (module, __webpack_exports__, __webpack_require__) { - - "use strict"; - __webpack_require__.r(__webpack_exports__); - /* harmony import */ var _modules_Renderer__WEBPACK_IMPORTED_MODULE_0__ = __webpack_require__(/*! ./modules/Renderer */ "./resources/js/modules/Renderer.js"); - /* harmony import */ var _modules_SingleProductConfig__WEBPACK_IMPORTED_MODULE_1__ = __webpack_require__(/*! ./modules/SingleProductConfig */ "./resources/js/modules/SingleProductConfig.js"); - /* harmony import */ var _modules_UpdateCart__WEBPACK_IMPORTED_MODULE_2__ = __webpack_require__(/*! ./modules/UpdateCart */ "./resources/js/modules/UpdateCart.js"); - /* harmony import */ var _modules_ErrorHandler__WEBPACK_IMPORTED_MODULE_3__ = __webpack_require__(/*! ./modules/ErrorHandler */ "./resources/js/modules/ErrorHandler.js"); - - - - - - document.addEventListener('DOMContentLoaded', () => { - if (!typeof PayPalCommerceGateway) { - console.error('PayPal button could not be configured.'); - return; - } - if (!document.querySelector(PayPalCommerceGateway.button.wrapper)) { - console.error('No wrapper for PayPal button found.'); - return; - } - const context = PayPalCommerceGateway.context; - if (context === 'product' && !document.querySelector('form.cart')) { - return; - } - - const errorHandler = new _modules_ErrorHandler__WEBPACK_IMPORTED_MODULE_3__["default"](); - const renderer = new _modules_Renderer__WEBPACK_IMPORTED_MODULE_0__["default"]({ - url: PayPalCommerceGateway.button.url, - wrapper: PayPalCommerceGateway.button.wrapper - }); - - const updateCart = new _modules_UpdateCart__WEBPACK_IMPORTED_MODULE_2__["default"](PayPalCommerceGateway.ajax.change_cart.endpoint, PayPalCommerceGateway.ajax.change_cart.nonce); - let configurator = null; - if (context === 'product') { - configurator = new _modules_SingleProductConfig__WEBPACK_IMPORTED_MODULE_1__["default"](PayPalCommerceGateway, updateCart, renderer.showButtons.bind(renderer), renderer.hideButtons.bind(renderer), document.querySelector('form.cart'), errorHandler); - } - if (!configurator) { - console.error('No context for button found.'); - return; - } - renderer.render(configurator.configuration()); - }); - - /***/ }), - - /***/ "./resources/js/modules/ButtonsToggleListener.js": - /*!*******************************************************!*\ - !*** ./resources/js/modules/ButtonsToggleListener.js ***! - \*******************************************************/ - /*! exports provided: default */ - /***/ (function (module, __webpack_exports__, __webpack_require__) { - - "use strict"; - __webpack_require__.r(__webpack_exports__); - /** - * When you can't add something to the cart, the PayPal buttons should not show. - * Therefore we listen for changes on the add to cart button and show/hide the buttons accordingly. - */ - - class ButtonsToggleListener { - constructor(element, showCallback, hideCallback) - { - this.element = element; - this.showCallback = showCallback; - this.hideCallback = hideCallback; - this.observer = null; - } - - init() - { - const config = { attributes: true }; - const callback = () => { - if (this.element.classList.contains('disabled')) { - this.hideCallback(); - return; - } - this.showCallback(); - }; - this.observer = new MutationObserver(callback); - this.observer.observe(this.element, config); - } - - disconnect() - { - this.observer.disconnect(); - } - } - - /* harmony default export */ __webpack_exports__["default"] = (ButtonsToggleListener); - - /***/ }), - - /***/ "./resources/js/modules/ErrorHandler.js": - /*!**********************************************!*\ - !*** ./resources/js/modules/ErrorHandler.js ***! - \**********************************************/ - /*! exports provided: default */ - /***/ (function (module, __webpack_exports__, __webpack_require__) { - - "use strict"; - __webpack_require__.r(__webpack_exports__); - class ErrorHandler { - - constructor() - { - this.wrapper = document.querySelector('.woocommerce-notices-wrapper'); - } - - message(text) - { - this.wrapper.classList.add('woocommerce-error'); - this.wrapper.innerText = this.sanitize(text); - } - - sanitize(text) - { - const textarea = document.createElement('textarea'); - textarea.innerHTML = text; - return textarea.value; - } - - clear() - { - if (!this.wrapper.classList.contains('woocommerce-error')) { - return; - } - this.wrapper.classList.remove('woocommerce-error'); - this.wrapper.innerText = ''; - } - } - - /* harmony default export */ __webpack_exports__["default"] = (ErrorHandler); - - /***/ }), - - /***/ "./resources/js/modules/Renderer.js": - /*!******************************************!*\ - !*** ./resources/js/modules/Renderer.js ***! - \******************************************/ - /*! exports provided: default */ - /***/ (function (module, __webpack_exports__, __webpack_require__) { - - "use strict"; - __webpack_require__.r(__webpack_exports__); - class Renderer { - - constructor(config) - { - this.config = config; - } - - render(buttonConfig) - { - - const script = document.createElement('script'); - - if (typeof paypal !== 'object') { - script.setAttribute('src', this.config.url); - script.addEventListener('load', event => { - this.renderButtons(buttonConfig); - }); - document.body.append(script); - return; - } - - this.renderButtons(buttonConfig); - } - - renderButtons(buttonConfig) - { - - paypal.Buttons(buttonConfig).render(this.config.wrapper); - } - - hideButtons() - { - document.querySelector(this.config.wrapper).style.display = 'none'; - } - - showButtons() - { - document.querySelector(this.config.wrapper).style.display = 'block'; - } - } - - /* harmony default export */ __webpack_exports__["default"] = (Renderer); - - /***/ }), - - /***/ "./resources/js/modules/SingleProductConfig.js": - /*!*****************************************************!*\ - !*** ./resources/js/modules/SingleProductConfig.js ***! - \*****************************************************/ - /*! exports provided: default */ - /***/ (function (module, __webpack_exports__, __webpack_require__) { - - "use strict"; - __webpack_require__.r(__webpack_exports__); - /* harmony import */ var _ButtonsToggleListener__WEBPACK_IMPORTED_MODULE_0__ = __webpack_require__(/*! ./ButtonsToggleListener */ "./resources/js/modules/ButtonsToggleListener.js"); - - - class SingleProductConfig { - - constructor(config, updateCart, showButtonCallback, hideButtonCallback, formElement, errorHandler) - { - this.config = config; - this.updateCart = updateCart; - this.showButtonCallback = showButtonCallback; - this.hideButtonCallback = hideButtonCallback; - this.formElement = formElement; - this.errorHandler = errorHandler; - } - - configuration() - { - - if (this.hasVariations()) { - const observer = new _ButtonsToggleListener__WEBPACK_IMPORTED_MODULE_0__["default"](this.formElement.querySelector('.single_add_to_cart_button'), this.showButtonCallback, this.hideButtonCallback); - observer.init(); - } - const onApprove = (data, actions) => { - return actions.redirect(this.config.redirect); - }; - return { - createOrder: this.createOrder(), - onApprove, - onError: error => { - this.errorHandler.message(error); - } - }; - } - - createOrder() - { - const createOrder = (data, actions) => { - this.errorHandler.clear(); - const product = document.querySelector('[name="add-to-cart"]').value; - const qty = document.querySelector('[name="quantity"]').value; - const variations = this.variations(); - - const onResolve = purchase_units => { - return fetch(this.config.ajax.create_order.endpoint, { - method: 'POST', - body: JSON.stringify({ - nonce: this.config.ajax.create_order.nonce, - purchase_units - }) - }).then(function (res) { - return res.json(); - }).then(function (data) { - if (!data.success) { - //Todo: Error handling - return; - } - return data.data.id; - }); - }; - - const promise = this.updateCart.update(onResolve, product, qty, variations); - return promise; - }; - return createOrder; - } - - variations() - { - - if (!this.hasVariations()) { - return null; - } - const attributes = [...this.formElement.querySelectorAll("[name^='attribute_']")].map(element => { - return { - value: element.value, - name: element.name - }; - }); - return attributes; - } - - hasVariations() - { - return this.formElement.classList.contains('variations_form'); - } - } - - /* harmony default export */ __webpack_exports__["default"] = (SingleProductConfig); - - /***/ }), - - /***/ "./resources/js/modules/UpdateCart.js": - /*!********************************************!*\ - !*** ./resources/js/modules/UpdateCart.js ***! - \********************************************/ - /*! exports provided: default */ - /***/ (function (module, __webpack_exports__, __webpack_require__) { - - "use strict"; - __webpack_require__.r(__webpack_exports__); - class UpdateCart { - - constructor(endpoint, nonce) - { - this.endpoint = endpoint; - this.nonce = nonce; - } - - update(onResolve, product, qty, variations) - { - return new Promise((resolve, reject) => { - fetch(this.endpoint, { - method: 'POST', - body: JSON.stringify({ - nonce: this.nonce, - product, - qty, - variations - }) - }).then(result => { - return result.json(); - }).then(result => { - if (!result.success) { - reject(result.data); - return; - } - - const resolved = onResolve(result.data); - resolve(resolved); - }); - }); - } - } - - /* harmony default export */ __webpack_exports__["default"] = (UpdateCart); - - /***/ }) - -/******/ }); +!function(e){var t={};function r(n){if(t[n])return t[n].exports;var o=t[n]={i:n,l:!1,exports:{}};return e[n].call(o.exports,o,o.exports,r),o.l=!0,o.exports}r.m=e,r.c=t,r.d=function(e,t,n){r.o(e,t)||Object.defineProperty(e,t,{enumerable:!0,get:n})},r.r=function(e){"undefined"!=typeof Symbol&&Symbol.toStringTag&&Object.defineProperty(e,Symbol.toStringTag,{value:"Module"}),Object.defineProperty(e,"__esModule",{value:!0})},r.t=function(e,t){if(1&t&&(e=r(e)),8&t)return e;if(4&t&&"object"==typeof e&&e&&e.__esModule)return e;var n=Object.create(null);if(r.r(n),Object.defineProperty(n,"default",{enumerable:!0,value:e}),2&t&&"string"!=typeof e)for(var o in e)r.d(n,o,function(t){return e[t]}.bind(null,o));return n},r.n=function(e){var t=e&&e.__esModule?function(){return e.default}:function(){return e};return r.d(t,"a",t),t},r.o=function(e,t){return Object.prototype.hasOwnProperty.call(e,t)},r.p="",r(r.s=0)}([function(e,t,r){"use strict";r.r(t);var n=class{constructor(e){this.config=e}render(e){const t=document.createElement("script");if("object"!=typeof paypal)return t.setAttribute("src",this.config.url),t.addEventListener("load",t=>{this.renderButtons(e)}),void document.body.append(t);this.renderButtons(e)}renderButtons(e){paypal.Buttons(e).render(this.config.wrapper)}hideButtons(){document.querySelector(this.config.wrapper).style.display="none"}showButtons(){document.querySelector(this.config.wrapper).style.display="block"}};var o=class{constructor(e,t,r){this.element=e,this.showCallback=t,this.hideCallback=r,this.observer=null}init(){this.observer=new MutationObserver(()=>{this.element.classList.contains("disabled")?this.hideCallback():this.showCallback()}),this.observer.observe(this.element,{attributes:!0})}disconnect(){this.observer.disconnect()}};var a=class{constructor(e,t,r){this.id=e,this.quantity=t,this.variations=r}data(){return{id:this.id,quantity:this.quantity,variations:this.variations}}};var i=class{constructor(e,t,r,n,o,a){this.config=e,this.updateCart=t,this.showButtonCallback=r,this.hideButtonCallback=n,this.formElement=o,this.errorHandler=a}configuration(){if(this.hasVariations()){new o(this.formElement.querySelector(".single_add_to_cart_button"),this.showButtonCallback,this.hideButtonCallback).init()}return{createOrder:this.createOrder(),onApprove:(e,t)=>t.redirect(this.config.redirect),onError:e=>{this.errorHandler.message(e)}}}createOrder(){return this.isGroupedProduct()?createOrder:(e,t)=>{this.errorHandler.clear();const r=document.querySelector('[name="add-to-cart"]').value,n=document.querySelector('[name="quantity"]').value,o=this.variations(),i=new a(r,n,o);return this.updateCart.update(e=>fetch(this.config.ajax.create_order.endpoint,{method:"POST",body:JSON.stringify({nonce:this.config.ajax.create_order.nonce,purchase_units:e})}).then((function(e){return e.json()})).then((function(e){if(e.success)return e.data.id})),[i])}}variations(){if(!this.hasVariations())return null;return[...this.formElement.querySelectorAll("[name^='attribute_']")].map(e=>({value:e.value,name:e.name}))}hasVariations(){return this.formElement.classList.contains("variations_form")}isGroupedProduct(){return null!==this.formElement.querySelector(".woocommerce-grouped-product-list")}};var s=class{constructor(e,t){this.endpoint=e,this.nonce=t}update(e,t){return new Promise((r,n)=>{fetch(this.endpoint,{method:"POST",body:JSON.stringify({nonce:this.nonce,products:t})}).then(e=>e.json()).then(t=>{if(!t.success)return void n(t.data);const o=e(t.data);r(o)})})}};var c=class{constructor(){this.wrapper=document.querySelector(".woocommerce-notices-wrapper")}message(e){this.wrapper.classList.add("woocommerce-error"),this.wrapper.innerText=this.sanitize(e)}sanitize(e){const t=document.createElement("textarea");return t.innerHTML=e,t.value}clear(){this.wrapper.classList.contains("woocommerce-error")&&(this.wrapper.classList.remove("woocommerce-error"),this.wrapper.innerText="")}};document.addEventListener("DOMContentLoaded",()=>{if(!document.querySelector(PayPalCommerceGateway.button.wrapper))return void console.error("No wrapper for PayPal button found.");const e=PayPalCommerceGateway.context;if("product"===e&&!document.querySelector("form.cart"))return;const t=new c,r=new n({url:PayPalCommerceGateway.button.url,wrapper:PayPalCommerceGateway.button.wrapper}),o=new s(PayPalCommerceGateway.ajax.change_cart.endpoint,PayPalCommerceGateway.ajax.change_cart.nonce);let a=null;"product"===e&&(a=new i(PayPalCommerceGateway,o,r.showButtons.bind(r),r.hideButtons.bind(r),document.querySelector("form.cart"),t)),a?r.render(a.configuration()):console.error("No context for button found.")})}]); //# sourceMappingURL=button.js.map \ No newline at end of file diff --git a/modules.local/ppcp-button/assets/js/button.js.map b/modules.local/ppcp-button/assets/js/button.js.map index 909c91b87..1ad6da4f1 100644 --- a/modules.local/ppcp-button/assets/js/button.js.map +++ b/modules.local/ppcp-button/assets/js/button.js.map @@ -1 +1 @@ -{"version":3,"sources":["webpack:///webpack/bootstrap","webpack:///./resources/js/button.js","webpack:///./resources/js/modules/ButtonsToggleListener.js","webpack:///./resources/js/modules/ErrorHandler.js","webpack:///./resources/js/modules/Renderer.js","webpack:///./resources/js/modules/SingleProductConfig.js","webpack:///./resources/js/modules/UpdateCart.js"],"names":["document","addEventListener","PayPalCommerceGateway","console","error","querySelector","button","wrapper","context","errorHandler","ErrorHandler","renderer","Renderer","url","updateCart","UpdateCart","ajax","change_cart","endpoint","nonce","configurator","SingleProductConfig","showButtons","bind","hideButtons","render","configuration","ButtonsToggleListener","constructor","element","showCallback","hideCallback","observer","init","config","attributes","callback","classList","contains","MutationObserver","observe","disconnect","message","text","add","innerText","sanitize","textarea","createElement","innerHTML","value","clear","remove","buttonConfig","script","paypal","setAttribute","event","renderButtons","body","append","Buttons","style","display","showButtonCallback","hideButtonCallback","formElement","hasVariations","onApprove","data","actions","redirect","createOrder","onError","product","qty","variations","onResolve","purchase_units","fetch","create_order","method","JSON","stringify","then","res","json","success","id","promise","update","querySelectorAll","map","name","Promise","resolve","reject","result","resolved"],"mappings":"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","file":"js/button.js","sourcesContent":[" \t// The module cache\n \tvar installedModules = {};\n\n \t// The require function\n \tfunction __webpack_require__(moduleId) {\n\n \t\t// Check if module is in cache\n \t\tif(installedModules[moduleId]) {\n \t\t\treturn installedModules[moduleId].exports;\n \t\t}\n \t\t// Create a new module (and put it into the cache)\n \t\tvar module = installedModules[moduleId] = {\n \t\t\ti: moduleId,\n \t\t\tl: false,\n \t\t\texports: {}\n \t\t};\n\n \t\t// Execute the module function\n \t\tmodules[moduleId].call(module.exports, module, module.exports, __webpack_require__);\n\n \t\t// Flag the module as loaded\n \t\tmodule.l = true;\n\n \t\t// Return the exports of the module\n \t\treturn module.exports;\n \t}\n\n\n \t// expose the modules object (__webpack_modules__)\n \t__webpack_require__.m = modules;\n\n \t// expose the module cache\n \t__webpack_require__.c = installedModules;\n\n \t// define getter function for harmony exports\n \t__webpack_require__.d = function(exports, name, getter) {\n \t\tif(!__webpack_require__.o(exports, name)) {\n \t\t\tObject.defineProperty(exports, name, { enumerable: true, get: getter });\n \t\t}\n \t};\n\n \t// define __esModule on exports\n \t__webpack_require__.r = function(exports) {\n \t\tif(typeof Symbol !== 'undefined' && Symbol.toStringTag) {\n \t\t\tObject.defineProperty(exports, Symbol.toStringTag, { value: 'Module' });\n \t\t}\n \t\tObject.defineProperty(exports, '__esModule', { value: true });\n \t};\n\n \t// create a fake namespace object\n \t// mode & 1: value is a module id, require it\n \t// mode & 2: merge all properties of value into the ns\n \t// mode & 4: return value when already ns object\n \t// mode & 8|1: behave like require\n \t__webpack_require__.t = function(value, mode) {\n \t\tif(mode & 1) value = __webpack_require__(value);\n \t\tif(mode & 8) return value;\n \t\tif((mode & 4) && typeof value === 'object' && value && value.__esModule) return value;\n \t\tvar ns = Object.create(null);\n \t\t__webpack_require__.r(ns);\n \t\tObject.defineProperty(ns, 'default', { enumerable: true, value: value });\n \t\tif(mode & 2 && typeof value != 'string') for(var key in value) __webpack_require__.d(ns, key, function(key) { return value[key]; }.bind(null, key));\n \t\treturn ns;\n \t};\n\n \t// getDefaultExport function for compatibility with non-harmony modules\n \t__webpack_require__.n = function(module) {\n \t\tvar getter = module && module.__esModule ?\n \t\t\tfunction getDefault() { return module['default']; } :\n \t\t\tfunction getModuleExports() { return module; };\n \t\t__webpack_require__.d(getter, 'a', getter);\n \t\treturn getter;\n \t};\n\n \t// Object.prototype.hasOwnProperty.call\n \t__webpack_require__.o = function(object, property) { return Object.prototype.hasOwnProperty.call(object, property); };\n\n \t// __webpack_public_path__\n \t__webpack_require__.p = \"\";\n\n\n \t// Load entry module and return exports\n \treturn __webpack_require__(__webpack_require__.s = \"./resources/js/button.js\");\n","import Renderer from './modules/Renderer';\nimport SingleProductConfig from './modules/SingleProductConfig';\nimport UpdateCart from './modules/UpdateCart';\nimport ErrorHandler from './modules/ErrorHandler';\n\ndocument.addEventListener(\n 'DOMContentLoaded',\n () => {\n if (! typeof(PayPalCommerceGateway)) {\n console.error('PayPal button could not be configured.');\n return;\n }\n if (! document.querySelector(PayPalCommerceGateway.button.wrapper)) {\n console.error('No wrapper for PayPal button found.');\n return;\n }\n const context = PayPalCommerceGateway.context;\n if (context === 'product' && ! document.querySelector('form.cart') ) {\n return;\n }\n\n const errorHandler = new ErrorHandler();\n const renderer = new Renderer({\n url: PayPalCommerceGateway.button.url,\n wrapper:PayPalCommerceGateway.button.wrapper\n });\n\n\n const updateCart = new UpdateCart(\n PayPalCommerceGateway.ajax.change_cart.endpoint,\n PayPalCommerceGateway.ajax.change_cart.nonce\n );\n let configurator = null;\n if (context === 'product') {\n configurator = new SingleProductConfig(\n PayPalCommerceGateway,\n updateCart,\n renderer.showButtons.bind(renderer),\n renderer.hideButtons.bind(renderer),\n document.querySelector('form.cart'),\n errorHandler\n );\n }\n if (! configurator) {\n console.error('No context for button found.');\n return;\n }\n renderer.render(configurator.configuration());\n\n }\n);","/**\n * When you can't add something to the cart, the PayPal buttons should not show.\n * Therefore we listen for changes on the add to cart button and show/hide the buttons accordingly.\n */\n\nclass ButtonsToggleListener {\n constructor(element, showCallback, hideCallback) {\n this.element = element;\n this.showCallback = showCallback;\n this.hideCallback = hideCallback;\n this.observer = null;\n }\n\n init() {\n const config = { attributes : true };\n const callback = () => {\n if (this.element.classList.contains('disabled')) {\n this.hideCallback();\n return;\n }\n this.showCallback();\n }\n this.observer = new MutationObserver(callback);\n this.observer.observe(this.element, config);\n }\n\n disconnect() {\n this.observer.disconnect();\n }\n}\n\nexport default ButtonsToggleListener;","class ErrorHandler {\n\n constructor() {\n this.wrapper = document.querySelector('.woocommerce-notices-wrapper');\n }\n\n message(text) {\n this.wrapper.classList.add('woocommerce-error');\n this.wrapper.innerText = this.sanitize(text);\n }\n\n sanitize(text) {\n const textarea = document.createElement('textarea');\n textarea.innerHTML = text;\n return textarea.value;\n }\n\n clear() {\n if (! this.wrapper.classList.contains('woocommerce-error')) {\n return;\n }\n this.wrapper.classList.remove('woocommerce-error');\n this.wrapper.innerText = '';\n }\n}\n\nexport default ErrorHandler;","class Renderer {\n\n constructor(config) {\n this.config = config;\n }\n\n render(buttonConfig) {\n\n const script = document.createElement('script');\n\n if (typeof paypal !== 'object') {\n script.setAttribute('src', this.config.url);\n script.addEventListener('load', (event) => {\n this.renderButtons(buttonConfig);\n })\n document.body.append(script);\n return;\n }\n\n this.renderButtons(buttonConfig);\n }\n\n renderButtons(buttonConfig) {\n\n paypal.Buttons(\n buttonConfig\n ).render(this.config.wrapper);\n }\n\n hideButtons() {\n document.querySelector(this.config.wrapper).style.display = 'none';\n }\n\n showButtons() {\n document.querySelector(this.config.wrapper).style.display = 'block';\n }\n}\n\nexport default Renderer;","import ButtonsToggleListener from \"./ButtonsToggleListener\";\n\nclass SingleProductConfig {\n\n constructor(\n config,\n updateCart,\n showButtonCallback,\n hideButtonCallback,\n formElement,\n errorHandler\n ) {\n this.config = config;\n this.updateCart = updateCart;\n this.showButtonCallback = showButtonCallback;\n this.hideButtonCallback = hideButtonCallback;\n this.formElement = formElement;\n this.errorHandler = errorHandler;\n }\n\n configuration() {\n\n if ( this.hasVariations() ) {\n const observer = new ButtonsToggleListener(\n this.formElement.querySelector('.single_add_to_cart_button'),\n this.showButtonCallback,\n this.hideButtonCallback\n );\n observer.init();\n }\n const onApprove = (data, actions) => {\n return actions.redirect(this.config.redirect);\n }\n return {\n createOrder: this.createOrder(),\n onApprove,\n onError: (error) => {\n this.errorHandler.message(error);\n }\n }\n }\n\n createOrder() {\n const createOrder = (data, actions) => {\n this.errorHandler.clear();\n const product = document.querySelector('[name=\"add-to-cart\"]').value;\n const qty = document.querySelector('[name=\"quantity\"]').value;\n const variations = this.variations();\n\n const onResolve = (purchase_units) => {\n return fetch(this.config.ajax.create_order.endpoint, {\n method: 'POST',\n body: JSON.stringify({\n nonce:this.config.ajax.create_order.nonce,\n purchase_units\n })\n }).then(function(res) {\n return res.json();\n }).then(function(data) {\n if (! data.success) {\n //Todo: Error handling\n return;\n }\n return data.data.id;\n });\n };\n\n const promise = this.updateCart.update(onResolve, product, qty, variations);\n return promise;\n };\n return createOrder;\n }\n\n variations() {\n\n if (! this.hasVariations()) {\n return null;\n }\n const attributes = [...this.formElement.querySelectorAll(\"[name^='attribute_']\")].map(\n (element) => {\n return {\n value:element.value,\n name:element.name\n }\n }\n );\n return attributes;\n }\n\n hasVariations() {\n return this.formElement.classList.contains('variations_form');\n }\n}\n\nexport default SingleProductConfig;","class UpdateCart {\n\n constructor(endpoint, nonce) {\n this.endpoint = endpoint;\n this.nonce = nonce;\n }\n\n update(onResolve, product, qty, variations) {\n return new Promise( (resolve, reject) => {\n fetch(\n this.endpoint,\n {\n method: 'POST',\n body: JSON.stringify({\n nonce: this.nonce,\n product,\n qty,\n variations\n })\n }\n ).then(\n (result) => {\n return result.json();\n }\n ).then( (result) => {\n if (! result.success) {\n reject(result.data);\n return;\n }\n\n const resolved = onResolve(result.data);\n resolve(resolved);\n }\n )\n });\n }\n}\n\nexport default UpdateCart;"],"sourceRoot":""} \ No newline at end of file +{"version":3,"sources":["webpack:///webpack/bootstrap","webpack:///./resources/js/modules/Renderer.js","webpack:///./resources/js/modules/ButtonsToggleListener.js","webpack:///./resources/js/modules/Product.js","webpack:///./resources/js/modules/SingleProductConfig.js","webpack:///./resources/js/modules/UpdateCart.js","webpack:///./resources/js/modules/ErrorHandler.js","webpack:///./resources/js/button.js"],"names":["installedModules","__webpack_require__","moduleId","exports","module","i","l","modules","call","m","c","d","name","getter","o","Object","defineProperty","enumerable","get","r","Symbol","toStringTag","value","t","mode","__esModule","ns","create","key","bind","n","object","property","prototype","hasOwnProperty","p","s","Renderer","constructor","config","this","render","buttonConfig","script","document","createElement","paypal","setAttribute","url","addEventListener","event","renderButtons","body","append","Buttons","wrapper","hideButtons","querySelector","style","display","showButtons","ButtonsToggleListener","element","showCallback","hideCallback","observer","init","MutationObserver","classList","contains","observe","attributes","disconnect","Product","id","quantity","variations","data","SingleProductConfig","updateCart","showButtonCallback","hideButtonCallback","formElement","errorHandler","configuration","hasVariations","createOrder","onApprove","actions","redirect","onError","error","message","isGroupedProduct","clear","qty","product","update","purchase_units","fetch","ajax","create_order","endpoint","method","JSON","stringify","nonce","then","res","json","success","querySelectorAll","map","UpdateCart","onResolve","products","Promise","resolve","reject","result","resolved","ErrorHandler","text","add","innerText","sanitize","textarea","innerHTML","remove","PayPalCommerceGateway","button","console","context","renderer","change_cart","configurator"],"mappings":"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","file":"js/button.js","sourcesContent":[" \t// The module cache\n \tvar installedModules = {};\n\n \t// The require function\n \tfunction __webpack_require__(moduleId) {\n\n \t\t// Check if module is in cache\n \t\tif(installedModules[moduleId]) {\n \t\t\treturn installedModules[moduleId].exports;\n \t\t}\n \t\t// Create a new module (and put it into the cache)\n \t\tvar module = installedModules[moduleId] = {\n \t\t\ti: moduleId,\n \t\t\tl: false,\n \t\t\texports: {}\n \t\t};\n\n \t\t// Execute the module function\n \t\tmodules[moduleId].call(module.exports, module, module.exports, __webpack_require__);\n\n \t\t// Flag the module as loaded\n \t\tmodule.l = true;\n\n \t\t// Return the exports of the module\n \t\treturn module.exports;\n \t}\n\n\n \t// expose the modules object (__webpack_modules__)\n \t__webpack_require__.m = modules;\n\n \t// expose the module cache\n \t__webpack_require__.c = installedModules;\n\n \t// define getter function for harmony exports\n \t__webpack_require__.d = function(exports, name, getter) {\n \t\tif(!__webpack_require__.o(exports, name)) {\n \t\t\tObject.defineProperty(exports, name, { enumerable: true, get: getter });\n \t\t}\n \t};\n\n \t// define __esModule on exports\n \t__webpack_require__.r = function(exports) {\n \t\tif(typeof Symbol !== 'undefined' && Symbol.toStringTag) {\n \t\t\tObject.defineProperty(exports, Symbol.toStringTag, { value: 'Module' });\n \t\t}\n \t\tObject.defineProperty(exports, '__esModule', { value: true });\n \t};\n\n \t// create a fake namespace object\n \t// mode & 1: value is a module id, require it\n \t// mode & 2: merge all properties of value into the ns\n \t// mode & 4: return value when already ns object\n \t// mode & 8|1: behave like require\n \t__webpack_require__.t = function(value, mode) {\n \t\tif(mode & 1) value = __webpack_require__(value);\n \t\tif(mode & 8) return value;\n \t\tif((mode & 4) && typeof value === 'object' && value && value.__esModule) return value;\n \t\tvar ns = Object.create(null);\n \t\t__webpack_require__.r(ns);\n \t\tObject.defineProperty(ns, 'default', { enumerable: true, value: value });\n \t\tif(mode & 2 && typeof value != 'string') for(var key in value) __webpack_require__.d(ns, key, function(key) { return value[key]; }.bind(null, key));\n \t\treturn ns;\n \t};\n\n \t// getDefaultExport function for compatibility with non-harmony modules\n \t__webpack_require__.n = function(module) {\n \t\tvar getter = module && module.__esModule ?\n \t\t\tfunction getDefault() { return module['default']; } :\n \t\t\tfunction getModuleExports() { return module; };\n \t\t__webpack_require__.d(getter, 'a', getter);\n \t\treturn getter;\n \t};\n\n \t// Object.prototype.hasOwnProperty.call\n \t__webpack_require__.o = function(object, property) { return Object.prototype.hasOwnProperty.call(object, property); };\n\n \t// __webpack_public_path__\n \t__webpack_require__.p = \"\";\n\n\n \t// Load entry module and return exports\n \treturn __webpack_require__(__webpack_require__.s = 0);\n","class Renderer {\n\n constructor(config)\n {\n this.config = config;\n }\n\n render(buttonConfig)\n {\n\n const script = document.createElement('script');\n\n if (typeof paypal !== 'object') {\n script.setAttribute('src', this.config.url);\n script.addEventListener('load', (event) => {\n this.renderButtons(buttonConfig);\n })\n document.body.append(script);\n return;\n }\n\n this.renderButtons(buttonConfig);\n }\n\n renderButtons(buttonConfig)\n {\n\n paypal.Buttons(\n buttonConfig\n ).render(this.config.wrapper);\n }\n\n hideButtons()\n {\n document.querySelector(this.config.wrapper).style.display = 'none';\n }\n\n showButtons()\n {\n document.querySelector(this.config.wrapper).style.display = 'block';\n }\n}\n\nexport default Renderer;","/**\n * When you can't add something to the cart, the PayPal buttons should not show.\n * Therefore we listen for changes on the add to cart button and show/hide the buttons accordingly.\n */\n\nclass ButtonsToggleListener {\n constructor(element, showCallback, hideCallback)\n {\n this.element = element;\n this.showCallback = showCallback;\n this.hideCallback = hideCallback;\n this.observer = null;\n }\n\n init()\n {\n const config = { attributes : true };\n const callback = () => {\n if (this.element.classList.contains('disabled')) {\n this.hideCallback();\n return;\n }\n this.showCallback();\n }\n this.observer = new MutationObserver(callback);\n this.observer.observe(this.element, config);\n }\n\n disconnect()\n {\n this.observer.disconnect();\n }\n}\n\nexport default ButtonsToggleListener;","class Product {\n\n constructor(id, quantity, variations) {\n this.id = id;\n this.quantity = quantity;\n this.variations = variations;\n }\n\n data() {\n return {\n id:this.id,\n quantity:this.quantity,\n variations:this.variations\n }\n }\n}\n\nexport default Product;","import ButtonsToggleListener from \"./ButtonsToggleListener\";\nimport Product from \"./Product\";\nclass SingleProductConfig {\n\n constructor(\n config,\n updateCart,\n showButtonCallback,\n hideButtonCallback,\n formElement,\n errorHandler\n ) {\n this.config = config;\n this.updateCart = updateCart;\n this.showButtonCallback = showButtonCallback;\n this.hideButtonCallback = hideButtonCallback;\n this.formElement = formElement;\n this.errorHandler = errorHandler;\n }\n\n configuration()\n {\n\n if ( this.hasVariations() ) {\n const observer = new ButtonsToggleListener(\n this.formElement.querySelector('.single_add_to_cart_button'),\n this.showButtonCallback,\n this.hideButtonCallback\n );\n observer.init();\n }\n const onApprove = (data, actions) => {\n return actions.redirect(this.config.redirect);\n }\n return {\n createOrder: this.createOrder(),\n onApprove,\n onError: (error) => {\n this.errorHandler.message(error);\n }\n }\n }\n\n createOrder()\n {\n if (! this.isGroupedProduct() ) {\n return (data, actions) => {\n this.errorHandler.clear();\n const id = document.querySelector('[name=\"add-to-cart\"]').value;\n const qty = document.querySelector('[name=\"quantity\"]').value;\n const variations = this.variations();\n const product = new Product(id, qty, variations);\n\n const onResolve = (purchase_units) => {\n return fetch(this.config.ajax.create_order.endpoint, {\n method: 'POST',\n body: JSON.stringify({\n nonce: this.config.ajax.create_order.nonce,\n purchase_units\n })\n }).then(function (res) {\n return res.json();\n }).then(function (data) {\n if (!data.success) {\n //Todo: Error handling\n return;\n }\n return data.data.id;\n });\n };\n\n const promise = this.updateCart.update(onResolve, [product]);\n return promise;\n };\n }\n return createOrder;\n }\n\n variations()\n {\n\n if (! this.hasVariations()) {\n return null;\n }\n const attributes = [...this.formElement.querySelectorAll(\"[name^='attribute_']\")].map(\n (element) => {\n return {\n value:element.value,\n name:element.name\n }\n }\n );\n return attributes;\n }\n\n hasVariations()\n {\n return this.formElement.classList.contains('variations_form');\n }\n\n isGroupedProduct()\n {\n return this.formElement.querySelector('.woocommerce-grouped-product-list') !== null;\n }\n}\n\nexport default SingleProductConfig;","import Product from \"./Product\";\nclass UpdateCart {\n\n constructor(endpoint, nonce)\n {\n this.endpoint = endpoint;\n this.nonce = nonce;\n }\n\n /**\n *\n * @param onResolve\n * @param {Product[]} products\n * @returns {Promise}\n */\n update(onResolve, products)\n {\n return new Promise((resolve, reject) => {\n fetch(\n this.endpoint,\n {\n method: 'POST',\n body: JSON.stringify({\n nonce: this.nonce,\n products,\n })\n }\n ).then(\n (result) => {\n return result.json();\n }\n ).then((result) => {\n if (! result.success) {\n reject(result.data);\n return;\n }\n\n const resolved = onResolve(result.data);\n resolve(resolved);\n })\n });\n }\n}\n\nexport default UpdateCart;","class ErrorHandler {\n\n constructor()\n {\n this.wrapper = document.querySelector('.woocommerce-notices-wrapper');\n }\n\n message(text)\n {\n this.wrapper.classList.add('woocommerce-error');\n this.wrapper.innerText = this.sanitize(text);\n }\n\n sanitize(text)\n {\n const textarea = document.createElement('textarea');\n textarea.innerHTML = text;\n return textarea.value;\n }\n\n clear()\n {\n if (! this.wrapper.classList.contains('woocommerce-error')) {\n return;\n }\n this.wrapper.classList.remove('woocommerce-error');\n this.wrapper.innerText = '';\n }\n}\n\nexport default ErrorHandler;","import Renderer from './modules/Renderer';\nimport SingleProductConfig from './modules/SingleProductConfig';\nimport UpdateCart from './modules/UpdateCart';\nimport ErrorHandler from './modules/ErrorHandler';\n\ndocument.addEventListener(\n 'DOMContentLoaded',\n () => {\n if (! typeof(PayPalCommerceGateway)) {\n console.error('PayPal button could not be configured.');\n return;\n }\n if (! document.querySelector(PayPalCommerceGateway.button.wrapper)) {\n console.error('No wrapper for PayPal button found.');\n return;\n }\n const context = PayPalCommerceGateway.context;\n if (context === 'product' && ! document.querySelector('form.cart') ) {\n return;\n }\n const errorHandler = new ErrorHandler();\n const renderer = new Renderer({\n url: PayPalCommerceGateway.button.url,\n wrapper:PayPalCommerceGateway.button.wrapper\n });\n const updateCart = new UpdateCart(\n PayPalCommerceGateway.ajax.change_cart.endpoint,\n PayPalCommerceGateway.ajax.change_cart.nonce\n );\n let configurator = null;\n if (context === 'product') {\n configurator = new SingleProductConfig(\n PayPalCommerceGateway,\n updateCart,\n renderer.showButtons.bind(renderer),\n renderer.hideButtons.bind(renderer),\n document.querySelector('form.cart'),\n errorHandler\n );\n }\n if (! configurator) {\n console.error('No context for button found.');\n return;\n }\n renderer.render(configurator.configuration());\n }\n);"],"sourceRoot":""} \ No newline at end of file diff --git a/modules.local/ppcp-button/resources/js/modules/Product.js b/modules.local/ppcp-button/resources/js/modules/Product.js new file mode 100644 index 000000000..9f5648490 --- /dev/null +++ b/modules.local/ppcp-button/resources/js/modules/Product.js @@ -0,0 +1,18 @@ +class Product { + + constructor(id, quantity, variations) { + this.id = id; + this.quantity = quantity; + this.variations = variations; + } + + data() { + return { + id:this.id, + quantity:this.quantity, + variations:this.variations + } + } +} + +export default Product; \ No newline at end of file diff --git a/modules.local/ppcp-button/resources/js/modules/SingleProductConfig.js b/modules.local/ppcp-button/resources/js/modules/SingleProductConfig.js index d655ff708..442c6a136 100644 --- a/modules.local/ppcp-button/resources/js/modules/SingleProductConfig.js +++ b/modules.local/ppcp-button/resources/js/modules/SingleProductConfig.js @@ -1,5 +1,5 @@ import ButtonsToggleListener from "./ButtonsToggleListener"; - +import Product from "./Product"; class SingleProductConfig { constructor( @@ -43,33 +43,36 @@ class SingleProductConfig { createOrder() { - const createOrder = (data, actions) => { - this.errorHandler.clear(); - const product = document.querySelector('[name="add-to-cart"]').value; - const qty = document.querySelector('[name="quantity"]').value; - const variations = this.variations(); + if (! this.isGroupedProduct() ) { + return (data, actions) => { + this.errorHandler.clear(); + const id = document.querySelector('[name="add-to-cart"]').value; + const qty = document.querySelector('[name="quantity"]').value; + const variations = this.variations(); + const product = new Product(id, qty, variations); - const onResolve = (purchase_units) => { - return fetch(this.config.ajax.create_order.endpoint, { - method: 'POST', - body: JSON.stringify({ - nonce:this.config.ajax.create_order.nonce, - purchase_units - }) - }).then(function (res) { - return res.json(); - }).then(function (data) { - if (! data.success) { - //Todo: Error handling - return; - } - return data.data.id; - }); + const onResolve = (purchase_units) => { + return fetch(this.config.ajax.create_order.endpoint, { + method: 'POST', + body: JSON.stringify({ + nonce: this.config.ajax.create_order.nonce, + purchase_units + }) + }).then(function (res) { + return res.json(); + }).then(function (data) { + if (!data.success) { + //Todo: Error handling + return; + } + return data.data.id; + }); + }; + + const promise = this.updateCart.update(onResolve, [product]); + return promise; }; - - const promise = this.updateCart.update(onResolve, product, qty, variations); - return promise; - }; + } return createOrder; } @@ -94,6 +97,11 @@ class SingleProductConfig { { return this.formElement.classList.contains('variations_form'); } + + isGroupedProduct() + { + return this.formElement.querySelector('.woocommerce-grouped-product-list') !== null; + } } export default SingleProductConfig; \ No newline at end of file diff --git a/modules.local/ppcp-button/resources/js/modules/UpdateCart.js b/modules.local/ppcp-button/resources/js/modules/UpdateCart.js index bf5a5a437..08a324032 100644 --- a/modules.local/ppcp-button/resources/js/modules/UpdateCart.js +++ b/modules.local/ppcp-button/resources/js/modules/UpdateCart.js @@ -1,3 +1,4 @@ +import Product from "./Product"; class UpdateCart { constructor(endpoint, nonce) @@ -6,7 +7,13 @@ class UpdateCart { this.nonce = nonce; } - update(onResolve, product, qty, variations) + /** + * + * @param onResolve + * @param {Product[]} products + * @returns {Promise} + */ + update(onResolve, products) { return new Promise((resolve, reject) => { fetch( @@ -15,9 +22,7 @@ class UpdateCart { method: 'POST', body: JSON.stringify({ nonce: this.nonce, - product, - qty, - variations + products, }) } ).then( diff --git a/modules.local/ppcp-button/src/Endpoint/ChangeCartEndpoint.php b/modules.local/ppcp-button/src/Endpoint/ChangeCartEndpoint.php index b27b397d1..c19ad6a53 100644 --- a/modules.local/ppcp-button/src/Endpoint/ChangeCartEndpoint.php +++ b/modules.local/ppcp-button/src/Endpoint/ChangeCartEndpoint.php @@ -40,8 +40,8 @@ class ChangeCartEndpoint implements EndpointInterface try { $data = $this->requestData->readRequest($this->nonce()); - if (! isset($data['product']) - || ! isset($data['qty']) + if (! isset($data['products']) + || ! is_array($data['products']) ) { wp_send_json_error( __( @@ -51,23 +51,45 @@ class ChangeCartEndpoint implements EndpointInterface ); return false; } - $product = wc_get_product((int) $data['product']); - if (! $product) { - wp_send_json_error( - __( - 'No product defined. Action aborted.', - 'woocommerce-paypal-commerce-gateway' - ) - ); - return false; + + $products = []; + foreach ($data['products'] as $product) { + if (! isset($product['quantity']) || ! isset($product['id'])) { + wp_send_json_error( + __( + 'Necessary fields not defined. Action aborted.', + 'woocommerce-paypal-commerce-gateway' + ) + ); + return false; + } + + $wcProduct = wc_get_product((int) $product['id']); + if (! $wcProduct) { + wp_send_json_error( + __( + 'Product not found. Action aborted.', + 'woocommerce-paypal-commerce-gateway' + ) + ); + return false; + } + $products[] = [ + 'product' => $wcProduct, + 'quantity' => (int) $product['quantity'], + 'variations' => isset($product['variations']) ? $product['variations'] : null, + ]; + } - $quantity = (int) $data['qty']; $this->shipping->reset_shipping(); $this->cart->empty_cart(false); - $success = (! $product->is_type('variable')) ? - $success = $this->addProduct($product, $quantity) - : $this->addVariableProduct($product, $quantity, $data['variations']); + $success = true; + foreach ($products as $product) { + $success = $success && (! $product['product']->is_type('variable')) ? + $success = $this->addProduct($product['product'], $product['quantity']) + : $this->addVariableProduct($product['product'], $product['quantity'], $product['variations']); + } if (! $success) { $message = __('Something went wrong. Action aborted', 'woocommerce-paypal-commerce-gateway'); $errors = wc_get_notices('error');