/*
* ATTENTION: The "eval" devtool has been used (maybe by default in mode: "development").
* This devtool is neither made for production nor for readable output files.
* It uses "eval()" calls to create a separate source file in the browser devtools.
* If you are trying to read the output file, select a different devtool (https://webpack.js.org/configuration/devtool/)
* or disable the default devtool with "devtool: false".
* If you are looking for production-ready output files, see mode: "production" (https://webpack.js.org/configuration/mode/).
*/
/******/ (() => { // webpackBootstrap
/******/ var __webpack_modules__ = ({
/***/ "./node_modules/@wordpress/dom-ready/build-module/index.js":
/*!*****************************************************************!*\
!*** ./node_modules/@wordpress/dom-ready/build-module/index.js ***!
\*****************************************************************/
/***/ ((__unused_webpack_module, __webpack_exports__, __webpack_require__) => {
"use strict";
eval("__webpack_require__.r(__webpack_exports__);\n/* harmony export */ __webpack_require__.d(__webpack_exports__, {\n/* harmony export */ \"default\": () => (/* binding */ domReady)\n/* harmony export */ });\n/**\n * @typedef {() => void} Callback\n *\n * TODO: Remove this typedef and inline `() => void` type.\n *\n * This typedef is used so that a descriptive type is provided in our\n * automatically generated documentation.\n *\n * An in-line type `() => void` would be preferable, but the generated\n * documentation is `null` in that case.\n *\n * @see https://github.com/WordPress/gutenberg/issues/18045\n */\n\n/**\n * Specify a function to execute when the DOM is fully loaded.\n *\n * @param {Callback} callback A function to execute after the DOM is ready.\n *\n * @example\n * ```js\n * import domReady from '@wordpress/dom-ready';\n *\n * domReady( function() {\n * \t//do something after DOM loads.\n * } );\n * ```\n *\n * @return {void}\n */\nfunction domReady(callback) {\n if (typeof document === 'undefined') {\n return;\n }\n if (document.readyState === 'complete' ||\n // DOMContentLoaded + Images/Styles/etc loaded, so we call directly.\n document.readyState === 'interactive' // DOMContentLoaded fires at this point, so we call directly.\n ) {\n return void callback();\n }\n\n // DOMContentLoaded has not fired yet, delay callback until then.\n document.addEventListener('DOMContentLoaded', callback);\n}\n//# sourceMappingURL=index.js.map\n\n//# sourceURL=webpack://formidable-abandonment/./node_modules/@wordpress/dom-ready/build-module/index.js?");
/***/ }),
/***/ "./assets/src/components/clipboard.js":
/*!********************************************!*\
!*** ./assets/src/components/clipboard.js ***!
\********************************************/
/***/ ((__unused_webpack_module, __webpack_exports__, __webpack_require__) => {
"use strict";
eval("__webpack_require__.r(__webpack_exports__);\n/* harmony export */ __webpack_require__.d(__webpack_exports__, {\n/* harmony export */ \"default\": () => (/* binding */ copyClipBoard)\n/* harmony export */ });\n/**\n * Copy link to clipboard on click and display the tooltip.\n *\n * @param {string} elID Element id of copy link button.\n * @param {string} elValueID Element id of value.\n * @param {string} param Element attribute.\n *\n * @since 1.1\n */\nfunction copyClipBoard(elID, elValueID, param) {\n document.addEventListener('click', e => {\n const copyEl = document.getElementById(elID);\n if (!copyEl || !e.target.id.match(elID) && !copyEl.contains(e.target)) {\n // Only continue if the click is on the exact element or child.\n return;\n }\n e.preventDefault();\n copyToClipboard(document.getElementById(elValueID), param);\n\n // If .frm-abandonment-copy-success exists, remove it.\n const success = document.querySelector('.frm-abandonment-copy-success');\n if (success) {\n success.remove();\n }\n const message = document.createElement('span');\n message.setAttribute('class', 'frm-abandonment-copy-success');\n message.innerHTML = '';\n message.style.margin = '0 5px';\n copyEl.parentNode.insertBefore(message, copyEl.nextSibling);\n setTimeout(() => {\n message.remove();\n }, 6000);\n });\n}\n\n/**\n * Copy link to clipboard.\n *\n * @param {string} element Element.\n * @param {string} param Element attribute.\n *\n * @since 1.1\n */\nasync function copyToClipboard(element, param) {\n if (!element) {\n return;\n }\n if (navigator.clipboard) {\n try {\n await navigator.clipboard.writeText(element.getAttribute(param));\n } catch (err) {\n // eslint-disable-next-line no-console\n console.log(err);\n }\n }\n}\n\n//# sourceURL=webpack://formidable-abandonment/./assets/src/components/clipboard.js?");
/***/ }),
/***/ "./assets/src/components/modal.js":
/*!****************************************!*\
!*** ./assets/src/components/modal.js ***!
\****************************************/
/***/ ((__unused_webpack_module, __webpack_exports__, __webpack_require__) => {
"use strict";
eval("__webpack_require__.r(__webpack_exports__);\n/* harmony export */ __webpack_require__.d(__webpack_exports__, {\n/* harmony export */ \"default\": () => (__WEBPACK_DEFAULT_EXPORT__)\n/* harmony export */ });\n/* harmony import */ var tingle_js__WEBPACK_IMPORTED_MODULE_0__ = __webpack_require__(/*! tingle.js */ \"./node_modules/tingle.js/dist/tingle.min.js\");\n/* harmony import */ var tingle_js__WEBPACK_IMPORTED_MODULE_0___default = /*#__PURE__*/__webpack_require__.n(tingle_js__WEBPACK_IMPORTED_MODULE_0__);\n/* harmony import */ var _clipboard__WEBPACK_IMPORTED_MODULE_1__ = __webpack_require__(/*! ./clipboard */ \"./assets/src/components/clipboard.js\");\n/* harmony import */ var _dom_helper__WEBPACK_IMPORTED_MODULE_2__ = __webpack_require__(/*! ../dom-helper */ \"./assets/src/dom-helper.js\");\n/* global frmAbdn */\n\n/**\n *External dependencies\n */\n\n\n/**\n *Internal dependencies\n */\n\n\n\n/**\n * Class for handling closing of DOM.\n *\n * @since 1.1\n */\nfunction draftModal() {\n /**\n * First email_to field id.\n *\n * @since 1.1\n */\n this.firstEmailToField = false;\n /**\n * Is sending data Eligible.\n *\n * @since 1.1\n */\n this.hasEmail = false;\n /**\n * Form ID to watch.\n *\n * @since 1.1\n */\n this.formID = null;\n /**\n * Modal instance.\n *\n * @since 1.1\n */\n this.modal = null;\n /**\n * Check if form has been submitted.\n *\n * @since 1.1\n */\n this.watchSaveDraft = function () {\n document.addEventListener('click', e => {\n const saveBtn = e.target;\n if (!saveBtn.classList.contains('frm_save_draft')) {\n return;\n }\n const formCont = (0,_dom_helper__WEBPACK_IMPORTED_MODULE_2__.selector)(this.formID);\n if (!this.hasEmail && this.addRequiredEmailError(formCont, saveBtn)) {\n // Check if the email field is visible on the current page.\n return;\n }\n if (formCont.classList.contains('frm-temp-js-validate')) {\n // Remove temporary frm_js_validate class.\n formCont.classList.remove('frm_js_validate', 'frm-temp-js-validate');\n }\n if (this.hasEmail) {\n this.maybeAddHiddenField(formCont);\n } else {\n this.stopFormSubmit(saveBtn);\n if (!this.modal) {\n this.initiateModal();\n }\n this.modal.open();\n }\n }, true); // Capture phase before other click events.\n };\n\n /**\n * Add required email error if the field is on the current page.\n *\n * @param {Object} formCont Form container.\n * @param {Object} saveBtn Save button.\n * @return {boolean} Whether the email validation was added.\n */\n this.addRequiredEmailError = function (formCont, saveBtn) {\n const visibleEmailField = document.querySelector(`input[name=\"${this.firstEmailToField}\"][type=\"email\"]`);\n if (!visibleEmailField) {\n return false;\n }\n const fieldCont = visibleEmailField.parentNode;\n if (fieldCont && visibleEmailField.value === '') {\n fieldCont.classList.add('frm_blank_field');\n visibleEmailField.addEventListener('change', () => {\n this.allowFormSubmit(saveBtn);\n });\n\n // Add temporary frm_js_validate class to trigger validation.\n if (!formCont.classList.contains('frm_js_validate')) {\n formCont.classList.add('frm_js_validate', 'frm-temp-js-validate');\n }\n this.stopFormSubmit(saveBtn);\n return true;\n }\n fieldCont.classList.remove('frm_blank_field');\n return false;\n };\n this.stopFormSubmit = function (saveBtn) {\n saveBtn.classList.remove('frm_save_draft');\n saveBtn.classList.add('frm_pending_save_draft');\n };\n this.allowFormSubmit = function (saveBtn) {\n saveBtn.classList.remove('frm_pending_save_draft');\n saveBtn.classList.add('frm_save_draft');\n };\n\n /**\n * This field will trigger the saved draft copy link to show in the success message.\n *\n * @param {Object} formCont Form container.\n */\n this.maybeAddHiddenField = function (formCont) {\n if (this.hasEmail) {\n (0,_dom_helper__WEBPACK_IMPORTED_MODULE_2__.addHiddenField)(formCont, 'loggedout_draft', '1');\n }\n };\n\n /**\n * Create a modal.\n *\n * @since 1.1\n */\n this.initiateModal = function () {\n const formClass = (0,_dom_helper__WEBPACK_IMPORTED_MODULE_2__.selector)(this.formID).parentNode.getAttribute('class');\n const formClassArray = formClass.split(' ').filter(Boolean);\n formClassArray[0] = 'frm-abandonment-modal';\n this.modal = new (tingle_js__WEBPACK_IMPORTED_MODULE_0___default().modal)({\n footer: true,\n stickyFooter: false,\n closeMethods: ['overlay', 'escape'],\n closeLabel: frmAbdn.translatable.close,\n cssClass: formClassArray,\n onOpen: () => {\n // Add styling class to footer for buttons.\n const footer = document.querySelector('.tingle-modal-box__footer');\n footer.classList.add('frm_submit');\n },\n onClose: () => {\n const formEl = (0,_dom_helper__WEBPACK_IMPORTED_MODULE_2__.selector)(this.formID);\n const saveDraftEl = formEl.querySelector('.frm_pending_save_draft');\n if (!saveDraftEl) {\n return;\n }\n this.maybeAddHiddenField(formEl);\n this.allowFormSubmit(saveDraftEl);\n }\n });\n this.modalSetContent();\n this.modalSetButton();\n };\n\n /**\n * Set modal content.\n *\n * @since 1.1\n */\n this.modalSetContent = function () {\n this.modal.setContent(`\n\t\t×\n\t\t
\n\t\t\t${frmAbdn.translatable.title}\n\t\t
\n\t\t\n\t\t\t
\n\t\t\t${frmAbdn.translatable.content}\n\t\t\t
\n\t\t
\n\t\t\n\t\t`);\n };\n\n /**\n * Set modal footer button.\n *\n * @since 1.1\n */\n this.modalSetButton = function () {\n this.modal.addFooterBtn(frmAbdn.translatable.button, 'frm-abandonment-modal-btn frm-abandonment-modal-btn-primary', () => {\n const formCont = (0,_dom_helper__WEBPACK_IMPORTED_MODULE_2__.selector)(this.formID);\n const formEmailEl = formCont.querySelector(`input[name=\"${this.firstEmailToField}\"]`);\n const modalEmailEl = document.getElementById('frm-abandonment-modal-email');\n const pattern = /^(([^<>()\\[\\]\\\\.,;:\\s@\"]+(\\.[^<>()\\[\\]\\\\.,;:\\s@\"]+)*)|(\".+\"))@((\\[[0-9]{1,3}\\.[0-9]{1,3}\\.[0-9]{1,3}\\.[0-9]{1,3}])|(([a-zA-Z\\-0-9]+\\.)+[a-zA-Z]{2,}))$/i;\n if (modalEmailEl.value.match(pattern)) {\n formEmailEl.value = modalEmailEl.value;\n this.hasEmail = true;\n const saveDraftEl = formCont.querySelector('.frm_pending_save_draft');\n this.allowFormSubmit(saveDraftEl);\n saveDraftEl.click();\n this.modal.close();\n return;\n }\n const modalEmail = document.getElementById('frm-abandonment-modal-email');\n modalEmail.focus();\n modalEmail.style.border = '1px solid rgb(255, 0, 0)';\n const errorLabel = document.querySelector('.frm-abandonment-field-error');\n errorLabel.classList.remove('frm-abandonment-btn-invisible');\n });\n\n // Close button.\n document.querySelector('.frm-abandonment-close').addEventListener('click', () => {\n this.modal.close();\n });\n };\n\n /**\n * Observe fields for changes.\n *\n * @since 1.1\n */\n this.observeEmailFields = function () {\n const observableFields = (0,_dom_helper__WEBPACK_IMPORTED_MODULE_2__.getSetting)(this.formID, 'observable_fields', 'loggedOutDraft');\n // When there is no field selected in any action we don't need to open modal at all.\n if ('undefined' === typeof observableFields) {\n this.hasEmail = true;\n return;\n }\n const selectors = (0,_dom_helper__WEBPACK_IMPORTED_MODULE_2__.observableSelector)(observableFields);\n const formEl = (0,_dom_helper__WEBPACK_IMPORTED_MODULE_2__.selector)(this.formID);\n Array.prototype.forEach.call(selectors, (selector, key) => {\n // Collect first email id as main corresponding modal email field value.\n if (0 === key) {\n this.firstEmailToField = selector;\n }\n const fieldEl = formEl.querySelector(`input[name='${selector}']`);\n if (fieldEl && fieldEl.value) {\n this.hasEmail = true;\n }\n document.addEventListener('change', e => {\n if (selector === e.target.getAttribute('name')) {\n this.hasEmail = Boolean(e.target.value);\n }\n });\n });\n };\n /**\n * Initialization function.\n *\n * @since 1.1\n *\n * @param {string} formID Form ID.\n */\n this.init = function (formID) {\n this.formID = formID;\n this.observeEmailFields();\n this.watchSaveDraft();\n (0,_clipboard__WEBPACK_IMPORTED_MODULE_1__[\"default\"])('frm-abandonment-copy-link', 'frm-abandonment-link', 'value');\n };\n}\n/* harmony default export */ const __WEBPACK_DEFAULT_EXPORT__ = (draftModal);\n\n//# sourceURL=webpack://formidable-abandonment/./assets/src/components/modal.js?");
/***/ }),
/***/ "./assets/src/dom-closing.js":
/*!***********************************!*\
!*** ./assets/src/dom-closing.js ***!
\***********************************/
/***/ ((__unused_webpack_module, __webpack_exports__, __webpack_require__) => {
"use strict";
eval("__webpack_require__.r(__webpack_exports__);\n/* harmony export */ __webpack_require__.d(__webpack_exports__, {\n/* harmony export */ \"default\": () => (__WEBPACK_DEFAULT_EXPORT__)\n/* harmony export */ });\n/* harmony import */ var _dom_helper__WEBPACK_IMPORTED_MODULE_0__ = __webpack_require__(/*! ./dom-helper */ \"./assets/src/dom-helper.js\");\n/* global frmAbdn */\n\n\n\n/**\n * Class for handling closing of DOM.\n *\n * @since 1.0\n */\nfunction domClosing() {\n /**\n * Is sending data Eligible.\n *\n * @since 1.0\n */\n this.eligible = false;\n\n /**\n * Observed fields filled.\n *\n * @since x.x\n */\n this.observedFieldsFilled = false;\n\n /**\n * Form ID to watch.\n *\n * @since 1.0\n */\n this.formID = null;\n\n /**\n * Attached callback on dom close.\n *\n * @since 1.0\n */\n this.callBack = null;\n\n /**\n * Flag when form entry is a draft.\n *\n * @since 1.1\n */\n this.is_draft = false;\n\n /**\n * Auto save intervals by form id.\n *\n * @since 1.1\n */\n this.autoSaveInterval = false;\n\n /**\n * Bind the function if eligible.\n *\n * @since 1.0\n */\n this.bind = function () {\n if (this.isEligible()) {\n this.callBack();\n this.afterCallback();\n\n // Avoid saving when no changes have been made.\n this.eligible = false;\n }\n };\n\n /**\n * Check if eligible.\n *\n * @since 1.0\n *\n * @return {boolean} Eligibility.\n */\n this.isEligible = function () {\n return this.eligible;\n };\n\n /**\n * Handle visibility change event.\n *\n * @since 1.0\n */\n this.visibilityChange = function () {\n document.addEventListener('visibilitychange', () => {\n if (document.visibilityState === 'hidden') {\n this.bind();\n }\n });\n };\n\n /**\n * Capture form on interval to backup the visibilitychange \"hidden\"\n * when it's not triggered.\n *\n * @since 1.1\n */\n this.saveOnInterval = function () {\n if (!this.autoSaveInterval) {\n return;\n }\n setInterval(() => {\n if (!this.isEligible()) {\n return;\n }\n this.bind();\n if (this.is_draft) {\n this.showAutoSaveTime();\n }\n }, this.autoSaveInterval);\n };\n\n /**\n * Show the last saved timestap with the save draft button when auto save draft is enabled.\n */\n this.showAutoSaveTime = function () {\n const dateTime = `${frmAbdn.translatable.autoSaved} ${this.formatedTime()}`;\n let lastUpdatedTime = document.getElementById('frm-auto-save-time');\n if (!lastUpdatedTime) {\n lastUpdatedTime = document.createElement('span');\n lastUpdatedTime.id = 'frm-auto-save-time';\n }\n lastUpdatedTime.textContent = dateTime;\n const draftLink = (0,_dom_helper__WEBPACK_IMPORTED_MODULE_0__.selector)(this.formID).querySelector('.frm_submit .frm_save_draft');\n if (draftLink) {\n draftLink.parentNode.insertBefore(lastUpdatedTime, draftLink.nextSibling);\n }\n };\n\n /**\n * Convert the PHP time to JS time format.\n *\n * a Lowercase Ante meridiem and Post meridiem am or pm\n * A Uppercase Ante meridiem and Post meridiem AM or PM\n * g 12-hour format of an hour without leading zeros 1 through 12\n * G 24-hour format of an hour without leading zeros 0 through 23\n * h 12-hour format of an hour with leading zeros 01 through 12\n * H 24-hour format of an hour with leading zeros 00 through 23\n * i Minutes with leading zeros 00 to 59\n *\n * @return {string} Formatted time.\n */\n this.formatedTime = function () {\n const currentDate = new Date();\n const timeFormat = this.getValidTimeFormat();\n const hours = currentDate.getHours();\n const minutes = currentDate.getMinutes();\n const isPm = hours >= 12;\n const replacements = {\n g: hours % 12 || 12,\n // 12-hour without leading zero\n G: hours,\n // 24-hour without leading zero\n h: (hours % 12 || 12).toString().padStart(2, '0'),\n // 12-hour with leading zero\n H: hours.toString().padStart(2, '0'),\n // 24-hour with leading zero\n i: minutes.toString().padStart(2, '0'),\n // Minutes with leading zero\n a: isPm ? 'pm' : 'am',\n A: isPm ? 'PM' : 'AM'\n };\n\n // Replace format characters in the timeFormat string with actual time values\n const formattedTime = timeFormat.split('').map(char => replacements[char] !== undefined ? replacements[char] : char).join('');\n return formattedTime;\n };\n this.getValidTimeFormat = function () {\n const allowed = ['h', 'H', 'g', 'G', 'i', 'a', 'A', ' ', ':'];\n const defaultFormat = 'g:i a';\n const timeFormat = frmAbdn.timeFormat || defaultFormat;\n // Validate each character in the timeFormat against allowed characters\n for (const char of timeFormat) {\n if (!allowed.includes(char)) {\n // Return default format if an invalid character is found\n return defaultFormat;\n }\n }\n return timeFormat; // Return the original format if all characters are valid\n };\n\n /**\n * Check if is current form has a draft entry.\n *\n * @since 1.1\n *\n * @return {undefined|true} If draft submitted.\n */\n this.isAutoSave = function () {\n return this.autoSaveInterval !== 0;\n };\n\n /**\n * Set auto save interval.\n * @since 1.1\n * @return {void}\n */\n this.setAutoSaveInterval = function () {\n let saveInterval = (0,_dom_helper__WEBPACK_IMPORTED_MODULE_0__.getFieldValue)(this.formID, 'auto_save');\n if (!saveInterval) {\n saveInterval = 0;\n }\n this.autoSaveInterval = saveInterval;\n };\n\n /**\n * Check if the form field has changed by visitor.\n *\n * @since 1.0\n */\n this.isFormManipulated = function () {\n (0,_dom_helper__WEBPACK_IMPORTED_MODULE_0__.selector)(this.formID).addEventListener('change', () => {\n this.eligible = true;\n });\n };\n /**\n * Check if form has been submitted.\n *\n * @since 1.0\n */\n this.isFormSubmitted = function () {\n document.addEventListener('click', e => {\n if (e.target.classList.contains('frm_final_submit')) {\n this.eligible = false;\n }\n });\n };\n\n /**\n * Observe whether form is a draft in ajax or normal forms.\n *\n * @since 1.1\n */\n this.setDraftStatus = function () {\n if (!this.isAutoSave()) {\n return;\n }\n\n // Entry is draft no need for observer.\n if (true === (0,_dom_helper__WEBPACK_IMPORTED_MODULE_0__.getSetting)(this.formID, 'is_draft')) {\n this.switchToDraft();\n }\n };\n\n /**\n * The form switched to a draft.\n *\n * @since 1.1\n * @return {void}\n */\n this.switchToDraft = function () {\n this.is_draft = true;\n this.eligible = true;\n };\n\n /**\n * Check if the \"id\" field in the form exists and has a value.\n *\n * @return {void}\n */\n this.afterCallback = function () {\n if (this.is_draft) {\n return;\n }\n const idField = (0,_dom_helper__WEBPACK_IMPORTED_MODULE_0__.selector)(this.formID).querySelector('[name=\"id\"]');\n if (idField && idField.value !== '') {\n this.switchToDraft();\n }\n };\n\n /**\n * Check if email required is enabled.\n *\n * @since 1.0\n *\n * @return {undefined|true} If collection under circumstances is enabled.\n */\n this.isEmailRequired = function () {\n return this.isAbandonEnabled() && (0,_dom_helper__WEBPACK_IMPORTED_MODULE_0__.getSetting)(this.formID, 'abandon_email_required');\n };\n\n /**\n * Check if abandonment is enabled.\n *\n * @since 1.1\n *\n * @return {undefined|true} If abandonment enabled.\n */\n this.isAbandonEnabled = function () {\n return (0,_dom_helper__WEBPACK_IMPORTED_MODULE_0__.getSetting)(this.formID, 'enable_abandon');\n };\n\n /**\n * Observe fields for changes.\n *\n * @since 1.0\n */\n this.observeFields = function () {\n const selectors = (0,_dom_helper__WEBPACK_IMPORTED_MODULE_0__.observableSelector)((0,_dom_helper__WEBPACK_IMPORTED_MODULE_0__.getSetting)(this.formID, 'observable_fields'));\n Array.prototype.forEach.call(selectors, selector => {\n // Make the form eligible immediately on keyup.\n document.addEventListener('keyup', e => {\n if (selector === e.target.name) {\n this.eligible = true;\n this.observedFieldsFilled = true;\n }\n });\n });\n (0,_dom_helper__WEBPACK_IMPORTED_MODULE_0__.selector)(this.formID).addEventListener('change', () => {\n if (this.observedFieldsFilled) {\n this.eligible = true;\n }\n });\n };\n this.initForm = function () {\n const saveAbandon = !this.is_draft && this.isAbandonEnabled();\n const saveDraft = this.is_draft && this.isAutoSave();\n if (saveAbandon && this.isEmailRequired()) {\n this.observeFields();\n } else if (saveAbandon || saveDraft) {\n this.isFormManipulated();\n }\n };\n\n /**\n * Initialization function.\n *\n * @since 1.0\n *\n * @param {string} formID - Form ID.\n * @param {Function} callBack - Callback function.\n */\n this.init = function (formID = this.formID, callBack = this.callBack) {\n this.formID = formID;\n this.callBack = callBack;\n\n // Unbind the callback whenever the form is being submitted.\n this.isFormSubmitted();\n this.setAutoSaveInterval();\n this.setDraftStatus();\n jQuery(document).on('frmPageChanged frmFormComplete', function () {\n if (!this.is_draft && (0,_dom_helper__WEBPACK_IMPORTED_MODULE_0__.selector)(this.formID)?.querySelector('.frm_saving_draft')) {\n this.switchToDraft();\n }\n this.initForm();\n }.bind(this));\n jQuery(document).on('frmAfterRemoveRow', function () {\n this.eligible = true;\n }.bind(this));\n this.initForm();\n\n // In addition to page visibility change we will save the form on intervals.\n this.saveOnInterval();\n this.visibilityChange();\n };\n}\n/* harmony default export */ const __WEBPACK_DEFAULT_EXPORT__ = (domClosing);\n\n//# sourceURL=webpack://formidable-abandonment/./assets/src/dom-closing.js?");
/***/ }),
/***/ "./assets/src/dom-helper.js":
/*!**********************************!*\
!*** ./assets/src/dom-helper.js ***!
\**********************************/
/***/ ((__unused_webpack_module, __webpack_exports__, __webpack_require__) => {
"use strict";
eval("__webpack_require__.r(__webpack_exports__);\n/* harmony export */ __webpack_require__.d(__webpack_exports__, {\n/* harmony export */ addHiddenField: () => (/* binding */ addHiddenField),\n/* harmony export */ doAjax: () => (/* reexport safe */ _global_helper__WEBPACK_IMPORTED_MODULE_0__.doAjax),\n/* harmony export */ formSelector: () => (/* binding */ formSelector),\n/* harmony export */ getFieldValue: () => (/* binding */ getFieldValue),\n/* harmony export */ getFormData: () => (/* binding */ getFormData),\n/* harmony export */ getSetting: () => (/* binding */ getSetting),\n/* harmony export */ observableSelector: () => (/* binding */ observableSelector),\n/* harmony export */ selector: () => (/* binding */ selector)\n/* harmony export */ });\n/* harmony import */ var _global_helper__WEBPACK_IMPORTED_MODULE_0__ = __webpack_require__(/*! ./global-helper */ \"./assets/src/global-helper.js\");\n/* global frmAbdn */\n\n\n\n/**\n * Get all dom needed for app.\n *\n * @param {Array} formIDs\n * @since 1.0\n *\n * @return {Object} Elements.\n */\nconst formSelector = formIDs => {\n const selectors = {\n [Symbol.iterator]() {\n const values = Object.values(this);\n let index = Object.keys(this);\n return {\n next() {\n if (index < values.length) {\n const val = values[index];\n index++;\n return {\n value: val,\n done: false\n };\n }\n return {\n done: true\n };\n }\n };\n }\n };\n Array.prototype.forEach.call(formIDs, formSetting => {\n selectors[formSetting.form_id] = document.querySelector('#frm_form_' + formSetting.form_id + '_container form');\n });\n return selectors;\n};\n\n/**\n * Get dom form selector based on passed ID.\n *\n * @since 1.0\n *\n * @param {string} formID form identifier.\n *\n * @return {Object} Elements.\n */\nconst selector = formID => document.querySelector(`#frm_form_${formID}_container form`);\n\n/**\n * Get a setting from the global object.\n *\n * @since 1.0\n *\n * @param {string} formID The form ID to match against.\n * @param {string} optionName The option name to retrieve from the matched form's settings.\n * @param {string} type Type of settings.\n *\n * @return {*} The value of the requested setting for the matched form.\n */\nconst getSetting = (formID, optionName, type = 'abandonment') => {\n let formSettings;\n // Observer on forms which has enabled abandonment.\n if (typeof frmAbdn.formSettings !== 'undefined' && 'abandonment' === type) {\n formSettings = frmAbdn.formSettings;\n }\n // Observer on draft enabled forms with logged out permission.\n if (typeof frmAbdn.loggedOutDraft !== 'undefined' && 'loggedOutDraft' === type) {\n formSettings = frmAbdn.loggedOutDraft;\n }\n const matchedSetting = formSettings.find(setting => setting.form_id === formID);\n return matchedSetting[optionName];\n};\n\n/**\n * Prepare all filled form Data.\n *\n * @since 1.0\n *\n * @param {string} id Form selector.\n * @return {Object|string} An object with empty: true if there is no data to send. Otherwise, a serialized string is returned.\n */\nconst getFormData = id => {\n const element = selector(id);\n if (isFormEmpty(element)) {\n return {\n empty: true\n };\n }\n\n // If the form is loading, don't save.\n if (element.classList.contains('frm_loading_form') || element.classList.contains('frm_loading_prev')) {\n return {\n empty: true\n };\n }\n return serializeForm(element) + '&antispam_token=' + element.dataset.token;\n};\n\n/**\n * This function works the same as jQuery.serialize, but without using jQuery.\n *\n * @param {HTMLElement} element\n * @return {string} Serialized form data.\n */\nconst serializeForm = element => {\n return Array.from(new FormData(element), function (e) {\n return e.map(encodeURIComponent).join('=');\n }).join('&');\n};\n\n/**\n * Check if any form input values are not empty.\n *\n * @since 1.1.2\n *\n * @param {HTMLElement} element\n * @return {boolean} True if the every form input value is empty.\n */\nconst isFormEmpty = element => {\n const formData = new FormData(element);\n for (const value of formData.values()) {\n if ('' !== value) {\n return false;\n }\n }\n return true;\n};\n\n/**\n * Get field value by name.\n *\n * @since 1.1\n * @param {string} formID Form identifier.\n * @param {string} fieldName Field name.\n * @return {string} Field value.\n */\nconst getFieldValue = (formID, fieldName) => {\n const form = selector(formID);\n const field = form.querySelector(`input[name='${fieldName}']`);\n if (!field) {\n return '';\n }\n return field.value;\n};\n\n/**\n * Add a hidden input to the form if it doesn't exist.\n *\n * @param {Object} formEl The form element.\n * @param {string} fieldName The name of the input.\n * @param {string} value The value of the input.\n * @return {void}\n */\nconst addHiddenField = (formEl, fieldName, value) => {\n if (value === undefined) {\n return;\n }\n let input = formEl.querySelector(`input[name=\"${fieldName}\"]`);\n if (!input) {\n input = document.createElement('input');\n input.type = 'hidden';\n input.name = fieldName;\n input.value = value;\n formEl.appendChild(input);\n }\n};\n\n/**\n * Prepare an array of observable fields selectors.\n *\n * @since 1.0\n *\n * @param {Array} fieldsName array of field names.\n *\n * @return {Array} array of email or phone number elements for a form.\n */\nconst observableSelector = fieldsName => fieldsName.map(fieldName => `item_meta[${fieldName}]`);\n\n//# sourceURL=webpack://formidable-abandonment/./assets/src/dom-helper.js?");
/***/ }),
/***/ "./assets/src/global-helper.js":
/*!*************************************!*\
!*** ./assets/src/global-helper.js ***!
\*************************************/
/***/ ((__unused_webpack_module, __webpack_exports__, __webpack_require__) => {
"use strict";
eval("__webpack_require__.r(__webpack_exports__);\n/* harmony export */ __webpack_require__.d(__webpack_exports__, {\n/* harmony export */ doAjax: () => (/* binding */ doAjax)\n/* harmony export */ });\n/* global frm_js */\n\n/**\n * Handling Ajax.\n *\n * @param {Object} args\n * @since 1.1\n * @return {string|Object} Success object or message on failure.\n */\nconst doAjax = async args => {\n if (!args) {\n return {\n success: false,\n message: 'No data to send.'\n };\n }\n const response = await fetch(frm_js.ajax_url,\n // eslint-disable-line camelcase\n {\n method: 'POST',\n credentials: 'same-origin',\n headers: {\n 'Cache-Control': 'no-cache'\n },\n body: args\n });\n return Promise.resolve(response.json());\n};\n\n//# sourceURL=webpack://formidable-abandonment/./assets/src/global-helper.js?");
/***/ }),
/***/ "./assets/src/index.js":
/*!*****************************!*\
!*** ./assets/src/index.js ***!
\*****************************/
/***/ ((__unused_webpack_module, __webpack_exports__, __webpack_require__) => {
"use strict";
eval("__webpack_require__.r(__webpack_exports__);\n/* harmony import */ var _wordpress_dom_ready__WEBPACK_IMPORTED_MODULE_3__ = __webpack_require__(/*! @wordpress/dom-ready */ \"./node_modules/@wordpress/dom-ready/build-module/index.js\");\n/* harmony import */ var _dom_helper__WEBPACK_IMPORTED_MODULE_0__ = __webpack_require__(/*! ./dom-helper */ \"./assets/src/dom-helper.js\");\n/* harmony import */ var _dom_closing__WEBPACK_IMPORTED_MODULE_1__ = __webpack_require__(/*! ./dom-closing */ \"./assets/src/dom-closing.js\");\n/* harmony import */ var _components_modal__WEBPACK_IMPORTED_MODULE_2__ = __webpack_require__(/*! ./components/modal */ \"./assets/src/components/modal.js\");\n/* global frmAbdn */\n\n/**\n * WordPress dependencies\n */\n\n\n/**\n *Internal dependencies\n */\n\n\n\n\n/**\n * Initializes the scripts when DOM is ready.\n *\n * @since 1.0\n */\n(0,_wordpress_dom_ready__WEBPACK_IMPORTED_MODULE_3__[\"default\"])(() => {\n // Observer on forms which has enabled abandonment.\n if (typeof frmAbdn.formSettings !== 'undefined') {\n observer();\n }\n // Observer on draft enabled forms with logged out permission.\n if (typeof frmAbdn.loggedOutDraft !== 'undefined') {\n draftModalObserver();\n }\n});\n\n/**\n * Observes the forms and handles their data.\n *\n * @since 1.0\n */\nconst observer = () => {\n const formSelectors = (0,_dom_helper__WEBPACK_IMPORTED_MODULE_0__.formSelector)(frmAbdn.formSettings);\n for (const formID in formSelectors) {\n // Bail if form exists.\n if (null === formSelectors[formID]) {\n continue;\n }\n const domClosingObject = new _dom_closing__WEBPACK_IMPORTED_MODULE_1__[\"default\"]();\n domClosingObject.init(formID, () => {\n let formData = (0,_dom_helper__WEBPACK_IMPORTED_MODULE_0__.getFormData)(formID);\n formData = prepareFormAjaxRequest(formID, formData);\n (0,_dom_helper__WEBPACK_IMPORTED_MODULE_0__.doAjax)(formData).then(response => {\n handleFormAjaxResponse(response, formID);\n });\n });\n }\n};\n\n/**\n * Observes the forms and handles their data.\n *\n * @since 1.1\n */\nconst draftModalObserver = () => {\n const formSelectors = (0,_dom_helper__WEBPACK_IMPORTED_MODULE_0__.formSelector)(frmAbdn.loggedOutDraft);\n for (const formID in formSelectors) {\n if (null === formSelectors[formID]) {\n continue;\n }\n const draftModalObject = new _components_modal__WEBPACK_IMPORTED_MODULE_2__[\"default\"]();\n draftModalObject.init(formID);\n }\n};\n\n/**\n * @param {string} formID Form id.\n * @param {Object} data Form data.\n * @return {FormData|boolean} Form data or false when form is empty.\n */\nfunction prepareFormAjaxRequest(formID, data) {\n // Check the empty flag on prepare data and avoid sending form whenever form is empty.\n if (data.empty === true) {\n return false;\n }\n const formData = new FormData();\n formData.append('form_id', formID);\n formData.append('data', data);\n formData.append('action', 'frm_abandoned');\n return formData;\n}\n\n/**\n * Use the ajax response to update hidden form fields.\n *\n * @param {Object} response The response from the server.\n * @param {string} formID The form ID.\n * @return {void}\n */\nfunction handleFormAjaxResponse(response, formID) {\n if (!response.success || !response.data.id) {\n return;\n }\n\n // Get the \"frm_action\" input and set the value to \"update\".\n const form = document.querySelector('#frm_form_' + formID + '_container .frm_fields_container');\n const frmAction = form.querySelector('input[name=\"frm_action\"]');\n frmAction.value = 'update';\n (0,_dom_helper__WEBPACK_IMPORTED_MODULE_0__.addHiddenField)(form, 'id', response.data.id);\n (0,_dom_helper__WEBPACK_IMPORTED_MODULE_0__.addHiddenField)(form, 'secret', response.data.secret);\n}\n\n//# sourceURL=webpack://formidable-abandonment/./assets/src/index.js?");
/***/ }),
/***/ "./node_modules/tingle.js/dist/tingle.min.js":
/*!***************************************************!*\
!*** ./node_modules/tingle.js/dist/tingle.min.js ***!
\***************************************************/
/***/ (function(module, exports, __webpack_require__) {
eval("var __WEBPACK_AMD_DEFINE_FACTORY__, __WEBPACK_AMD_DEFINE_RESULT__;!function(t,o){ true?!(__WEBPACK_AMD_DEFINE_FACTORY__ = (o),\n\t\t__WEBPACK_AMD_DEFINE_RESULT__ = (typeof __WEBPACK_AMD_DEFINE_FACTORY__ === 'function' ?\n\t\t(__WEBPACK_AMD_DEFINE_FACTORY__.call(exports, __webpack_require__, exports, module)) :\n\t\t__WEBPACK_AMD_DEFINE_FACTORY__),\n\t\t__WEBPACK_AMD_DEFINE_RESULT__ !== undefined && (module.exports = __WEBPACK_AMD_DEFINE_RESULT__)):0}(this,function(){var o=!1;function t(t){this.opts=function(){for(var t=1;t',this.modalCloseBtnLabel=document.createElement(\"span\"),this.modalCloseBtnLabel.classList.add(\"tingle-modal__closeLabel\"),this.modalCloseBtnLabel.innerHTML=this.opts.closeLabel,this.modalCloseBtn.appendChild(this.modalCloseBtnIcon),this.modalCloseBtn.appendChild(this.modalCloseBtnLabel));this.modalBox=document.createElement(\"div\"),this.modalBox.classList.add(\"tingle-modal-box\"),this.modalBoxContent=document.createElement(\"div\"),this.modalBoxContent.classList.add(\"tingle-modal-box__content\"),this.modalBox.appendChild(this.modalBoxContent),-1!==this.opts.closeMethods.indexOf(\"button\")&&this.modal.appendChild(this.modalCloseBtn);this.modal.appendChild(this.modalBox)}.call(this),function(){this._events={clickCloseBtn:this.close.bind(this),clickOverlay:function(t){var o=this.modal.offsetWidth-this.modal.clientWidth,e=t.clientX>=this.modal.offsetWidth-15,s=this.modal.scrollHeight!==this.modal.offsetHeight;if(\"MacIntel\"===navigator.platform&&0==o&&e&&s)return;-1!==this.opts.closeMethods.indexOf(\"overlay\")&&!function(t,o){for(;(t=t.parentElement)&&!t.classList.contains(o););return t}(t.target,\"tingle-modal\")&&t.clientX {
/******/ // getDefaultExport function for compatibility with non-harmony modules
/******/ __webpack_require__.n = (module) => {
/******/ var getter = module && module.__esModule ?
/******/ () => (module['default']) :
/******/ () => (module);
/******/ __webpack_require__.d(getter, { a: getter });
/******/ return getter;
/******/ };
/******/ })();
/******/
/******/ /* webpack/runtime/define property getters */
/******/ (() => {
/******/ // define getter functions for harmony exports
/******/ __webpack_require__.d = (exports, definition) => {
/******/ for(var key in definition) {
/******/ if(__webpack_require__.o(definition, key) && !__webpack_require__.o(exports, key)) {
/******/ Object.defineProperty(exports, key, { enumerable: true, get: definition[key] });
/******/ }
/******/ }
/******/ };
/******/ })();
/******/
/******/ /* webpack/runtime/hasOwnProperty shorthand */
/******/ (() => {
/******/ __webpack_require__.o = (obj, prop) => (Object.prototype.hasOwnProperty.call(obj, prop))
/******/ })();
/******/
/******/ /* webpack/runtime/make namespace object */
/******/ (() => {
/******/ // define __esModule on exports
/******/ __webpack_require__.r = (exports) => {
/******/ if(typeof Symbol !== 'undefined' && Symbol.toStringTag) {
/******/ Object.defineProperty(exports, Symbol.toStringTag, { value: 'Module' });
/******/ }
/******/ Object.defineProperty(exports, '__esModule', { value: true });
/******/ };
/******/ })();
/******/
/************************************************************************/
/******/
/******/ // startup
/******/ // Load entry module and return exports
/******/ // This entry module can't be inlined because the eval devtool is used.
/******/ var __webpack_exports__ = __webpack_require__("./assets/src/index.js");
/******/
/******/ })()
;