Skip to content
Merged
Show file tree
Hide file tree
Changes from 4 commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
5 changes: 5 additions & 0 deletions src/Blocks/components/form/assets-admin/index.js
Original file line number Diff line number Diff line change
Expand Up @@ -4,6 +4,10 @@ import domReady from '@wordpress/dom-ready';
import manifest from './../manifest.json';

domReady(() => {
if (typeof esFormsLocalization === 'undefined') {
throw 'Your project is missing global variable esFormsLocalization called from the enqueue script.';
Comment thread
iruzevic marked this conversation as resolved.
Outdated
}

const {
componentJsClass,
componentCacheJsClass,
Expand All @@ -17,6 +21,7 @@ domReady(() => {
formSelector: selector,
formSubmitRestApiUrl: esFormsLocalization.formSettingsSubmitRestApiUrl,
formIsAdmin: true,
customFormParams: esFormsLocalization.customFormParams,
});

form.init();
Expand Down
114 changes: 57 additions & 57 deletions src/Blocks/components/form/assets/form.js
Original file line number Diff line number Diff line change
Expand Up @@ -62,15 +62,12 @@ export class Form {
this.selectSelector = `${this.fieldSelector} select`;
this.fileSelector = `${this.fieldSelector} input[type='file']`;

// State selectors.
this.CLASS_ACTIVE = FORM_SELECTORS.CLASS_ACTIVE;
this.CLASS_FILLED = FORM_SELECTORS.CLASS_FILLED;
this.CLASS_LOADING = FORM_SELECTORS.CLASS_LOADING;
this.CLASS_HAS_ERROR = FORM_SELECTORS.CLASS_HAS_ERROR;

// LocalStorage
this.STORAGE_NAME = 'es-storage';

// Custom fields params.
this.FORM_CUSTOM_FORM_PARAMS = options.customFormParams;

// Settings options.
this.formDisableScrollToFieldOnError = options.formDisableScrollToFieldOnError ?? true;
this.formDisableScrollToGlobalMessageOnSuccess = options.formDisableScrollToGlobalMessageOnSuccess ?? true;
Expand All @@ -79,6 +76,7 @@ export class Form {
this.hideGlobalMessageTimeout = options.hideGlobalMessageTimeout ?? 6000;
this.hideLoadingStateTimeout = options.hideLoadingStateTimeout ?? 600;
this.fileCustomRemoveLabel = options.fileCustomRemoveLabel ?? '';
this.formServerErrorMsg = options.formServerErrorMsg ?? '';
this.captcha = options.captcha ?? '';
this.storageConfig = options.storageConfig ?? '';

Expand All @@ -87,14 +85,6 @@ export class Form {
this.customTextareas = [];
this.customSelects = [];
this.customFiles = [];

// Data attributes.
this.DATA_ATTR_FORM_TYPE = FORM_DATA_ATTRIBUTES.DATA_ATTR_FORM_TYPE;
this.DATA_ATTR_FIELD_ID = FORM_DATA_ATTRIBUTES.DATA_ATTR_FIELD_ID;
this.DATA_ATTR_FORM_POST_ID = FORM_DATA_ATTRIBUTES.DATA_ATTR_FORM_POST_ID;
this.DATA_ATTR_TRACKING_EVENT_NAME = FORM_DATA_ATTRIBUTES.DATA_ATTR_TRACKING_EVENT_NAME;
this.DATA_ATTR_TRACKING = FORM_DATA_ATTRIBUTES.DATA_ATTR_TRACKING;
this.DATA_ATTR_TRACKING_SELECT_LABEL = FORM_DATA_ATTRIBUTES.DATA_ATTR_TRACKING_SELECT_LABEL;
}

// Init all actions.
Expand Down Expand Up @@ -122,7 +112,7 @@ export class Form {
}

// Get form ID.
const formId = element.getAttribute(this.DATA_ATTR_FORM_POST_ID);
const formId = element.getAttribute(FORM_DATA_ATTRIBUTES.DATA_ATTR_FORM_POST_ID);

// All fields selectors.
const inputs = element.querySelectorAll(this.inputSelector);
Expand Down Expand Up @@ -197,7 +187,7 @@ export class Form {
},
body: JSON.stringify({
token,
formId: element.getAttribute(this.DATA_ATTR_FORM_POST_ID),
formId: element.getAttribute(FORM_DATA_ATTRIBUTES.DATA_ATTR_FORM_POST_ID),
}),
credentials: 'same-origin',
redirect: 'follow',
Expand Down Expand Up @@ -247,7 +237,7 @@ export class Form {

const formData = this.getFormData(element, singleSubmit);

const formType = element.getAttribute(this.DATA_ATTR_FORM_TYPE);
const formType = element.getAttribute(FORM_DATA_ATTRIBUTES.DATA_ATTR_FORM_TYPE);

// Populate body data.
const body = {
Expand Down Expand Up @@ -359,6 +349,17 @@ export class Form {

// Dispatch event.
this.dispatchFormEvent(element, FORM_EVENTS.AFTER_FORM_SUBMIT_END);
})
.catch(() => {
this.setGlobalMsg(element, this.formServerErrorMsg, 'error');

// Remove loader.
this.hideLoader(element);

// Hide global msg in any case after some time.
setTimeout(() => {
this.hideGlobalMsg(element);
}, parseInt(this.hideGlobalMessageTimeout, 10));
});
};

Expand All @@ -371,7 +372,7 @@ export class Form {
// Check if we are saving group items in one key.
if (groups.length && !singleSubmit) {
for (const [key, group] of Object.entries(groups)) { // eslint-disable-line no-unused-vars
const groupId = group.getAttribute(this.DATA_ATTR_FIELD_ID);
const groupId = group.getAttribute(FORM_DATA_ATTRIBUTES.DATA_ATTR_FIELD_ID);
const groupInner = group.querySelectorAll(`
${this.groupInnerSelector} input,
${this.groupInnerSelector} select,
Expand Down Expand Up @@ -409,8 +410,7 @@ export class Form {
textarea:not(${this.groupInnerSelector} textarea)
`);

const formType = element.getAttribute(this.DATA_ATTR_FORM_TYPE);
const formAction = element.getAttribute('action');
const formType = element.getAttribute(FORM_DATA_ATTRIBUTES.DATA_ATTR_FORM_TYPE);

// If single submit override items and pass only one item to submit.
if (singleSubmit) {
Expand Down Expand Up @@ -483,43 +483,43 @@ export class Form {
}

// Add form ID field.
formData.append('es-form-post-id', JSON.stringify({
value: element.getAttribute(this.DATA_ATTR_FORM_POST_ID),
formData.append(this.FORM_CUSTOM_FORM_PARAMS.postId, JSON.stringify({
value: element.getAttribute(FORM_DATA_ATTRIBUTES.DATA_ATTR_FORM_POST_ID),
type: 'hidden',
}));

// Add form type field.
formData.append('es-form-type', JSON.stringify({
formData.append(this.FORM_CUSTOM_FORM_PARAMS.type, JSON.stringify({
value: formType,
type: 'hidden',
}));

// Add form action field.
formData.append('action', JSON.stringify({
value: formAction,
formData.append(this.FORM_CUSTOM_FORM_PARAMS.action, JSON.stringify({
value: element.getAttribute('action'),
type: 'hidden',
}));

// Add additional options for HubSpot only.
if (formType === 'hubspot' && !this.formIsAdmin) {
formData.append('es-form-hubspot-cookie', JSON.stringify({
formData.append(this.FORM_CUSTOM_FORM_PARAMS.hubspotCookie, JSON.stringify({
Comment thread
iruzevic marked this conversation as resolved.
value: cookies.getCookie('hubspotutk'),
type: 'hidden',
}));

formData.append('es-form-hubspot-page-name', JSON.stringify({
formData.append(this.FORM_CUSTOM_FORM_PARAMS.hubspotPageName, JSON.stringify({
value: document.title,
type: 'hidden',
}));

formData.append('es-form-hubspot-page-url', JSON.stringify({
formData.append(this.FORM_CUSTOM_FORM_PARAMS.hubspotPageUrl, JSON.stringify({
value: window.location.href,
type: 'hidden',
}));
}

if (singleSubmit && this.formIsAdmin) {
formData.append('es-form-single-submit', JSON.stringify({
formData.append(this.FORM_CUSTOM_FORM_PARAMS.singleSubmit, JSON.stringify({
value: 'true',
type: 'hidden',
}));
Expand All @@ -528,7 +528,7 @@ export class Form {
// Set localStorage to hidden field.
const storage = this.getLocalStorage();
if (storage) {
formData.append('es-form-storage', JSON.stringify({
formData.append(this.FORM_CUSTOM_FORM_PARAMS.storage, JSON.stringify({
value: storage,
type: 'hidden',
}));
Expand All @@ -543,7 +543,7 @@ export class Form {
for (const [key] of Object.entries(fields)) {
const item = element.querySelector(`${this.errorSelector}[data-id="${key}"]`);

item?.closest(this.fieldSelector).classList.add(this.CLASS_HAS_ERROR);
item?.closest(this.fieldSelector).classList.add(FORM_SELECTORS.CLASS_HAS_ERROR);

if (item !== null) {
item.innerHTML = fields[key];
Expand All @@ -563,7 +563,7 @@ export class Form {
if (this.formResetOnSuccess) {
element.reset();

const formId = element.getAttribute(this.DATA_ATTR_FORM_POST_ID);
const formId = element.getAttribute(FORM_DATA_ATTRIBUTES.DATA_ATTR_FORM_POST_ID);

// Unset the choices in the submitted form.
if (this.customSelects[formId]) {
Expand All @@ -582,9 +582,9 @@ export class Form {
const fields = element.querySelectorAll(this.fieldSelector);

[...fields].forEach((item) => {
item.classList.remove(this.CLASS_FILLED);
item.classList.remove(this.CLASS_ACTIVE);
item.classList.remove(this.CLASS_HAS_ERROR);
item.classList.remove(FORM_SELECTORS.CLASS_FILLED);
item.classList.remove(FORM_SELECTORS.CLASS_ACTIVE);
item.classList.remove(FORM_SELECTORS.CLASS_HAS_ERROR);
});

// Remove focus from last input.
Expand All @@ -603,7 +603,7 @@ export class Form {
});

// Reset all error classes on fields.
element.querySelectorAll(`.${this.CLASS_HAS_ERROR}`).forEach((element) => element.classList.remove(this.CLASS_HAS_ERROR));
element.querySelectorAll(`.${FORM_SELECTORS.CLASS_HAS_ERROR}`).forEach((element) => element.classList.remove(FORM_SELECTORS.CLASS_HAS_ERROR));

this.unsetGlobalMsg(element);
};
Expand All @@ -612,27 +612,27 @@ export class Form {
showLoader = (element) => {
const loader = element.querySelector(this.loaderSelector);

element?.classList?.add(this.CLASS_LOADING);
element?.classList?.add(FORM_SELECTORS.CLASS_LOADING);

if (!loader) {
return;
}

loader.classList.add(this.CLASS_ACTIVE);
loader.classList.add(FORM_SELECTORS.CLASS_ACTIVE);
};

// Hide loader.
hideLoader = (element) => {
const loader = element.querySelector(this.loaderSelector);

setTimeout(() => {
element?.classList?.remove(this.CLASS_LOADING);
element?.classList?.remove(FORM_SELECTORS.CLASS_LOADING);

if (!loader) {
return;
}

loader.classList.remove(this.CLASS_ACTIVE);
loader.classList.remove(FORM_SELECTORS.CLASS_ACTIVE);
}, parseInt(this.hideLoadingStateTimeout, 10));
};

Expand All @@ -648,7 +648,7 @@ export class Form {
return;
}

messageContainer.classList.add(this.CLASS_ACTIVE);
messageContainer.classList.add(FORM_SELECTORS.CLASS_ACTIVE);
messageContainer.dataset.status = status;
messageContainer.innerHTML = `<span>${msg}</span>`;

Expand All @@ -666,7 +666,7 @@ export class Form {
return;
}

messageContainer.classList.remove(this.CLASS_ACTIVE);
messageContainer.classList.remove(FORM_SELECTORS.CLASS_ACTIVE);
messageContainer.dataset.status = '';
messageContainer.innerHTML = '';
}
Expand All @@ -679,12 +679,12 @@ export class Form {
return;
}

messageContainer.classList.remove(this.CLASS_ACTIVE);
messageContainer.classList.remove(FORM_SELECTORS.CLASS_ACTIVE);
}

// Submit GTM event.
gtmSubmit(element) {
const eventName = element.getAttribute(this.DATA_ATTR_TRACKING_EVENT_NAME);
const eventName = element.getAttribute(FORM_DATA_ATTRIBUTES.DATA_ATTR_TRACKING_EVENT_NAME);

if (eventName) {
const gtmData = this.getGtmData(element, eventName);
Expand All @@ -698,15 +698,15 @@ export class Form {

// Build GTM data for the data layer.
getGtmData(element, eventName) {
const items = element.querySelectorAll(`[${this.DATA_ATTR_TRACKING}]`);
const items = element.querySelectorAll(`[${FORM_DATA_ATTRIBUTES.DATA_ATTR_TRACKING}]`);
const dataTemp = {};

if (!items.length) {
return {};
}

[...items].forEach((item) => {
const tracking = item.getAttribute(this.DATA_ATTR_TRACKING);
const tracking = item.getAttribute(FORM_DATA_ATTRIBUTES.DATA_ATTR_TRACKING);

if (tracking) {
const {type, checked} = item;
Expand All @@ -724,7 +724,7 @@ export class Form {
}

// Check if you have this data attr and if so use select label.
if (item.hasAttribute(this.DATA_ATTR_TRACKING_SELECT_LABEL)) {
if (item.hasAttribute(FORM_DATA_ATTRIBUTES.DATA_ATTR_TRACKING_SELECT_LABEL)) {
dataTemp[tracking] = item.selectedOptions[0].label;
return;
}
Expand Down Expand Up @@ -866,11 +866,11 @@ export class Form {
// On add one file.
myDropzone.on("addedfile", (file) => {
setTimeout(() => {
file.previewTemplate.classList.add(this.CLASS_ACTIVE);
file.previewTemplate.classList.add(FORM_SELECTORS.CLASS_ACTIVE);
}, 200);

setTimeout(() => {
file.previewTemplate.classList.add(this.CLASS_FILLED);
file.previewTemplate.classList.add(FORM_SELECTORS.CLASS_FILLED);
}, 1200);
});

Expand Down Expand Up @@ -910,28 +910,28 @@ export class Form {
case 'checkbox':
case 'radio':
if (input.checked) {
input.closest(this.fieldSelector).classList.add(this.CLASS_FILLED);
input.closest(this.fieldSelector).classList.add(FORM_SELECTORS.CLASS_FILLED);
}
break;
case 'select-custom': {
const customSelect = input.config.choices;

if (customSelect.some((item) => item.selected === true && item.value !== '')) {
input.passedElement.element.closest(this.fieldSelector).classList.add(this.CLASS_FILLED);
input.passedElement.element.closest(this.fieldSelector).classList.add(FORM_SELECTORS.CLASS_FILLED);
}
break;
}
default:
if (input.value && input.value.length) {
input.closest(this.fieldSelector).classList.add(this.CLASS_FILLED);
input.closest(this.fieldSelector).classList.add(FORM_SELECTORS.CLASS_FILLED);
}
break;
}
};

// On Focus event for regular fields.
onFocusEvent = (event) => {
event.target.closest(this.fieldSelector).classList.add(this.CLASS_ACTIVE);
event.target.closest(this.fieldSelector).classList.add(FORM_SELECTORS.CLASS_ACTIVE);
};

// On Blur generic method. Check for length of value.
Expand Down Expand Up @@ -970,10 +970,10 @@ export class Form {
}

if (condition) {
field.classList.remove(this.CLASS_ACTIVE);
field.classList.add(this.CLASS_FILLED);
field.classList.remove(FORM_SELECTORS.CLASS_ACTIVE);
field.classList.add(FORM_SELECTORS.CLASS_FILLED);
} else {
field.classList.remove(this.CLASS_ACTIVE, this.CLASS_FILLED);
field.classList.remove(FORM_SELECTORS.CLASS_ACTIVE, FORM_SELECTORS.CLASS_FILLED);
}
};

Expand All @@ -989,7 +989,7 @@ export class Form {
// Regular submit.
element.removeEventListener('submit', this.onFormSubmit);

const formId = element.getAttribute(this.DATA_ATTR_FORM_POST_ID);
const formId = element.getAttribute(FORM_DATA_ATTRIBUTES.DATA_ATTR_FORM_POST_ID);

const inputs = element.querySelectorAll(this.inputSelector);
const textareas = element.querySelectorAll(this.textareaSelector);
Expand Down
Loading