PageSourceSearch

https://deliciousbrains.com/app/src/EmailMarketing/Hubspot/js/hubspot.js?ver=7.1.1

js deliciousbrains.com collected 2026-09-24 07:41:43 UTC 7,113 bytes, 267 lines download raw bytes

1/**
2 * JavaScript for Hubspot sign-up forms.
3 */
4
5/**
6 * This class is a small data object for field types used in the API.
7 * See: https://legacydocs.hubspot.com/docs/methods/forms/submit_form
8 */
9class DbiHubspotField {
10	/**
11	 * Constructor
12	 *
13	 * @param {string} objectTypeId The Object Type ID - see https://developers.hubspot.com/docs/api/crm/crm-custom-objects
14	 * @param {string} name         The field name
15	 * @param {string} value        The field value
16	 */
17	constructor( objectTypeId, name, value ) {
18		this.objectTypeId = objectTypeId;
19		this.name = name;
20		this.value = value;
21	}
22}
23
24/**
25 * This is the main form class that handles form validation and submissions
26 */
27class DbiEmailMarketingForms {
28	/**
29	 * The base URL of the form submission API
30	 *
31	 * @type {string}
32	 */
33	baseUrl = 'https://api.hsforms.com/submissions/v3/integration/submit';
34
35	/**
36	 * Constructor
37	 */
38	constructor() {
39		document.querySelectorAll( '.drip-signup' ).forEach( ( form ) => {
40			form.addEventListener( 'submit', this.handleSubmit.bind( this ) );
41		} );
42	}
43
44	/**
45	 * Handler for submit event
46	 *
47	 * @param {Event} event The event to handle
48	 * @return {boolean}  This will always return false in order to prevent the form submitting as normal.
49	 */
50	handleSubmit( event ) {
51		event.preventDefault();
52		/**
53		 * The form element
54		 *
55		 * @type {HTMLFormElement}
56		 */
57		const form = event.target;
58
59		/**
60		 * The first input in the form
61		 *
62		 * @type {HTMLInputElement}
63		 */
64		const firstInput = form.querySelector( 'input' );
65
66		/**
67		 * The errors container element
68		 *
69		 * @type {HTMLDivElement}
70		 */
71		const errorsElement = form.previousElementSibling; // This needs to be  '.dbi__signup-errors
72
73		// If form isn't expanded, expand and focus it. Do not submit.
74		if ( ! form.classList.contains( 'expanded' ) ) {
75			form.classList.add( 'expanded' );
76			firstInput.focus();
77			return false;
78		}
79
80		let allowSubmit = true;
81
82		// Validate inputs
83		form.querySelectorAll( 'input[type=email], input[type=text]' ).forEach(
84			( input ) => {
85				allowSubmit =
86					allowSubmit &&
87					this.validateTextInput( input, errorsElement );
88			}
89		);
90
91		if ( allowSubmit ) {
92			form.querySelector(
93				'input[type="submit"], button[type="submit"], button.dbi-welcome-signup__submit'
94			).disabled = true;
95			errorsElement.style.display = 'none';
96
97			this.submitFormData( form ).then( ( result ) => {
98				if ( result === true ) {
99					// If we have a redirect, send to that
100					if ( form.dataset.redirectTo ) {
101						window.location = form.dataset.redirectTo;
102					}
103					// There are currently no other actions
104				} else {
105					errorsElement.innerText = result;
106					errorsElement.style.display = 'block';
107				}
108			} );
109		}
110
111		return allowSubmit;
112	}
113
114	/**
115	 * Validate a text input element
116	 *
117	 * @param {HTMLInputElement} inputElement  The input element to validate
118	 * @param {HTMLDivElement}   errorsElement The element to display errors in
119	 * @return {boolean}                       True if the value validates
120	 */
121	validateTextInput( inputElement, errorsElement ) {
122		// Check for 0-length input
123		if (
124			inputElement.dataset.errorText &&
125			0 === inputElement.value.length
126		) {
127			errorsElement.innerText = `Please enter your ${ inputElement.dataset.errorText }.`;
128			errorsElement.style.display = 'block';
129
130			return false;
131		}
132
133		// Check for invalid name
134		// The regular expression is loose, but it's good enough for our purposes
135		if (
136			inputElement.dataset.errorText &&
137			inputElement.type === 'text' &&
138			inputElement.value.match( /<.*>/ )
139		) {
140			errorsElement.innerText = `Your ${ inputElement.dataset.errorText } can not contain HTML.`;
141			errorsElement.style.display = 'block';
142
143			return false;
144		}
145
146		return true;
147	}
148
149	/**
150	 * Gathers and submits the form data
151	 *
152	 * @param {HTMLFormElement} formElement The form element
153	 * @return {Promise<boolean|string>} True for a successful form submission. An error message otherwise.
154	 */
155	async submitFormData( formElement ) {
156		// Get form details
157		const accountId = this.getAccountId( formElement );
158		const formId = this.getFormId( formElement );
159		// Construct URL
160		const url = this.constructUrl( accountId, formId );
161		// Get data from form
162		const fieldsData = this.getDataFromForm( formElement );
163		// Make the request and return the result
164		return await this.sendRequest( url, fieldsData, formElement );
165	}
166
167	/**
168	 * Gets the Hubspot form id from an HTML form
169	 *
170	 * @param {HTMLFormElement} formElement
171	 * @return {string} The Hubspot form ID
172	 */
173	getFormId( formElement ) {
174		const formId = formElement.dataset.hubspotFormId;
175		if ( ! formId ) {
176			return '';
177		}
178		return formId;
179	}
180
181	/**
182	 * Gets the Hubspot account id from an HTML form
183	 *
184	 * @param {HTMLFormElement} formElement
185	 * @return {string} The Hubspot account ID
186	 */
187	getAccountId( formElement ) {
188		const accountId = formElement.dataset.hubspotAccountId;
189		if ( ! accountId ) {
190			return '';
191		}
192		return accountId;
193	}
194
195	/**
196	 * Construct the API URL to use
197	 *
198	 * @param {string} hubspotAccountId The Hubspot account ID
199	 * @param {string} formId           The Hubspot form ID
200	 * @return {string} The URL to use for the API submission
201	 */
202	constructUrl( hubspotAccountId, formId ) {
203		return `${ this.baseUrl }/${ hubspotAccountId }/${ formId }`;
204	}
205
206	/**
207	 * Note the API Docs:
208	 *  - https://legacydocs.hubspot.com/docs/methods/forms/submit_form
209	 *  - https://developers.hubspot.com/docs/api/crm/crm-custom-objects
210	 *  Note that the objectTypeId for the standard "Contact" object is 0-1
211	 *
212	 * @param {HTMLFormElement} formElement The form element to get data from
213	 * @return {Array<DbiHubspotField>}  An array of field objects
214	 */
215	getDataFromForm( formElement ) {
216		const inputs = Array.from(
217			formElement.querySelectorAll( 'input[data-hubspot-field-name]' )
218		);
219
220		if ( inputs.length === 0 ) {
221			return [];
222		}
223
224		return inputs.map(
225			( inputElem ) =>
226				new DbiHubspotField(
227					inputElem.dataset.hubspotObjectTypeId,
228					inputElem.dataset.hubspotFieldName,
229					inputElem.value
230				)
231		);
232	}
233
234	/**
235	 * Send the API request with the subscribe form data
236	 *
237	 * @param {string}                 url         The API URL to send to
238	 * @param {Array<DbiHubspotField>} fieldsData  The fields data to send in the body
239	 * @param {HTMLFormElement}        formElement The formElement
240	 * @return {Promise<boolean|string>} True for a successful form submission. An error message otherwise.
241	 */
242	async sendRequest( url, fieldsData, formElement ) {
243		const dataToSend = { fields: fieldsData };
244
245		const options = {
246			method: formElement.method,
247			body: JSON.stringify( dataToSend ),
248			headers: {
249				'Content-Type': 'application/json',
250			},
251			cache: 'no-cache',
252		};
253
254		let returnValue = true;
255
256		const response = await fetch( url, options ).catch( ( err ) => {
257			returnValue = `There was a problem processing your request: ${ err }`;
258		} );
259		if ( response && ! response.ok ) {
260			returnValue = `There was a problem processing your request. Result code: ${ response.status }`;
261		}
262
263		return returnValue;
264	}
265}
266
267new DbiEmailMarketingForms();

Line numbers count LF bytes from the start of the resource, as the search results do. Vendor segments are library code the classifier recognised; they are stored but not indexed. Bytes are shown as Latin1 characters, one per byte.