PageSourceSearch

https://campaign.viessmann-cold.com/acton/content/form_embed.js

js viessmann-cold.com collected 2026-10-04 13:24:04 UTC 100,320 bytes, 2,141 lines download raw bytes

1var aoPostLoadFormCallback = aoPostLoadFormCallback || {};
2var aoPostSubmitFormCallback = aoPostSubmitFormCallback || {};
3
4var MAX_FILE_SIZE = 1024 * 1024 * 1024; // 1GB in bytes
5
6var DEFAULT_SUPPORTED_FORMATS = [];
7
8var ACTON_BASE_URL = "/acton/file-upload-service";
9
10const dropzoneFileCollections = {};
11const inputToDropzoneMap = new Map(); 
12var maxUploads = 10;
13
14var FILE_SCAN_ERROR_TEXT = "Virus scan failed. File rejected.";
15
16var pathname = window.location.pathname;
17
18function getErrorIconSVG() {
19    return '<svg width="12" height="12" viewBox="0 0 12 12" fill="none" xmlns="http://www.w3.org/2000/svg">' +
20        '<g clip-path="url(#clip0_533_1217)">' +
21        '<path fill-rule="evenodd" clip-rule="evenodd" d="M0 6C0 2.68629 2.68629 0 6 0C9.31371 0 12 2.68629 12 6C12 9.31371 9.31371 12 6 12C2.68629 12 0 9.31371 0 6ZM6.49989 6.49969V3.50002C6.49989 3.22391 6.27606 3.00008 5.99995 3.00008C5.72384 3.00008 5.5 3.22391 5.5 3.50002V6.49969C5.5 6.7758 5.72384 6.99963 5.99995 6.99963C6.27606 6.99963 6.49989 6.7758 6.49989 6.49969ZM5.5 8.50176V8.49678C5.5 8.22201 5.72384 7.99927 5.99995 7.99927C6.27606 7.99927 6.49989 8.22201 6.49989 8.49678V8.50176C6.49989 8.77652 6.27606 8.99927 5.99995 8.99927C5.72384 8.99927 5.5 8.77652 5.5 8.50176Z" fill="#F25656"/>' +
22        '</g>' +
23        '<defs>' +
24        '<clipPath id="clip0_533_1217">' +
25        '<rect width="12" height="12" fill="white"/>' +
26        '</clipPath>' +
27        '</defs>' +
28        '</svg>';
29}
30
31function getSuccessIconSVG() {
32    return '<svg width="12" height="12" viewBox="0 0 12 12" fill="none" xmlns="http://www.w3.org/2000/svg">' +
33        '<g clip-path="url(#clip0_533_1203)">' +
34        '<path fill-rule="evenodd" clip-rule="evenodd" d="M0 6C0 2.68629 2.68629 0 6 0C9.31371 0 12 2.68629 12 6C12 9.31371 9.31371 12 6 12C2.68629 12 0 9.31371 0 6ZM8.0274 4.08387C8.25717 4.23704 8.31925 4.54748 8.16608 4.77724L6.16608 7.77724C6.0129 8.007 5.70247 8.06909 5.4727 7.91592L3.9727 6.91592C3.74294 6.76274 3.68085 6.4523 3.83403 6.22254C3.9872 5.99278 4.29764 5.93069 4.5274 6.08387L5.61138 6.80651L7.33403 4.22254C7.4872 3.99278 7.79764 3.93069 8.0274 4.08387Z" fill="#69B466"/>' +
35        '</g>' +
36        '<defs>' +
37        '<clipPath id="clip0_533_1203">' +
38        '<rect width="12" height="12" fill="white"/>' +
39        '</clipPath>' +
40        '</defs>' +
41        '</svg>';
42}
43
44function getRemoveIconSvg() {
45    return '<svg width="24" height="24" viewBox="0 0 24 24" fill="none" xmlns="http://www.w3.org/2000/svg">' +
46            '<rect width="24" height="24" rx="4" fill="#FFEAEB"/>' +
47            '<path fill-rule="evenodd" clip-rule="evenodd" d="M15 8V7.5C15 7.10217 14.842 6.72064 14.5607 6.43934C14.2794 6.15804 13.8978 6 13.5 6H10.5C10.1022 6 9.72064 6.15804 9.43934 6.43934C9.15804 6.72064 9 7.10218 9 7.5V8H8.00071C8.00054 8 8.00087 8 8.00071 8H7.5C7.22386 8 7 8.22386 7 8.5C7 8.77614 7.22386 9 7.5 9H7.52717L7.95079 16.5829C7.972 16.9661 8.13928 17.3266 8.41824 17.5902C8.69711 17.8538 9.06635 18.0004 9.45001 18L14.5542 18C14.9379 18.0004 15.3079 17.8538 15.5868 17.5902C15.8658 17.3265 16.0331 16.9658 16.0542 16.5825L16.4732 9H16.5C16.7761 9 17 8.77614 17 8.5C17 8.22386 16.7761 8 16.5 8H15ZM10.5 7C10.3674 7 10.2402 7.05268 10.1464 7.14645C10.0527 7.24021 10 7.36739 10 7.5V8H14V7.5C14 7.36739 13.9473 7.24022 13.8536 7.14645C13.7598 7.05268 13.6326 7 13.5 7H10.5ZM8.52873 9L8.94923 16.5271C8.95627 16.6549 9.01206 16.7755 9.10507 16.8634C9.19809 16.9513 9.32127 17.0002 9.44925 17L14.555 17C14.683 17.0002 14.8069 16.9513 14.8999 16.8634C14.993 16.7755 15.0487 16.6553 15.0558 16.5275L15.4716 9H8.52873Z" fill="#E81212"/>' +
48        '</svg>';
49}
50
51function showOrHideSubmitButtons(currentForm) {
52    var submitButtons = !currentForm
53        ? document.querySelectorAll(".ao-form-submit")
54        : currentForm.querySelectorAll(".ao-form-submit");
55    var hasWarnings;
56
57    const isProgresBarVisible = document.querySelectorAll("[id^='progress-bar-wrapper']");
58    const hasVisibleProgressBars = Array.from(isProgresBarVisible).some(
59        (progressBar) => progressBar.style.display === "block"
60    );
61
62    for (const dropzoneKey in dropzoneFileCollections) {
63        const dropzone = dropzoneFileCollections[dropzoneKey];
64        for (const fileStatus of dropzone.fileStatuses) {
65            if (fileStatus.status === "WARNING" || fileStatus.status === "IN_PROGRESS" || hasVisibleProgressBars) {
66                hasWarnings = true;
67                break;
68            }
69        }
70        if (hasWarnings) break;
71    }
72
73    for (var i = 0; i < submitButtons.length; i++) {
74        if (hasWarnings) {
75            submitButtons[i].disabled = true;
76            submitButtons[i].style.opacity = "0.5";
77            submitButtons[i].style.pointerEvents = "none";
78        } else {
79            submitButtons[i].disabled = false;
80            submitButtons[i].style.opacity = "1";
81            submitButtons[i].style.pointerEvents = "auto";
82        }
83    }
84}
85
86var removeFileStatus = function(uniqueDropzoneId, fileName) {
87    const dropzoneData = dropzoneFileCollections[uniqueDropzoneId];
88    dropzoneData.fileStatuses = dropzoneData.fileStatuses.filter(file => file.fileName !== fileName);
89    showOrHideSubmitButtons();
90};
91
92const updateFileStatus = (allowMultiple, uniqueDropzoneId, fileName, status, attachmentId, jwtToken) => {
93    const dropzoneData = dropzoneFileCollections[uniqueDropzoneId];
94    const { fileStatuses } = dropzoneData;
95
96    if (!allowMultiple) {
97        dropzoneData.fileStatuses = [{ fileName, status, attachmentId, jwtToken}];
98    } else {
99        const existingFileIndex = fileStatuses.findIndex(file => file.fileName === fileName);
100        if (existingFileIndex !== -1) {
101            fileStatuses[existingFileIndex] = { fileName, status, attachmentId, jwtToken };
102        } else {
103            fileStatuses.push({ fileName, status, attachmentId, jwtToken});
104        }
105        dropzoneData.fileStatuses = fileStatuses;
106    }
107};
108
109function deleteAttachmentByToken(jwtToken, accountId, domain, scheme) {
110    return new Promise((resolve, reject) => {
111      if (!jwtToken) {
112        resolve(false);
113        return;
114      }
115
116      var url = scheme + domain + ACTON_BASE_URL + "/attachment/delete-by-token?jwtToken=" + jwtToken;
117  
118      const xhr = new XMLHttpRequest();
119      xhr.open('DELETE', url, true);
120      xhr.setRequestHeader( 'Content-Type', 'application/json' );
121
122
123        xhr.onload = function () {
124        if (xhr.status === 200) {
125          try {
126            const response = JSON.parse(xhr.responseText);
127            if (response) {
128              resolve(true);
129            } else {
130              resolve(false);
131            }
132          } catch (e) {
133            resolve(false);
134          }
135        } else {
136          resolve(false);
137        }
138      };
139  
140      xhr.onerror = function () {
141        resolve(false);
142      };
143  
144      xhr.send(JSON.stringify(jwtToken));
145    });
146}
147
148function updateFileUploadMetadata(uiniqueCollection, index) {
149    const uploadedFiles = uiniqueCollection.fileStatuses
150    .filter(fileStatus => fileStatus.status === "DONE" && fileStatus.attachmentId)
151    .map(fileStatus => ({
152        name: fileStatus.fileName,
153        id: fileStatus.attachmentId,
154    }));
155
156    const jsonValue = JSON.stringify({
157        type: "FILE",
158        data: uploadedFiles,
159    });
160
161    const fileUploadMetaData = document.querySelectorAll("[class^='file-upload-metadata']")[index];
162    if (fileUploadMetaData) {
163        fileUploadMetaData.value = jsonValue;
164    }
165}
166
167function getElementsByAttribute (tagName, index) { 
168    return document.querySelectorAll(`[${tagName}]`)[index]?.getAttribute(tagName)?.trim()
169}
170
171function getAllowedFileTypes(accountId, domain, scheme) {
172    return new Promise(function (resolve, reject) {
173        var query = "action=getAllowedFileTypesList&accountId=" + accountId;
174        var url = scheme + domain + "/acton/file/upload.jsp?" + query;
175        var xhr = new XMLHttpRequest();
176
177        xhr.open("GET", url, true);
178        xhr.onload = function () {
179            if (xhr.status >= 200 && xhr.status < 300) {
180                var data = JSON.parse(xhr.responseText);
181                DEFAULT_SUPPORTED_FORMATS = data.allowedFileUploadTypes;
182                resolve();
183            } else {
184                reject("Error: " + xhr.statusText);
185            }
186        };
187
188        xhr.onerror = function () {
189            reject("Network Error");
190        };
191
192        xhr.send();
193    });
194}
195
196
197var _aoFormLoader = (function(w){
198	var stylesLoaded = false;
199	var captchaLoaded = false;
200	var gfLoaded = false;
201	var htmlId = false;
202	var formsLoadedCount = 0;
203	var formsCount = 0;
204
205  var scheme = document.location.protocol + "//";
206
207  function populateDateField(inputElem, value) {
208    if(!value || !inputElem) {
209      return;
210    }
211
212    var dateWrapper = inputElem.parentElement;
213    var dateElements = dateWrapper.querySelectorAll('input.ao-form-field-date');
214  	var amPm;
215
216    if (value.indexOf("AM")) {
217    	value = value.replace("AM", "");
218    	amPm = "AM";
219	} else if (value.indexOf("PM")) {
220		value = value.replace("PM", "");
221		amPm = "PM";
222	}
223    var dateFormat = value.split(/[:\/\s]+/);
224
225    // Populate all date input fields
226    dateElements.forEach(function(elem, index) {
227      elem.value = dateFormat[index] || '';
228    });
229
230    // Populate AM/PM dropdown
231    if(amPm && dateWrapper.querySelector("option[value='" + amPm + "']")) {
232      dateWrapper.querySelector("option[value='" + amPm + "']").selected = true;
233    }
234  }
235
236	var loadForm = function(options){
237	    formsCount += 1; //increment for each form that is on the page
238		loadStylesheet(options);
239
240		var previewMarkup = '<p style="text-align: center;">Unable to preview form, it has reached the submission cap or expired.</p>';
241		var oReq = new XMLHttpRequest();
242		oReq.onload = function (e) {
243
244			var response;
245
246			if (e.target.responseType === 'json') {
247				response = e.target.response || false;
248			} else {
249				response = (e.target.response) ?  JSON.parse(e.target.response) : false;
250			}
251
252			if(!response){
253				return false;
254			} else if (response && typeof response.processedTemplate === 'undefined' && response.linkURL && response.linkURL != '') {
255				var linkURL = response.linkURL;
256				var queryString = window.location.search;
257				if (queryString) {
258					var params = queryString.substring(1).split('&');
259					var filteredParams = [];
260					for (var i = 0; i < params.length; i++) {
261						var paramName = params[i].split('=')[0];
262						// Skip internal Act-On parameters
263						if (paramName !== 'a' && paramName !== 'p' && paramName !== 't' &&
264							paramName !== 'fm' && paramName !== 'preview' && paramName !== 'r' &&
265							paramName !== 's' && paramName !== 'jsembed' && paramName !== 'tracking' &&
266							paramName !== 'src' && paramName !== 'cmp' && paramName !== 'cmpid' &&
267							paramName !== 'k' && paramName !== 'sid' && paramName !== 'd' &&
268							paramName !== 'rptpw') {
269							filteredParams.push(params[i]);
270						}
271					}
272					if (filteredParams.length > 0) {
273						linkURL += (linkURL.indexOf('?') > 0 ? '&' : '?') + filteredParams.join('&');
274					}
275				}
276
277				window.location = linkURL;
278				return false;
279			}
280
281			var idArr = options.id.split(":");
282
283			htmlId = (options.uniqueId) ? options.id + options.uniqueId : options.id;
284            divId = (options.uniqueId) ? idArr[0] + options.uniqueId : idArr[0];
285
286			var existingDiv = document.getElementById('aoform-' + divId);
287			if(existingDiv)
288				existingDiv.parentNode.removeChild(existingDiv);
289
290			var div = document.createElement('div');
291			var scriptTag = document.getElementById('aoform-script-' + htmlId);
292			div.id = 'aoform-' + divId;
293            div.style.visibility = "hidden";
294			scriptTag.parentNode.insertBefore(div, scriptTag);
295			div.innerHTML = response && response.processedTemplate ? response.processedTemplate : previewMarkup;
296			formsLoadedCount += 1; //increment for when a form is loaded onto the page
297
298            const dropzones = document.querySelectorAll("[id^='files-dropzone']");
299            const fileInputs = document.querySelectorAll("[id^='file-upload']");
300            const fileLists = document.querySelectorAll("[id^='filelist']");
301
302        getAllowedFileTypes(options.accountId, options.domain, scheme).then(function () {
303            dropzones.forEach((dropzone, index) => {
304                const fileSizeErrorMessage = getElementsByAttribute('data-filesizeerrormessage', index);
305                const fileGeneralErrorMessage = getElementsByAttribute('data-filegeneralerrormessage', index);
306                const fileAllowedTypesErrorMessage = getElementsByAttribute('data-fileallowedtypeserrormsg', index) || 'The uploaded file is not a supported file format';
307
308                const fileInput = fileInputs[index];
309                const fileList = fileLists[index];
310
311                const uniqueDropzoneId = `dropzone-${index}`;
312
313                dropzoneFileCollections[uniqueDropzoneId] = {
314                    files: [],
315                    fileElementsMap: new Map(),
316                    fileStatuses: [],
317                    pollingState:{},
318                    fileMessages: { fileSizeErrorMessage, fileGeneralErrorMessage, fileAllowedTypesErrorMessage }
319                };
320
321                if (fileInput) {
322                    inputToDropzoneMap.set(fileInput, uniqueDropzoneId);
323                }
324
325                if (dropzone && fileInput && fileList) {
326                    const allowedFileTypes = getElementsByAttribute('data-allowedfiletypes', index);
327                    const otherFileTypes = getElementsByAttribute('data-otherfiletypes', index);
328                    const unqiueCollection = dropzoneFileCollections[uniqueDropzoneId];
329
330                    unqiueCollection['SUPPORTED_FORMATS'] = DEFAULT_SUPPORTED_FORMATS;
331
332                    if (allowedFileTypes) {
333                        var typesArray = allowedFileTypes.split(',');
334                        unqiueCollection['SUPPORTED_FORMATS'] = typesArray;
335                    }
336
337                    // only keep other file types if specified
338                    if (otherFileTypes) {
339                        var extensions = otherFileTypes.match(/\w+/g);
340                        if( allowedFileTypes) {
341                            unqiueCollection['SUPPORTED_FORMATS'] = unqiueCollection['SUPPORTED_FORMATS'].concat(extensions);
342                        } else {
343                            unqiueCollection['SUPPORTED_FORMATS'] = extensions;
344                        }
345                    }
346
347                    const defaultMessage = dropzone.querySelector("p");
348                    const allowMultiple = getElementsByAttribute('data-multiple', index) === "true";
349                    fileInput.multiple = allowMultiple;
350
351                    const fileWrapper = document.createElement("div");
352                    fileWrapper.id = "file-wrapper";
353
354                    if (!(pathname.includes('landingPagePreview') || pathname.includes('showLandingPage'))) {
355                        fileWrapper.style.minWidth = "45%";
356                    }
357
358                    fileList.appendChild(fileWrapper);
359
360                    dropzone.addEventListener("dragover", function (event) {
361                        event.preventDefault();
362                    });
363
364                    dropzone.addEventListener('drop', function (event) {
365                        event.preventDefault();
366                        const files = Array.from(event.dataTransfer.files);
367
368                        const dataTransfer = new DataTransfer();
369                        files.forEach(file => dataTransfer.items.add(file));
370                        fileInput.files = dataTransfer.files;
371                        handleNewFiles(files);
372                        validateField(fileInput, { isFileUpload: true });
373                    });
374
375                    fileInput.addEventListener('change', function () {
376                        const files = Array.from(fileInput.files);
377                        if (files.length === 0) {
378                            return;
379                        }
380
381                        const dataTransfer = new DataTransfer();
382                        files.forEach(file => dataTransfer.items.add(file));
383                        fileInput.files = dataTransfer.files;
384
385                        handleNewFiles(files);
386                        validateField(fileInput, { isFileUpload: true });
387                    });
388
389                    function handleNewFiles(files) {
390                        const { files: storedFiles, fileElementsMap } = unqiueCollection;
391
392                        if (!allowMultiple) {
393                            const newFile = files[0];
394                            if (!newFile) return;
395
396                            const existingFileNames = storedFiles.map(file => file.name);
397                            if (existingFileNames.includes(newFile.name)) {
398                                return;
399                            }
400
401                            unqiueCollection.files = [newFile];
402                            unqiueCollection.fileStatuses = [{ fileName: newFile.name, status: "PENDING" }];
403                            fileElementsMap.clear();
404                            fileWrapper.innerHTML = "";
405                            updateDropzoneContent([newFile]);
406                        } else {
407                            const existingFileNames = storedFiles.map(file => file.name);
408                            const uniqueFiles = files.filter(file => !existingFileNames.includes(file.name));
409
410                            const remainingSlots = maxUploads - storedFiles.length;
411                            if (remainingSlots <= 0) {
412                                alert(`You can only upload up to ${maxUploads} files.`);
413                                return;
414                            }
415
416                            const filesToAdd = uniqueFiles.slice(0, remainingSlots);
417
418                            if (filesToAdd.length === 0) {
419                                return;
420                            }
421
422                            unqiueCollection.files = mergeFiles(storedFiles, filesToAdd);
423
424                            filesToAdd.forEach(file => {
425                                unqiueCollection.fileStatuses.push({
426                                    fileName: file.name,
427                                    status: "PENDING",
428                                });
429                            });
430                            updateDropzoneContent(filesToAdd);
431                        }
432                        updateUploadStatusVisibility();
433                        showOrHideSubmitButtons()
434                    }
435
436                    function mergeFiles(existingFiles, newFiles) {
437                        const fileMap = new Map();
438
439                        existingFiles.forEach(file => fileMap.set(file.name, file));
440                        newFiles.forEach(file => {
441                            if (!fileMap.has(file.name)) {
442                                fileMap.set(file.name, file);
443                            }
444                        });
445
446                        return Array.from(fileMap.values());
447                    }
448
449                    function updateDropzoneContent(files) {
450                        const { fileElementsMap } = unqiueCollection;
451
452                        if (files.length === 0) {
453                            defaultMessage.style.display = "block";
454                            fileList.style.display = "none";
455                        } else {
456                            defaultMessage.style.display = "none";
457                            fileList.style.display = "block";
458
459                            files.forEach(function (file) {
460                                if (!fileElementsMap.has(file.name)) {
461                                    var fileContainer = document.createElement("div");
462                                    fileContainer.id = "file-container";
463
464                                    var removeIcon = document.createElement("div");
465                                    removeIcon.id = "remove-icon";
466                                    removeIcon.innerHTML = getRemoveIconSvg();
467
468                                    var tooltip = document.createElement("div");
469                                    tooltip.id = "tooltip";
470                                    tooltip.textContent = "Remove file";
471
472                                    var tooltipArrow = document.createElement("div");
473                                    tooltip.appendChild(tooltipArrow);
474
475                                    removeIcon.addEventListener("click", function () {
476                                        const { fileStatuses } = unqiueCollection;
477
478                                        const fileStatus = fileStatuses.find(f => f.fileName === file.name);
479                                        if (fileStatus && fileStatus.status === "DONE") {
480                                            const accountId = options.accountId;
481                                            const jwtToken = fileStatus.jwtToken;
482
483                                            if (jwtToken) {
484                                                removeIcon.style.disabled = true;
485                                                removeIcon.style.opacity = "0.7";
486                                                removeIcon.style.cursor = "wait";
487                                                removeIcon.style.pointerEvents = "none";
488
489                                              deleteAttachmentByToken(jwtToken, accountId, options.domain, scheme)
490                                                  .then((isSuccessful) => {
491                                                      if (isSuccessful) {
492                                                          removeFileLocally();
493                                                      } else {
494                                                          restoreRemoveIconStyles();
495                                                          alert("Something went wrong. We couldn’t delete the file. Please try again.");
496                                                      }
497                                                  })
498                                                  .catch(() => {
499                                                      restoreRemoveIconStyles();
500                                                      alert("Network error occurred.");
501                                                  });
502                                            } else {
503                                                restoreRemoveIconStyles();
504                                                alert("Invalid attachmentId or accountId for removal.");
505                                            }
506                                        } else {
507                                            removeFileLocally();
508                                        }
509
510                                        function removeFileLocally() {
511                                            fileWrapper.removeChild(fileContainer);
512
513                                            unqiueCollection.files = unqiueCollection.files.filter(storedFile => storedFile.name !== file.name);
514                                            unqiueCollection.fileStatuses = fileStatuses.filter(f => f.fileName !== file.name);
515
516                                            const dataTransfer = new DataTransfer();
517                                            unqiueCollection.files.forEach(file => dataTransfer.items.add(file));
518                                            fileInput.files = dataTransfer.files;
519
520                                            unqiueCollection.fileElementsMap.delete(file.name);
521
522                                            if (unqiueCollection.files.length === 0) {
523                                                const dropzoneElements = document.querySelectorAll("#dropzone-text");
524                                                const dropzoneEl = dropzoneElements[index];
525
526                                                dropzoneEl.style.display = "block";
527                                                fileList.style.display = "none";
528                                            }
529
530                                            updateFileUploadMetadata(unqiueCollection, index);
531                                            removeFileStatus(uniqueDropzoneId, file.name);
532                                            updateUploadStatusVisibility();
533                                        }
534
535                                        function restoreRemoveIconStyles() {
536                                            removeIcon.style.disabled = false;
537                                            removeIcon.style.opacity = "1";
538                                            removeIcon.style.cursor = "pointer";
539                                            removeIcon.style.pointerEvents = "auto";
540                                        }
541                                    });
542
543                                    removeIcon.addEventListener("mouseenter", function () {
544                                        removeIcon.appendChild(tooltip);
545                                        tooltip.style.left = "50%";
546                                        tooltip.style.bottom = `${removeIcon.offsetHeight + 10}px`;
547                                        tooltip.style.transform = "translateX(-50%)";
548
549                                        tooltip.style.opacity = "1";
550                                        tooltip.style.transform = "translate(-50%, 0)";
551                                    });
552
553                                    removeIcon.addEventListener("mouseleave", function () {
554                                        tooltip.style.opacity = "0";
555                                        setTimeout(() => {
556                                            if (tooltip.parentNode === removeIcon) {
557                                                removeIcon.removeChild(tooltip);
558                                            }
559                                        }, 200);
560                                    });
561
562                                    fileContainer.addEventListener("mouseover", function () {
563                                        if (progressBarWrapper.style.display !== "block") {
564                                            removeIcon.style.display = "block";
565                                        }
566                                    });
567
568                                    fileContainer.addEventListener("mouseout", function () {
569                                        removeIcon.style.display = "none";
570                                    });
571
572                                    var fileDetailsWrapper = document.createElement("div");
573                                    fileDetailsWrapper.id = "file-details-wrapper";
574
575                                    var fileNameContainer = document.createElement("div");
576                                    fileNameContainer.id = "file-name-container";
577
578                                    var fileName = document.createElement("div");
579                                    fileName.id = "file-name";
580                                    fileName.textContent = shortenFileName(file.name, 12);
581
582                                    fileNameContainer.appendChild(fileName);
583
584                                    var fileSizeContainer = document.createElement("div");
585                                    fileSizeContainer.id = "file-size-container";
586
587                                    var fileSize = document.createElement("div");
588                                    fileSize.id = "file-size";
589                                    fileSize.textContent = "0 KB of " + (file.size / 1024).toFixed(2) + " KB";
590
591                                    fileSizeContainer.appendChild(fileSize);
592
593                                    fileDetailsWrapper.appendChild(fileNameContainer);
594                                    fileDetailsWrapper.appendChild(fileSizeContainer);
595
596                                    var statusWrapper = document.createElement("div");
597                                    statusWrapper.id = "status-wrapper";
598
599                                    var progressBarWrapper = document.createElement("div");
600                                    progressBarWrapper.id = "progress-bar-wrapper";
601
602                                    var progressBar = document.createElement("div");
603                                    progressBar.id = "progress-bar";
604
605                                    var statusIconContainer = document.createElement("div");
606                                    statusIconContainer.id = "status-icon-container";
607
608                                    var statusIcon = document.createElement("div");
609                                    statusIcon.id = "status-icon";
610                                    statusIcon.innerHTML = "";
611                                    statusIconContainer.appendChild(statusIcon);
612
613                                    var statusMessageContainer = document.createElement("div");
614                                    statusMessageContainer.id = "status-message-container";
615
616                                    var statusMessage = document.createElement("div");
617                                    statusMessage.id = "status-message";
618                                    statusMessage.textContent = "";
619
620                                    statusMessageContainer.appendChild(status
620Message);
621
622                                    progressBarWrapper.appendChild(progressBar);
623                                    statusWrapper.appendChild(progressBarWrapper);
624                                    statusWrapper.appendChild(statusIconContainer);
625                                    statusWrapper.appendChild(statusMessageContainer);
626
627                                    fileContainer.appendChild(removeIcon);
628                                    fileContainer.appendChild(fileDetailsWrapper);
629                                    fileContainer.appendChild(statusWrapper);
630
631                                    fileWrapper.appendChild(fileContainer);
632
633                                    fileElementsMap.set(file.name, {
634                                        fileContainer,
635                                        progressBarWrapper,
636                                        progressBar,
637                                        statusMessage,
638                                        fileSize,
639                                        statusIcon,
640                                    });
641
642                                    uploadFile(file, progressBar, statusMessage, fileSize, statusIcon, statusWrapper, fileContainer, removeIcon, progressBarWrapper);
643                                }
644                            });
645                        }
646                    }
647
648
649                    function shortenFileName(fileName, maxLength) {
650                        if (fileName.length <= maxLength) return fileName;
651                        var fileExtension = fileName.split('.').pop();
652                        var baseName = fileName.substring(0, maxLength - fileExtension.length - 3);
653                        return baseName + "..." + fileExtension;
654                    }
655
656                    function checkImageDimensions(file) {
657                        const maxPixels = 10000;
658
659                        return new Promise(function(resolve, reject) {
660                            createImageBitmap(file).then(function(bitmap) {
661                                const width = bitmap.width;
662                                const height = bitmap.height;
663
664                                bitmap.close();
665
666                                resolve({
667                                    valid: width <= maxPixels && height <= maxPixels,
668                                    width: width,
669                                    height: height
670                                });
671                            }).catch(function() {
672                                reject(new Error('Failed to read image dimensions'));
673                            });
674                        });
675                    }
676
677                    function uploadFile(file, progressBar, statusMessage, fileSize, statusIcon, statusWrapper, fileContainer, removeIcon, progressBarWrapper) {
678
679                        const fileExtension = file.name.split('.').pop().toLowerCase();
680                        const fileGeneralErrorMessage = unqiueCollection.fileMessages.fileGeneralErrorMessage;
681                        const fileSizeErrorMessage = unqiueCollection.fileMessages.fileSizeErrorMessage
682                        const fileAllowedTypesErrorMessage  = unqiueCollection.fileMessages.fileAllowedTypesErrorMessage
683                        const imageMaxDimensionsErrorMessage = 'Image dimensions exceed the maximum size of 10,000 pixels'
684
685                        if (file.size > MAX_FILE_SIZE) {
686                            statusMessage.textContent = fileSizeErrorMessage;
687                            updateFileStatus(allowMultiple, uniqueDropzoneId, file.name, "WARNING");
688                            if (fileSizeErrorMessage.length > 52) {
689                                fileContainer.style.alignItems = 'baseline';
690                                statusWrapper.style.alignItems = 'baseline';
691                                statusMessage.style.maxWidth = "318px";
692                            }
693                            statusIcon.innerHTML = getErrorIconSVG();
694                            showOrHideSubmitButtons();
695
696                            return;
697                        }
698
699                        
700                        if (!unqiueCollection['SUPPORTED_FORMATS'].some(el => el && el.includes(fileExtension))) {
701                            statusMessage.textContent = fileAllowedTypesErrorMessage;
702                            updateFileStatus(allowMultiple, uniqueDropzoneId, file.name, "WARNING");
703                            if (fileAllowedTypesErrorMessage.length > 52) {
704                                fileContainer.style.alignItems = 'baseline';
705                                statusWrapper.style.alignItems = 'baseline';
706                                statusMessage.style.maxWidth = "318px";
707                            }
708
709                            statusIcon.innerHTML = getErrorIconSVG();
710                            showOrHideSubmitButtons();
711                            return;
712                        }
713
714                        const progressStep = 33.33;
715                        let currentProgress = 0;
716                        let simulatedProgress = 66;
717                        let updateInterval;
718
719                        const updateProgress = (targetProgress) => {
720                            updateFileStatus(allowMultiple, uniqueDropzoneId, file.name, "IN_PROGRESS");
721
722                            if (updateInterval) clearInterval(updateInterval);
723                            updateInterval = setInterval(() => {
724                                if (currentProgress < targetProgress) {
725                                    currentProgress += 0.5;
726                                    progressBar.style.width = `${currentProgress}%`;
727                                    fileSize.textContent = `${((currentProgress / 100) * file.size / 1024).toFixed(2)} KB of ${(file.size / 1024).toFixed(2)} KB`;
728                                } else {
729                                    clearInterval(updateInterval);
730                                }
731                            }, 50);
732                        };
733
734                        const finalizeProgress = (attachmentId, jwtToken) => {
735                            clearInterval(updateInterval);
736                            progressBar.style.width = "100%";
737                            fileSize.textContent = `${(file.size / 1024).toFixed(2)} KB of ${(file.size / 1024).toFixed(2)} KB`;
738                            setTimeout(() => {
739                                statusMessage.textContent = "Completed";
740                                statusIcon.innerHTML = getSuccessIconSVG();
741                                progressBarWrapper.style.display = "none";
742                                updateFileStatus(allowMultiple, uniqueDropzoneId, file.name, "DONE", attachmentId, jwtToken);
743
744                                updateFileUploadMetadata(unqiueCollection, index);
745                                updateUploadStatusVisibility();
746                                showOrHideSubmitButtons();
747                            }, 2000);
748
749                        };
750
751                        const showError = (message) => {
752                            updateFileStatus(allowMultiple, uniqueDropzoneId, file.name, "WARNING");
753                            clearInterval(updateInterval);
754                            progressBarWrapper.style.display = "none";
755                            statusMessage.textContent = message;
756                            statusIcon.innerHTML = getErrorIconSVG();
757                            updateUploadStatusVisibility();
758                            showOrHideSubmitButtons();
759                        };
760
761                        // 1. Store Request (0–33%)
762                        const storeRequest = () => {
763                            updateFileStatus(allowMultiple, uniqueDropzoneId, file.name, "IN_PROGRESS");
764
765                            const controller = new AbortController();
766                            const signal = controller.signal;
767
768                            const xhr = new XMLHttpRequest();
769
770                            var url = scheme + options.domain + ACTON_BASE_URL + "/file-process/";
771                            xhr.open("POST", url, true);
772                            xhr.setRequestHeader( 'Content-Type', 'application/json' );
773
774                            xhr.signal = signal;
775
776                            xhr.onload = () => {
777                                updateProgress(progressStep);
778                                if (xhr.status === 200) {
779                                    const response = JSON.parse(xhr.responseText);
780                                    const uploadUrl = response.uploadUrl;
781                                    uploadToS3(uploadUrl);
782                                } else {
783                                    showError(fileGeneralErrorMessage);
784                                    controller.abort();
785                                }
786                            };
787
788                            xhr.onerror = () => {
789                                showError(fileGeneralErrorMessage);
790                                controller.abort();
791                            };
792
793                            xhr.send(
794                              JSON.stringify({
795                                  accountId: options.accountId,
796                                  userId: 1,
797                                  identifier: options.id.replace(':', '_'),
798                                  fullFileName: file.name,
799                                  objectId: options.id.split(":")[0],
800                                  objectType: "FORM",
801                                  mimeType: file.type,
802                              })
803                            );
804                        };
805
806                        // 2. Upload to S3 (33–66%)
807                        const uploadToS3 = (uploadUrl) => {
808                            const controller = new AbortController();
809                            const signal = controller.signal;
810
811                            const xhr = new XMLHttpRequest();
812                            xhr.open("PUT", uploadUrl, true);
813                            xhr.setRequestHeader("Content-Type", file.type);
814                            xhr.signal = signal;
815
816                            xhr.upload.onprogress = (event) => {
817                                if (event.lengthComputable) {
818                                    const targetProgress = progressStep + (event.loaded / event.total) * progressStep;
819                                    updateProgress(targetProgress);
820                                }
821                            };
822
823                            xhr.onload = () => {
824                                if (xhr.status === 200) {
825                                    confirmUpload(uploadUrl);
826                                } else {
827                                    showError(fileGeneralErrorMessage);
828                                    controller.abort();
829                                }
830                            };
831
832                            xhr.onerror = () => {
833                                showError(fileGeneralErrorMessage);
834                                controller.abort();
835                            };
836
837                            xhr.send(file);
838                        };
839
840                        // 3. Confirm Upload and File-Scan (66–100%)
841                        const confirmUpload = (uploadUrl) => {
842                            const controller = new AbortController();
843                            const signal = controller.signal;
844
845                            const xhr = new XMLHttpRequest();
846
847                            var url = scheme + options.domain + ACTON_BASE_URL + "/file-process/confirm";
848                            xhr.open("POST", url, true);
849                            xhr.setRequestHeader( 'Content-Type', 'application/json' );
850                            xhr.signal = signal;
851
852                            xhr.onload = () => {
853                                if (xhr.status === 200) {
854                                    pollFileStatus(uploadUrl);
855                                } else {
856                                    showError(FILE_SCAN_ERROR_TEXT);
857                                    controller.abort();
858                                }
859                            };
860
861                            xhr.onerror = () => {
862                                showError(FILE_SCAN_ERROR_TEXT);
863                                controller.abort();
864                            };
865
866                            xhr.send(JSON.stringify({ tempUrl: uploadUrl }));
867                        };
868
869                        const handlePollingError = (fileName, dropzoneId, errorMessage, controller) => {
870                            const dropzoneState = dropzoneFileCollections[dropzoneId]["pollingState"][fileName];
871                            if (dropzoneState) {
872                                dropzoneState.isPolling = false;
873                                clearInterval(dropzoneState.interval);
874                            }
875                            controller.abort();
876                            showError(errorMessage);
877                        };
878
879                        const pollFileStatus = (uploadUrl) => {
880                            const controller = new AbortController();
881                            const signal = controller.signal;
882
883                            const pollingIntervalMs = 4000;
884                            const maxPollingTimeMs = 1 * 60 * 1000;
885                            const maxAttempts = Math.floor(maxPollingTimeMs / pollingIntervalMs);
886                            let attemptCount = 0;
887
888                            const pollingState = unqiueCollection["pollingState"];
889                            if (!pollingState[file.name]) {
890                                pollingState[file.name] = { isPolling: false, interval: null };
891                            }
892
893                            const dropzoneState = unqiueCollection["pollingState"][file.name];
894
895                            if (dropzoneState.isPolling) return;
896                            dropzoneState.isPolling = true;
897
898                            const startPolling = () => {
899                                dropzoneState.interval = setInterval(() => {
900                                    if (attemptCount >= maxAttempts) {
901                                        handlePollingError(file.name, uniqueDropzoneId, "Polling timed out. Please try again.");
902                                        controller.abort();  // Abort the request if polling times out
903                                        return;
904                                    }
905
906                                    const xhr = new XMLHttpRequest();
907
908                                    var url = scheme + options.domain + ACTON_BASE_URL + "/file-scanning/statuses";
909                                    xhr.open("POST", url, true);
910                                    xhr.setRequestHeader( 'Content-Type', 'application/json' );
911                                    xhr.signal = signal;
912
913                                    xhr.onload = () => {
914                                        simulatedProgress = Math.min(simulatedProgress + Math.floor(Math.random() * 11), 99);
915                                        progressBar.style.width = `${simulatedProgress}%`;
916                                        fileSize.textContent = `${((simulatedProgress / 100) * file.size / 1024).toFixed(2)} KB of ${(file.size / 1024).toFixed(2)} KB`;
917
918                                        if (xhr.status === 200) {
919                                            const response = JSON.parse(xhr.responseText);
920                                            const statuses = response;
921
922                                            if (statuses && statuses.length > 0) {
923                                                const status = statuses[0];
924                                                if (status.status === "IN_PROGRESS") {
925                                                    updateFileStatus(allowMultiple, uniqueDropzoneId, file.name, "IN_PROGRESS");
926                                                } else if (status.status === "DONE") {
927                                                    if (!(status.attachmentId || status.url)) {
928                                                        pollFileStatus(uploadUrl);
929                                                    } else {
930                                                        dropzoneState.isPolling = false;
931                                                        clearInterval(dropzoneState.interval);
932                                                        finalizeProgress(status.attachmentId, status.jwtToken);
933                                                    }
934                                                } else if (status.status === "FAILED") {
935                                                    handlePollingError(file.name, uniqueDropzoneId, FILE_SCAN_ERROR_TEXT, controller);
936                                                }
937                                            } else {
938                                                handlePollingError(file.name, uniqueDropzoneId, FILE_SCAN_ERROR_TEXT, controller);
939                                            }
940                                        } else {
941                                            handlePollingError(file.name, uniqueDropzoneId, FILE_SCAN_ERROR_TEXT, controller);
942                                        }
943                                    };
944
945                                    xhr.onerror = () => {
946                                        handlePollingError(file.name, uniqueDropzoneId, FILE_SCAN_ERROR_TEXT, controller);
947                                    };
948
949                                    xhr.send(JSON.stringify([uploadUrl]));
950                                    attemptCount++;
951                                }, pollingIntervalMs);
952                            };
953
954                            startPolling();
955                        };
956
957                        if(file.type.startsWith('image/')){
958                            checkImageDimensions(file).then(function(result) {
959                                if(!result.valid){
960                                    statusMessage.textContent = imageMaxDimensionsErrorMessage;
961                                    updateFileStatus(allowMultiple, uniqueDropzoneId, file.name, "WARNING");
962                                    fileContainer.style.alignItems = 'baseline';
963                                    statusWrapper.style.alignItems = 'baseline';
964                                    statusMessage.style.maxWidth = "318px";
965                                    statusIcon.innerHTML = getErrorIconSVG();
966                                    showOrHideSubmitButtons();
967
968                                    return;
969                                }
970                                else {
971                                    progressBarWrapper.style.display = "block";
972                                    removeIcon.style.display = "none";
973                                    storeRequest();
974                                }
975                            })
976                        } else {
977                            progressBarWrapper.style.display = "block";
978                            removeIcon.style.display = "none";
979                            storeRequest();
980                        }
981                    }
982
983                    function updateUploadStatusVisibility() {
984                        const uploadStatuses = document.querySelectorAll('#upload-status');
985                        const statusEL = uploadStatuses[index];
986                        const anyInProgress = Array.from(unqiueCollection.fileElementsMap.values()).some(
987                          (fileData) => fileData.progressBarWrapper.style.display === "block"
988                        );
989                        statusEL.style.display = anyInProgress ? "block" : "none";
990                    }
991                }
992            });
993        });
994
995            if(response.formProperties && ! response.formProperties.invalidDomain){
996                //Set referrer
997                div.querySelector("input[name='ao_refurl']").value = document.referrer;
998                div.querySelector("input[name='ao_target']").value = window.location.href;
999                div.querySelector("input[name='ao_refemail']").value = getParameterByName("aoRefEmail");
1000                div.querySelector("input[name='ao_campid']").value = getParameterByName("cmpid");
1001                div.querySelector("input[name='ao_gatedpage']").value = getParameterByName("ao_gatedpage");
1002                div.querySelector("input[name='ao_gatedasset']").value = getParameterByName("ao_gatedasset");
1003
1004                var ajaxSubmit = response && response.formProperties && response.formProperties.hasAjaxResponse ? response.formProperties.hasAjaxResponse : false;
1005
1006                loadCaptcha();
1007                !!response.formProperties.removeFormTabIndexes
1008                    ? removeTabIndexes()
1009                    : updateTabIndexes();
1010                loadGoogleFonts();
1011
1012                formValidationEvents(div, ajaxSubmit);
1013
1014
1015                // Form Prefill
1016                if ( response.prefill && Object.keys( response.prefill ).length > 0 ) {
1017                    var fields = Object.keys( response.prefill );
1018
1019                    fields.forEach( function( field ) {
1020                        var input = div.querySelector("input[name='" + field + "']");
1021                        var select = div.querySelector("select[name='" + field + "']");
1022                        var textarea = div.querySelector("textarea[name='" + field + "']");
1023
1024                        if ( ! input && ! select && ! textarea ) {
1025                            return;
1026                        }
1027
1028                        if(input){
1029                            if(input.type== "radio"){
1030                                var radios = div.querySelectorAll("input[name='" + field + "']");
1031                                for(var i = 0; i<radios.length; i++){
1032                                    if(radios[i].value == response.prefill[field]){
1033                                        radios[i].checked = true;
1034                                    }
1035                                }
1036                            } else if(input.type== "checkbox") {
1037                                if ( ! response.prefill[field] ) { return true; }
1038                                var checkboxes = div.querySelectorAll("input[name='" + field + "']");
1039                                var values = response.prefill[field].split(/[;,]/);
1040
1041                                for(var i = 0; i<checkboxes.length; i++){
1042                                    for(var j = 0; j<values.length; j++) {
1043                                        var strippedVal = values[j].replace(/^\^(.+(?=\^$))\^$/, '$1');
1044                                        if (checkboxes[i].value == strippedVal) {
1045                                            checkboxes[i].checked = true;
1046                                        }
1047                                    }
1048                                }
1049                            } else if (input.type=="text"){
1050                                div.querySelector("input[name='" + field + "']").value = response.prefill[field];
1051                            } else if (input.type === 'hidden' && input.className === 'ao-form-field-date-input') {
1052                              populateDateField(input, response.prefill[field]);
1053                            }
1054                        } else if(textarea) {
1055                            div.querySelector("textarea[name='" + field + "']").value = response.prefill[field];
1056                        } else if(select){
1057                            for (var i = 0; i < select.options.length; i++) {
1058                                if (select.options[i].text == response.prefill[field]) {
1059                                    select.options[i].selected = true;
1060                                }
1061                            }
1062                        }
1063                    });
1064                }
1065
1066                // init the rule listeners here
1067                if ( response.formProperties && response.formProperties.hasRules === true ) {
1068                    loadRules( options.accountId, options.id, response.watchFields, options, div);
1069                } else {
1070                    div.style.visibility = "visible";
1071				}
1072
1073                //Post Load Callback (universal)
1074                if (typeof aoPostLoadCallback === 'function') {
1075                    aoPostLoadCallback();
1076                }
1077
1078                //Post Load Callback (form specific)
1079                if(aoPostLoadFormCallback[divId] && typeof aoPostLoadFormCallback[divId] === 'function'){
1080                    aoPostLoadFormCallback[divId]();
1081                }
1082
1083                //Post Load Callback
1084                if (typeof aoPostLoadCallbackInternal === 'function') {
1085                    aoPostLoadCallbackInternal();
1086                }
1087			} else {
1088                div.style.visibility = "visible";
1089			}
1090		};
1091
1092		var url;
1093
1094		if(options.isTemp) {
1095			url = scheme + options.domain + '/acton/internalapi/FormBuilder/' + options.accountId + '/form/temp/' + options.id + '?ts=' + new Date().getTime() + "&noStyle=" + ((options.noStyle) ? "1" : "") + "&prefilledData=" + ((options.prefilledData) ? options.prefilledData : "");
1096		} else if(options.recId) {
1097            url = scheme + options.domain + '/acton/internalapi/FormBuilder/' + options.accountId + '/form/' + options.id + '?ts=' + new Date().getTime() + "&noStyle=" + ((options.noStyle) ? "1" : "") + "&prefilledData=" + ((options.prefilledData) ? options.prefilledData : "") + "&recId=" + ((options.recId) ? options.recId : "");
1098        } else {
1099            var useParentDomain = '';
1100      if (document.location.pathname.includes("subscriberPreviewPane.jsp") || document.location.pathname.includes("read/snippet/form")) {
1101                useParentDomain = '&assetNotAccepted=' + true;
1102            }
1103            url = scheme + options.domain + "/acton/openapi/form/v1/" + options.accountId + "/" + options.id + '?ts=' +
1104                new Date().getTime() + (options.noStyle ? "&noStyle=1" : "" ) + (options.prefill ? "&prefill=1" : "") +
1105                useParentDomain;
1106		}
1107
1108        var gated_asset = getParameterByName("ao_gatedasset");
1109        url += gated_asset ? "&ga=" + gated_asset : '';
1110
1111		oReq.open('GET', url, true);
1112		oReq.responseType = 'json';
1113        oReq.withCredentials = true;
1114		oReq.send();
1115	};
1116
1117	var loadStylesheet = function(options){
1118		if(! stylesLoaded){
1119			var styleTag = document.createElement("link");
1120			styleTag.rel = "stylesheet";
1121			styleTag.type = "text/css";
1122			styleTag.href =  scheme + options.domain + "/acton/content/form_flattener.css";
1123			styleTag.media = "all";
1124			document.getElementsByTagName('head')[0].appendChild(styleTag);
1125			stylesLoaded = true;
1126		}
1127	};
1128
1129	var loadCaptcha = function(){
1130
1131		//Only load captcha if at least one form on the page actually has a reCAPTCHA block rendered
1132		if(! captchaLoaded && (formsCount == formsLoadedCount) && document.querySelector(".g-recaptcha")){ //Don't load captcha until all forms that exist on page are loaded
1133			var scriptTag = document.createElement("script");
1134
1135			scriptTag.src = "https://www.google.com/recaptcha/api.js";
1136			scriptTag.defer = true;
1137            scriptTag.async = true;
1138
1139			document.getElementsByTagName('head')[0].appendChild(scriptTag);
1140			captchaLoaded = true;
1141
1142
1143		}
1144	};
1145
1146    var removeTabIndexes = function() {
1147        if (formsLoadedCount > 0) {
1148            const actonForms = document.querySelectorAll("form.ao-form");
1149            for (let i = 0; i < actonForms.length; i++) {
1150                const inputFields = actonForms[i].querySelectorAll('[tabindex]');
1151                for (let j = 0; j < inputFields.length; j++) {
1152                    inputFields[j].removeAttribute("tabindex");
1153                }
1154            }
1155        }
1156
1157    }
1158
1159	var updateTabIndexes = function(){
1160	    //If multiple forms on one page, update each new form with higher tab index (100+) than previous form)
1161        if(formsCount == formsLoadedCount && formsLoadedCount > 1) {
1162            var actonForms = document.querySelectorAll("form.ao-form");
1163
1164            var startingTabIndex = 100;
1165            for(var i = 1; i<actonForms.length; i++){
1166                var inputFields = actonForms[i].querySelectorAll('[tabindex]');
1167                for(var j=0; j<inputFields.length; j++){
1168                    inputFields[j].tabIndex = inputFields[j].tabIndex + startingTabIndex;
1169                }
1170                startingTabIndex = startingTabIndex + 100;
1171            }
1172        }
1173    };
1174
1175    var loadGoogleFonts = function(){
1176
1177        if(! gfLoaded){
1178            var scriptTag = document.createElement("script");
1179
1180            scriptTag.src = "https://ajax.googleapis.com/ajax/libs/webfont/1.5.18/webfont.js";
1181            scriptTag.defer = true;
1182            scriptTag.async = true;
1183
1184            document.getElementsByTagName('head')[0].appendChild(scriptTag);
1185            gfLoaded = true;
1186        }
1187    };
1188
1189	var evalFacts = function( accountId, formId, watchFields, options, containerDiv) {
1190
1191		var fact = {
1192			data : {}
1193		};
1194
1195        if ( formId.indexOf(':') > -1 ) {
1196            formId = formId.substr(0, formId.indexOf(':'));
1197        }
1198
1199        if(options.uniqueId){
1200            formId += (options.uniqueId) ? options.uniqueId : '';
1201        }
1202
1203		var formByID = document.getElementById("aoform-" + formId);
1204
1205		watchFields.forEach( function ( field ) {
1206
1207        // Webinar form block IDs are just numbers and do not start with `block-` or `b`
1208        var fieldElm = field.startsWith("b")
1209            ? formByID.querySelector("#" + field)
1210            : document.getElementById(field);
1211
1212        if (!fieldElm) {
1213            fieldElm = formByID.querySelector("#block-" + field);
1214        }
1215
1216        if(fieldElm){
1217                if(fieldElm.nodeName == "DIV" && fieldElm.classList.contains("ao-combo-layout")) {
1218                    var radios = fieldElm.querySelectorAll("input[type='radio'],input[type='checkbox']");
1219                    fact.data[field] = "";
1220
1221                    for (var i = 0; i < radios.length; i++) {
1222                        if (radios[i].checked) {
1223                            fact.data[field] += radios[i].value;
1224                        }
1225                    }
1226                }else if(fieldElm.nodeName=="DIV" && fieldElm.classList.contains("ao-date-block")) {
1227                    /*
1228                    Get parent div of a date control, then get all "ao-form-field-date" objects from that div
1229                    Build a date object from those, and set as value. If it's an invali
1229d date, value = null
1230
1231                    Date fields are tagged with id "date-<PART>-<ID>"
1232                     */
1233
1234                    var dtMonth = "";
1235                    var dtDay = "";
1236                    var dtYear = "";
1237                    var txtInputs = fieldElm.querySelectorAll("input[type='text']");
1238                    var dtMonth = "";
1239                    var dtDay = "";
1240                    var dtYear = "";
1241                    var txtInputs = fieldElm.querySelectorAll("input[type='text']");
1242                    var hasDateError = false;
1243                    for(var i=0; i < txtInputs.length; i++){
1244                        if (txtInputs[i].value == ""){
1245                            hasDateError = true;
1246                        }
1247                        switch(txtInputs[i].getAttribute("data-format")){
1248                            case "DD":
1249                                dtDay = txtInputs[i].value;
1250                                break;
1251                            case "MM":
1252                                dtMonth = txtInputs[i].value;
1253                                break;
1254                            case "YY":
1255                                dtYear = txtInputs[i].value;
1256                                break;
1257                            case "YYYY":
1258                                dtYear = txtInputs[i].value;
1259                                break;
1260                        }
1261                    }
1262                    if (!hasDateError){
1263                        fact.data[field] = dtYear + dtMonth + dtDay;
1264                    }else{
1265                        fact.data[field] = "";
1266                    }
1267                } else {
1268                    fact.data[field] = fieldElm.value;
1269                }
1270            }
1271		});
1272
1273		var body = {
1274			payload : {
1275				accountId : accountId,
1276                key : formId,
1277                facts : [fact]
1278            }
1279		};
1280
1281		var xhr = new XMLHttpRequest();
1282		xhr.open( 'PUT', scheme + options.domain + '/acton/openapi/form/v1/' + options.accountId + '/' + formId + '/factEval' );
1283        xhr.setRequestHeader( 'Content-Type', 'application/json' );
1284        xhr.send( JSON.stringify( body ) );
1285
1286        // Check if the active element lost focus due to conflicting conditionals such as hide / show,
1287        // Give focus back if lost focus and not hidden
1288        function refocusIfLostFocus(activeEl) {
1289               if(activeEl !== document.activeElement && !activeEl.classList.contains("ao-condition-hide")) {
1290                    activeEl.focus();
1291               }
1292        }
1293
1294        xhr.onreadystatechange = function() {
1295               if ( xhr.readyState === XMLHttpRequest.DONE && xhr.status === 200 ) {
1296                    // Get element that has focus before hiding/showing elements
1297                    const activeEl = document.activeElement;
1298                    var response = JSON.parse(xhr.response);
1299
1300                    //Go through the non true results first and set base display
1301                    for(var i=0; i<response.results[0].result.length; i++) {
1302
1303                    var result = response.results[0].result[i].result;
1304                    var ruleName = response.results[0].result[i].name;
1305                    var consequence = response.rules[ruleName].consequences;
1306
1307                    if (!result) {
1308                        for (var j = 0; j < consequence.length; j++) {
1309
1310                            var state = consequence[j].state;
1311
1312                            if (state !== "alert") {
1313                                var field = consequence[j].field;
1314                                var elm = formByID.querySelector("#block-" + field) || formByID.querySelector("#row-" + field);
1315
1316                                if(elm){
1317                                    switch (state) {
1318
1319                                        case "show":
1320                                            elm.style.display = "none";
1321                                            formElms = elm.querySelectorAll("input, select, textarea");
1322                                            for(var k=0; k<formElms.length; k++) {
1323                                                formElms[k].disabled = true;
1324                                            }
1325                                            elm.classList.add("ao-condition-hide");
1326                                            break;
1327
1328                                        case "hide":
1329                                            elm.style.removeProperty("display");
1330                                            formElms = elm.querySelectorAll("input, select, textarea");
1331                                            for(var l=0; l<formElms.length; l++) {
1332                                                formElms[l].disabled = false;
1333                                            }
1334                                            elm.classList.remove("ao-condition-hide");
1335                                            break;
1336                                    }
1337                                }
1338                            }
1339                        }
1340                        // Check if the previously focused element is no longer focused to avoid hide / show unfocusing
1341                        refocusIfLostFocus(activeEl);
1342                    }
1343                }
1344
1345                //Show form on initial load after fields have been hidden
1346                if(containerDiv){
1347                    containerDiv.style.visibility = "visible";
1348                }
1349
1350                //Now go through the true results first and set correct display
1351                for(var i=0; i<response.results[0].result.length; i++) {
1352
1353                    var result = response.results[0].result[i].result;
1354                    var ruleName = response.results[0].result[i].name;
1355                    var consequence = response.rules[ruleName].consequences;
1356
1357                    if (result) {
1358                        for (var j = 0; j < consequence.length; j++) {
1359
1360                            var state = consequence[j].state;
1361
1362                            if (state !== "alert") {
1363                                var field = consequence[j].field;
1364                                var elm = formByID.querySelector("#block-" + field) || formByID.querySelector("#row-" + field);
1365
1366                                if(elm) {
1367                                    switch (state) {
1368
1369                                        case "show":
1370                                            elm.style.removeProperty("display");
1371
1372                                            formElms = elm.querySelectorAll("input, select, textarea");
1373                                            for(var k=0; k<formElms.length; k++) {
1374                                                formElms[k].disabled = false;
1375                                            }
1376                                            elm.classList.remove("ao-condition-hide");
1377                                            break;
1378
1379                                        case "hide":
1380                                            elm.style.display = "none";
1381                                            formElms = elm.querySelectorAll("input, select, textarea");
1382                                            for(var l=0; l<formElms.length; l++) {
1383                                                formElms[l].disabled = true;
1384                                            }
1385                                            elm.classList.add("ao-condition-hide");
1386                                            break;
1387                                    }
1388                                }
1389                            }
1390                        }
1391                        // Check if the previously focused element is no longer focused to avoid hide / show unfocusing
1392                        refocusIfLostFocus(activeEl);
1393                    }
1394                }
1395			} else {
1396				// an error occurred
1397			}
1398		};
1399	};
1400
1401	var loadRules = function( accountId, formId, watchFields, options, containerDiv) {
1402        if ( formId.indexOf(':') > -1 ) {
1403            formId = formId.substr( 0, formId.indexOf(':') )
1404        }
1405
1406		if ( !watchFields ){
1407            //Show form on initial load
1408            containerDiv.style.visibility = "visible";
1409            return;
1410		}
1411
1412		//Remove duplicate watches
1413        var watchFieldsSeen = {};
1414        var watchFieldsUnique = watchFields.filter(function(item) {
1415            return watchFieldsSeen.hasOwnProperty(item) ? false : (watchFieldsSeen[item] = true);
1416        });
1417
1418        watchFieldsUnique.forEach( function ( field ) {
1419
1420        // Webinar form block IDs are just numbers and do not start with `block-` or `b`
1421        var el = field.startsWith("b")
1422            ? containerDiv.querySelector("#" + field)
1423            : document.getElementById(field);
1424
1425            /*If fieldElm is not found, will need to check for alternatives
1426			* Most likely candidate, if "date", look for a the block, then a named child
1427			* EG: div: block-fieldID child named date*/
1428            if(!el){
1429                el = containerDiv.querySelector("#block-" + field);
1430            }
1431
1432			if(el){
1433                if(el.nodeName == "SELECT"){
1434                    el.addEventListener( 'change', function ( event ) {
1435                        // put a debounce in here so we're making requests on every keystroke
1436						var result = evalFacts( accountId, formId, watchFieldsUnique, options );
1437                    }, false );
1438                } else if(el.nodeName == "DIV" && el.classList.contains("ao-combo-layout")) {
1439                    var inputs = el.querySelectorAll("input");
1440
1441                    for (i = 0; i < inputs.length; i++) {
1442                        inputs[i].addEventListener('click', function (event) {
1443                            // put a debounce in here so we're making requests on every keystroke
1444                            if (el.classList.contains("ao-form-error")) {
1445                                el.classList.remove("ao-form-error");
1446                            }
1447                            var result = evalFacts(accountId, formId, watchFieldsUnique, options);
1448                        }, false);
1449                    }
1450                }
1451                else if(el.nodeName == "DIV" && el.classList.contains("ao-date-block")) {
1452                    var inputs = el.querySelectorAll("input");
1453
1454                    for (i = 0; i < inputs.length; i++) {
1455                        if(!inputs[i].classList.contains("ao-form-field-date-input")) {
1456                            inputs[i].addEventListener( 'keyup', debounce(function () {
1457                                evalFacts( accountId, formId, watchFieldsUnique, options );
1458                            }, 500), false);
1459                        }
1460                    }
1461
1462                } else {
1463                    el.addEventListener( 'keyup', debounce(function () {
1464                        evalFacts( accountId, formId, watchFieldsUnique, options );
1465                    }, 500), false);
1466                }
1467			}
1468		});
1469
1470        //Initial Load
1471        evalFacts( accountId, formId, watchFieldsUnique, options, containerDiv);
1472	};
1473
1474    function getParameterByName(name) {
1475    	url = window.location.href;
1476        name = name.replace(/[\[\]]/g, "\\$&");
1477        var regex = new RegExp("[?&]" + name + "(=([^&#]*)|&|#|$)", "i"),
1478            results = regex.exec(url);
1479        if (!results) return null;
1480        if (!results[2]) return '';
1481        return decodeURIComponent(results[2].replace(/\+/g, " "));
1482    }
1483
1484	var formValidationEvents = function(form, ajaxSubmit){
1485		var actonForms = form.querySelectorAll("form.ao-form");
1486
1487		var findRecaptchaElements = function(form, hasError){
1488			//Find the recaptcha wrapper
1489			var recaptchaWrapper = form.querySelectorAll(".ao-recaptcha-error-wrapper");
1490			if (recaptchaWrapper.length > 0) {
1491				if (hasError) {
1492					//If found and has error then apply the style that will show the red border around the element
1493					recaptchaWrapper[0].classList.add("ao-recaptcha-error");
1494				} else {
1495					//Remove the style because the user has attempted to work with the recaptcha again
1496					recaptchaWrapper[0].classList.remove("ao-recaptcha-error");
1497				}
1498			}
1499
1500			//Find the element that will show the failed to completed the recaptcha
1501			var recaptchaMsg = form.querySelectorAll(".ao-recaptcha-error-robot-message");
1502			if (recaptchaMsg.length > 0) {
1503				if (hasError) {
1504					//Show the text
1505					recaptchaMsg[0].style.display = "block";
1506				} else {
1507					//Hide the text
1508					recaptchaMsg[0].style.display = "none";
1509				}
1510			}
1511		};
1512
1513		var invalidCaptcha = function(form){
1514            //Wait for the Recaptcha widget before we build the error logging aorund it
1515            setTimeout(function () {
1516
1517                //Apply the styling that says the user failed to validate the Recaptcha
1518                findRecaptchaElements(form, true);
1519
1520            }, 1000);
1521
1522            //Keep checking if the user has attempted to validate the Recaptcha, we will know because the token will go into the hidden input the cap sends on submission
1523            var recaptchaInterval = setInterval(function () {
1524                var recaptchaBoxCode = form.querySelectorAll("#g-recaptcha-response");
1525
1526                //If we find the element and the value is not empty then a user has interacted with the cap, validation happens on the submission not now
1527                if (recaptchaBoxCode.length > 0 && recaptchaBoxCode[0].value !== '') {
1528
1529                    //Remove the styling that was generated by the error
1530                    findRecaptchaElements(form, false);
1531
1532                    //Remove the interval that listens for the check
1533                    window.clearInterval(recaptchaInterval);
1534                }
1535            }, 2000);
1536		};
1537
1538		for(var i=0; i<actonForms.length; i++) {
1539
1540			//Set On Blur Events For All Inputs
1541			var validationFields = actonForms[i].querySelectorAll(".ao-form-field[data-validator]:not([data-attached])");
1542			var validationCombos = actonForms[i].querySelectorAll(".ao-combo-layout[data-validator]:not([data-attached])");
1543			var validationDates =  actonForms[i].querySelectorAll(".ao-form-field-date-wrapper[data-validator]:not([data-attached])");
1544            var validationDateFields =  actonForms[i].querySelectorAll(".ao-form-field-date");
1545            var dynamicHiddenFields =  actonForms[i].querySelectorAll(".ao-hidden-block-dynamic");
1546            var validationFileUpload = actonForms[i].querySelectorAll(".ao-fileupload-field[data-validator]");
1547            var submitBlock = actonForms[i].querySelectorAll(".ao-submit-block");
1548
1549            //Set All dynamic fields on load.  Will set again on submit.
1550            for (var j = 0; j < dynamicHiddenFields.length; j++) {
1551                var fieldMatch = dynamicHiddenFields[j].getAttribute("data-dynamic-match");
1552                var fieldDefault = dynamicHiddenFields[j].getAttribute("data-dynamic-default");
1553                dynamicHiddenFields[j].value = getParameterByName(fieldMatch) || fieldDefault;
1554            }
1555
1556            for (var j = 0; j < validationDateFields.length; j++) {
1557                var currentField = validationDateFields[j];
1558
1559                (function(currentField) {
1560                    currentField.addEventListener( "keyup", function(){
1561                        var e = event || evt; // for trans-browser compatibility
1562                        var charCode = e.which || e.keyCode; // for trans-browser compatibility
1563
1564						if(charCode != 9 && charCode != 16 && this.value.length >= this.getAttribute('maxlength') ){
1565                            var node = this.nextSibling;
1566                            while (node) {
1567                                if (node.tagName=='INPUT') {
1568                                    node.focus();
1569                                    break;
1570                                }
1571                                node = node.nextSibling;
1572                            }
1573						}
1574                    })
1575                })(currentField);
1576            }
1577
1578			//check if the form id matches the param sent back on the user submission redirect of the formid that failed user submit
1579			if(htmlId.indexOf(getParameterByName("validRecaptcha")) > -1) {
1580				invalidCaptcha(form);
1581			}
1582
1583      function enableOrDisableSubmitButton(e, isEnable){
1584          if(isEnable){
1585              e.submitter.style.opacity = 1;
1586              e.submitter.style.pointerEvents = "auto";
1587              e.submitter.disabled = false;
1588          }
1589          else {
1590              e.submitter.style.opacity = 0.5;
1591              e.submitter.style.pointerEvents = "none";
1592              e.submitter.disabled = true;
1593          }
1594      }
1595
1596			if(actonForms[i].hasAttribute('data-validate-blur')){
1597
1598                for (var j = 0; j < validationFields.length; j++) {
1599                    var currentField = validationFields[j];
1600
1601                    (function(currentField) {
1602                        currentField.addEventListener( "focusout", function(){
1603                            validateField(currentField);
1604                        });
1605                        currentField.addEventListener( "change", function(){
1606                            validateField(currentField);
1607                        });
1608                    })(currentField);
1609                }
1610
1611                for (var j = 0; j < validationFileUpload.length; j++) {
1612                    var currentField = validationFileUpload[j];
1613
1614                    (function(currentField) {
1615                        currentField.addEventListener( "focusout", function(){
1616                            validateField(currentField);
1617                        });
1618                        currentField.addEventListener( "change", function(){
1619                            validateField(currentField);
1620                        });
1621                    })(currentField);
1622                }
1623			}
1624
1625			//Set On Submit Event
1626			var currentForm = actonForms[i];
1627
1628			(function(currentForm, ajaxSubmit) {
1629				currentForm.addEventListener("submit", function(e){
1630					 var passedValidation = true;
1631					for (var i = 0; i < validationFields.length; i++) {
1632						//Check visibility of field. offsetWidth/Height of null = not visible
1633                        if (!!( validationFields[i].offsetWidth || validationFields[i].offsetHeight || validationFields[i].getClientRects().length )){
1634                            if (!validateField(validationFields[i])) {
1635                                passedValidation = false;
1636                            }
1637                    	}
1638					}
1639
1640                    for (var i = 0; i < validationFileUpload.length; i++) {
1641                        //Check visibility of field. offsetWidth/Height of null = not visible
1642                        if (!validateField(validationFileUpload[i], {isFileUpload: true})) {
1643                            passedValidation = false;
1644                        }
1645                    }
1646
1647					for (var i = 0; i < validationCombos.length; i++) {
1648                        //Check visibility of field. offsetWidth/Height of null = not visible
1649                        if (!!( validationCombos[i].offsetWidth || validationCombos[i].offsetHeight || validationCombos[i].getClientRects().length )) {
1650                            if (!validateField(validationCombos[i], {isCombo: true})) {
1651                                passedValidation = false;
1652                            }
1653                        }
1654					}
1655
1656					for (var i = 0; i < validationDates.length; i++) {
1657                        if (!!( validationDates[i].offsetWidth || validationDates[i].offsetHeight || validationDates[i].getClientRects().length )) {
1658                            if (!validateField(validationDates[i], {isDate: true})) {
1659                                passedValidation = false;
1660                            }
1661                        }
1662					}
1663
1664                    for (var i = 0; i < submitBlock.length; i++) {
1665                        if (!( submitBlock[i].offsetWidth || submitBlock[i].offsetHeight || submitBlock[i].getClientRects().length )) {
1666                            passedValidation = false;
1667                        }
1668                    }
1669
1670                    for (var i = 0; i < dynamicHiddenFields.length; i++) {
1671						var fieldMatch = dynamicHiddenFields[i].getAttribute("data-dynamic-match");
1672                        var fieldDefault = dynamicHiddenFields[i].getAttribute("data-dynamic-default");
1673						dynamicHiddenFields[i].value = getParameterByName(fieldMatch) || fieldDefault;
1674                    }
1675
1676					//Set Date fields
1677					var dateBlocks = 	currentForm.querySelectorAll(".ao-date-block");
1678                    for(var i = 0; i < dateBlocks.length; i++){
1679                    	var dateBlock = dateBlocks[i];
1680                    	var dateBlockInput = dateBlock.querySelector(".ao-form-field-date-input");
1681                    	var dateBlockPartials = dateBlock.querySelectorAll(".ao-form-field-date");
1682
1683                        var dateVal = "";
1684
1685                    	for(var j=0; j<dateBlockPartials.length; j++){
1686							var partial = dateBlockPartials[j];
1687							var format = partial.getAttribute("data-format");
1688							var isHour = format === "h" || format === "H";
1689
1690                            if(format == "MM" || format == "DD" || format == "YY" || format == "YYYY"){
1691                            	if(dateVal){
1692                            		dateVal = dateVal + "/";
1693								}
1694                                dateVal += partial.value;
1695							}
1696
1697                            if(isHour || format == "mm"){
1698                                if(dateVal && isHour){
1699                                    dateVal = dateVal + " ";
1700                                }
1701
1702                                dateVal += partial.value;
1703
1704                                if(isHour && partial.value){
1705                                    dateVal = dateVal + ":";
1706                                }
1707                            }
1708
1709                            if(format == "tt"){
1710                                if(dateVal){
1711                                    dateVal = dateVal + " ";
1712                                }
1713                                dateVal += partial.value;
1714                            }
1715						}
1716
1717						dateBlockInput.value = dateVal;
1718					}
1719
1720					var captcha = currentForm.querySelector('.g-recaptcha-response');
1721
1722					// if a captcha is being used check it
1723					if ( captcha !== null ) {
1724						var captchaValue = captcha.value;
1725
1726						// if the captcha value is empty invalidate the form
1727						if ( captchaValue === '' ) {
1728							passedValidation = false;
1729                            invalidCaptcha( currentForm );
1730						}
1731					}
1732
1733					if(! passedValidation || ajaxSubmit){
1734                        e.preventDefault();
1735					}
1736
1737            if(passedValidation){
1738                showOrHideSubmitButtons(currentForm);
1739                enableOrDisableSubmitButton(e, false);
1740            }
1741
1742
1743            if(passedValidation && ajaxSubmit){
1744                var data = new FormData(currentForm);
1745
1746                var req = new XMLHttpRequest();
1747                req.onerror = function() {
1748                    enableOrDisableSubmitButton(e, true);
1749
1750                };
1751
1752                req.onload = function(){
1753                    enableOrDisableSubmitButton(e, true);
1754
1755                    var response;
1756
1757                    try {
1758                        response = JSON.parse(this.response);
1759                    } catch(e) {
1760                        response = this.response;
1761                    }
1762
1763                  if(typeof response === 'object' && response.error && response.error == "captcha"){
1764                        invalidCaptcha(currentForm);
1765							} else {
1766								var divId = currentForm.id.replace("ao-form", "aoform");
1767                                var formId = currentForm.id.replace("ao-form-", "");
1768                                var div = document.getElementById(divId);
1769
1770                                div.innerHTML = typeof response === 'string' ? response : '';
1771
1772                                //Post Submit Callback
1773                                if (typeof aoPostSubmitCallback === 'function') {
1774                                    aoPostSubmitCallback();
1775                                }
1776
1777                                //Post Submit Callback (form specific)
1778                                formId = ( formId.indexOf(':') > -1 ) ? formId.substr( 0, formId.indexOf(':') ) : formId;
1779
1780                                if(aoPostSubmitFormCallback[formId] && typeof aoPostSubmitFormCallback[formId] === 'function'){
1781                                    aoPostSubmitFormCallback[formId]();
1782                                }
1783
1784                                //Inline gated content URL is only used in the case of iOS devices
1785                                var inlineURL = document.getElementById("ao_inline-" + formId);
1786
1787                                if (inlineURL && isIOS()) {
1788                                    window.location = inlineURL.value;
1789                                }
1790							}
1791                        };
1792                        req.open(currentForm.method, currentForm.action);
1793                        req.withCredentials = true;
1794                        req.send(data);
1795					}
1796			    })
1797			})(currentForm, ajaxSubmit);
1798		}
1799	};
1800
1801    function isIOS() {
1802        return /iPad|iPhone|iPod/.test(navigator.userAgent) && !window.MSStream;
1803    }
1804
1805    // special chracter escaped regex from https://emailregex.com/ with capital letter allowance added
1806    var validEmailRegex="^(?:[a-zA-Z0-9!#$%&\'*+/=?^_`{|}~-]+(?:\\.[a-zA-Z0-9!#$%&\'*+/=?^_`{|}~-]+)*|\"(?:[\\x01-\\x08\\x0b\\x0c\\x0e-\\x1f\\x21\\x23-\\x5b\\x5d-\\x7f]|\\\\[\\x01-\\x09\\x0b\\x0c\\x0e-\\x7f])*\")@(?:(?:[a-zA-Z0-9](?:[a-zA-Z0-9-]*[a-zA-Z0-9])?\\.)+[a-zA-Z0-9](?:[a-zA-Z0-9-]*[a-zA-Z0-9])?|\\[(?:(?:25[0-5]|2[0-4][0-9]|[01]?[0-9][0-9]?)\\.){3}(?:25[0-5]|2[0-4][0-9]|[01]?[0-9][0-9]?|[a-zA-Z0-9-]*[a-zA-Z0-9]:(?:[\\x01-\\x08\\x0b\\x0c\\x0e-\\x1f\\x21-\\x5a\\x53-\\x7f]|\\\\[\\x01-\\x09\\x0b\\x0c\\x0e-\\x7f])+)\\])$"
1807    var validEmailRegexObj = new RegExp(validEmailRegex);
1808
1809	var validateField = function(field, options){
1810
1811		var o = options ? options : {};
1812
1813		var validators = field.getAttribute('data-validator').split("|");
1814		var errorSpan = field.getAttribute('type') === 'file' ? field.parentNode.nextElementSibling : field.parentNode.querySelector(".ao-form-error-message");
1815		errorSpan.innerHTML = "&nbsp;";
1816
1817		var errorMessageArr = [];
1818		var errorMessageOverrideArr = (field.getAttribute('data-error-message')) ? field.getAttribute('data-error-message').split("::") : false;
1819
1820		field.classList.remove("ao-form-error");
1821
1822         if(field.getAttribute('type') === 'file'){
1823             field.parentNode.classList.remove("ao-file-upload-error");
1824             field.previousElementSibling.querySelector('label').classList.remove("ao-file-upload-error-label");
1825         }
1826
1827		for(var i=0; i<errorMessageOverrideArr.length; i++){
1828			var errorMessageOverride = errorMessageOverrideArr[i].split("|");
1829			errorMessageArr[ errorMessageOverride[0] ] = errorMessageOverride[1];
1830		}
1831
1832
1833		for(var j=0; j<validators.length; j++) {
1834			var validationType = validators[j];
1835			var hasErrors = false;
1836
1837			switch (validationType) {
1838
1839				case "required":
1840					if (o.isCombo) {
1841						var validationComboFields = field.querySelectorAll("input");
1842						var hasRequired = false;
1843
1844						for (var k = 0; k < validationComboFields.length; k++) {
1845							if (validationComboFields[k].checked) {
1846								hasRequired = true;
1847							}
1848						}
1849
1850						if (!hasRequired) {
1851							hasErrors = true;
1852						}
1853					}
1854                    else if(o.isDate) {
1855						var validationDateFields = field.querySelectorAll("input:not(.ao-form-field-date-input), select");
1856						var hasRequired = true;
1857
1858						for (var l = 0; l < validationDateFields.length; l++) {
1859							if (! validationDateFields[l].value.trim()) {
1860								validationDateFields[l].classList.add("ao-form-error");
1861								hasRequired = false;
1862							} else {
1863								validationDateFields[l].classList.remove("ao-form-error");
1864							}
1865						}
1866
1867						if (!hasRequired) {
1868							hasErrors = true;
1869						}
1870					} else if (!field.value.trim()) {
1871                         if (field.getAttribute("type") === "file") {
1872                            const uniqueDropzoneId = inputToDropzoneMap.get(field);
1873                            if (uniqueDropzoneId) {
1874                                const dropzoneData = dropzoneFileCollections[uniqueDropzoneId];
1875                                if (dropzoneData && dropzoneData.files && dropzoneData.files.length > 0) {
1876                                    return false;
1877                                }
1878                            }
1879                        } 
1880						hasErrors = true;
1881					}
1882					break;
1883				case "date":
1884					if(o.isDate) {
1885						var validationDateFields = field.querySelectorAll("input");
1886
1887						for (var m = 0; m < validationDateFields.length; m++) {
1888							var dateType = validationDateFields[m].getAttribute("placeholder");
1889
1890							switch(dateType){
1891								case "MM":
1892									if(validationDateFields[m].value && !/^([0]?[1-9]|1[012])$/.test(validationDateFields[m].value) ){
1893										validationDateFields[m].classList.add("ao-form-error");
1894										hasErrors = true;
1895									} else {
1896										validationDateFields[m].classList.remove("ao-form-error");
1897									}
1898									break;
1899
1900								case "DD":
1901									if(validationDateFields[m].value && !/^([0]?[1-9]|[12]\d|3[01])$/.test(validationDateFields[m].value) ){
1902										validationDateFields[m].classList.add("ao-form-error");
1903										hasErrors = true;
1904									} else {
1905										validationDateFields[m].classList.remove("ao-form-error");
1906									}
1907									break;
1908
1909								case "YY":
1910									if(validationDateFields[m].value && !/^(0?[1-9]|[1-9][0-9])$/.test(validationDateFields[m].value) ){
1911										validationDateFields[m].classList.add("ao-form-error");
1912										hasErrors = true;
1913									} else {
1914										validationDateFields[m].classList.remove("ao-form-error");
1915									}
1916									break;
1917
1918								case "YYYY":
1919									if(validationDateFields[m].value && !/^[0-9]{4}$/.test(validationDateFields[m].value) ){
1920										validationDateFields[m].classList.add("ao-form-error");
1921										hasErrors = true;
1922									} else {
1923										validationDateFields[m].classList.remove("ao-form-error");
1924									}
1925									break;
1926
1927								case "h":
1928									if(validationDateFields[m].value && !/^([0]?[1-9]|1[012])$/.test(validationDateFields[m].value) ){
1929										validationDateFields[m].classList.add("ao-form-error");
1930										hasErrors = true;
1931									} else {
1932										validationDateFields[m].classList.remove("ao-form-error");
1933									}
1934									break;
1935
1936								case "H":
1937									if(validationDateFields[m].value && !/^([0]?[0-9]|1[0-9]|2[0-3])$/.test(validationDateFields[m].value) ){
1938										validationDateFields[m].classList.add("ao-form-error");
1939										hasErrors = true;
1940									} else {
1941										validationDateFields[m].classList.remove("ao-form-error");
1942									}
1943									break;
1944
1945								case "mm":
1946									if(validationDateFields[m].value && !/^[0-5][0-9]$/.test(validationDateFields[m].value) ){
1947										validationDateFields[m].classList.add("ao-form-error");
1948										hasErrors = true;
1949									} else {
1950										validationDateFields[m].classList.remove("ao-form-error");
1951									}
1952									break;
1953							}
1954						}
1955					}
1956					break;
1957				case "email":
1958					if (field.value && !validEmailRegexObj.test(field.value)) {
1959						hasErrors = true;
1960					}
1961					break;
1962				case "nc_email":
1963                    if (field.value && (/^.*@(163[.]com|aol[.]com|bellsouth[.]net|blueyonder[.]co[.][a-z]{2}|btconnect[.]com|charter[.]com|comcast[.]net|cox[.]net|earthlink[.]net|email[.]com|gmail[.]co.[a-z]{2}|gmail[.]com|hotmail[.]co[.][a-z]{2}|hotmail[.]com|juno[.]com|mail[.]com|mail[.]ru|mindspring[.]com|msn[.]com|ntlworld[.]com|orange[.]fr|rogers[.]com|sbcglobal[.]net|shaw[.]ca|sympatico[.]ca|telus[.]net|verizon[.]net|virgin[.]net|virginmedia[.]com|yahoo[.]ca|yahoo[.]co[.][a-z]{2}|yahoo[.]com|ymail[.]com|icloud[.]com|me[.]com|mac[.]com|outlook[.]com|live[.]com|att[.]net|.*[.]rr[.]com|rr[.]com|qq[.]com|gmx[.]de|yandex[.]ru|libero[.]it|mailinator[.]com)$/i.test(field.value)
1964                        || field.value && !validEmailRegexObj.test(field.value))) {
1965                        hasErrors = true;
1966                    }
1967                    break;
1968                case "ng_email":
1969                    if (field.value && (!/^(?!(abuse@|accounting@|accounts@|adm@|admin@|administration@|administrator@|admissions@|ads@|all@|answers@|anti-spam@|antispam@|asdf@|billing@|ceo@|comments@|compliance@|contact@|contactus@|customer@|
1969customercare@|customerservice@|database@|decliend@|decline@|declined@|denied@|designer@|devnull@|director@|dns@|email@|employment@|enquiries@|everyone@|fbl@|feedback@|finance@|ftp@|general@|hello@|helpdesk@|home@|hostmaster@|hr@|info@|information@|inoc@|investorrelations@|ispfeedback@|ispsupport@|jobs@|lawyer@|lawyers@|legal@|list@|list-request@|mail@|mailbox@|mail-daemon@|maildaemon@|mail-deamon@|manager@|managers@|marketing@|me@|media@|mediarelations@|mkt@|news@|noc@|noreplies@|no-reply@|noreply@|noemail@|nospam@|nothanks@|null@|office@|operations@|orders@|phish@|phishing@|post@|postbox@|postmaster@|prepress@|president@|press@|privacy@|purchasing@|qwer@|qwert@|qwerty@|reception@|refuse@|refused@|registrar@|remove@|request@|reservations@|returns@|root@|sales@|secretary@|security@|service@|services@|shop@|spam@|staff@|studio@|subscribe@|support@|sysadmin@|tech@|undisclosed-recipients@|unsubscribe@|usenet@|users@|uucp@|web@|webmaster@|welcome@|www@)).*/i.test(field.value)
1970                        || field.value && !validEmailRegexObj.test(field.value) ) ){
1971                        hasErrors = true;
1972                    }
1973                    break;
1974				case "numeric":
1975					if (field.value && !/^\d+$/.test(field.value)) {
1976						hasErrors = true;
1977					}
1978					break;
1979				case "alphabetic":
1980					if (field.value && !/^[a-zA-Z]+$/.test(field.value)) {
1981						hasErrors = true;
1982					}
1983					break;
1984				case "alphanumeric":
1985					if (field.value && !/^[a-zA-Z0-9]*$/.test(field.value)) {
1986						hasErrors = true;
1987					}
1988					break;
1989				case "minlength":
1990					if (field.value && field.value.length < field.getAttribute('data-minlength') || 0) {
1991						hasErrors = true;
1992					}
1993					break;
1994				case "maxlength":
1995					if (field.value && field.value.length > field.getAttribute('maxlength') || 0) {
1996						hasErrors = true;
1997					}
1998					break;
1999                case "minyear":
2000                    if(o.isDate) {
2001                        var validationDateFields = field.querySelectorAll("input");
2002
2003                        for (var m = 0; m < validationDateFields.length; m++) {
2004                            var dateType = validationDateFields[m].getAttribute("placeholder");
2005
2006                            switch(dateType){
2007                                case "YY":
2008                                case "YYYY":
2009                                    if(validationDateFields[m].value < field.getAttribute('data-minyear') || 0 ){
2010                                        validationDateFields[m].classList.add("ao-form-error");
2011                                        hasErrors = true;
2012                                    } else {
2013                                        validationDateFields[m].classList.remove("ao-form-error");
2014                                    }
2015                                    break;
2016                            }
2017                        }
2018                    }
2019                    break;
2020                case "maxyear":
2021                    if(o.isDate) {
2022                        var validationDateFields = field.querySelectorAll("input");
2023
2024                        for (var m = 0; m < validationDateFields.length; m++) {
2025                            var dateType = validationDateFields[m].getAttribute("placeholder");
2026
2027                            switch(dateType){
2028                                case "YY":
2029                                case "YYYY":
2030                                    if(validationDateFields[m].value > field.getAttribute('data-maxyear') || 0 ){
2031                                        validationDateFields[m].classList.add("ao-form-error");
2032                                        hasErrors = true;
2033                                    } else {
2034                                        validationDateFields[m].classList.remove("ao-form-error");
2035                                    }
2036                                    break;
2037                            }
2038                        }
2039                    }
2040                    break;
2041				case "match":
2042				    var matchField = document.getElementById(field.getAttribute('data-match'));
2043					if (field && matchField && field.value != matchField.value ) {
2044						hasErrors = true;
2045					}
2046					break;
2047				case "phoneus":
2048					if(field.value && !/^(\+?1?)?(-?\s?\.?)?(\([2-9]([02-9]\d|1[02-9])\)|[2-9]([02-9]\d|1[02-9]))-?\s?\.?[2-9]([0-9]{2})\s?-?\.?\d{4}$/.test(field.value)) {
2049						hasErrors = true;
2050					}
2051					break;
2052                case "phoneint":
2053                    if(field.value && !/^\+(?:[0-9] ?){6,14}[0-9]$/.test(field.value)) {
2054                        hasErrors = true;
2055                    }
2056                case "phoneall":
2057                    if(field.value && !/(^(\+?1?)?(-?\s?\.?)?(\([2-9]([02-9]\d|1[02-9])\)|[2-9]([02-9]\d|1[02-9]))-?\s?\.?[2-9]([0-9]{2})\s?-?\.?\d{4}$)|(^\+(?:[0-9] ?){6,14}[0-9]$)/.test(field.value)) {
2058                        hasErrors = true;
2059                    }
2060                    break;
2061				case "url":
2062					if(field.value && !/(http|ftp|https):\/\/[\w-]+(\.[\w-]+)+([\w.,@?^=%&amp;:/~+#-]*[\w@?^=%&amp;/~+#-])?/.test(field.value)) {
2063						hasErrors = true;
2064					}
2065					break;
2066				case "custom":
2067					var pattern = new RegExp(field.getAttribute('data-custom'));
2068
2069					if (field.value && !pattern.test(field.value)) {
2070						hasErrors = true;
2071					}
2072					break;
2073			}
2074
2075			if (hasErrors){
2076				if(! o.isDate)
2077                    field.classList.add("ao-form-error");
2078
2079                field.setAttribute("aria-invalid", "true");
2080				errorSpan.innerHTML = ( errorMessageArr[validationType] ) ? errorMessageArr[validationType] : "Invalid";
2081
2082                if(o.isFileUpload){
2083                    field.parentNode.classList.add("ao-file-upload-error");
2084                    field.previousElementSibling.querySelector('label').classList.add("ao-file-upload-error-label");
2085                }
2086
2087				return false;
2088			}
2089		}
2090
2091		return true;
2092	};
2093
2094    function debounce(a,b,c){var d;return function(){var e=this,f=arguments;clearTimeout(d),d=setTimeout(function(){d=null,c||a.apply(e,f)},b),c&&!d&&a.apply(e,f)}}
2095
2096	return {
2097		load: function(opts) {
2098			loadForm(opts);
2099		},
2100		loadAll: function(){
2101			for(var i=0; i<w._aoForms.length; i++){
2102				loadForm(w._aoForms[i]);
2103			}
2104		}
2105	};
2106
2107}(window));
2108
2109/*** FormData for older browsers ***/
2110(function(w) {
2111    if (w.FormData)
2112        return;
2113    function FormData() {
2114        this.fake = true;
2115        this.boundary = "--------FormData" + Math.random();
2116        this._fields = [];
2117    }
2118    FormData.prototype.append = function(key, value) {
2119        this._fields.push([key, value]);
2120    }
2121    FormData.prototype.toString = function() {
2122        var boundary = this.boundary;
2123        var body = "";
2124        this._fields.forEach(function(field) {
2125            body += "--" + boundary + "\r\n";
2126            // file upload
2127            if (field[1].name) {
2128                var file = field[1];
2129                body += "Content-Disposition: form-data; name=\""+ field[0] +"\"; filename=\""+ file.name +"\"\r\n";
2130                body += "Content-Type: "+ file.type +"\r\n\r\n";
2131                body += file.getAsBinary() + "\r\n";
2132            } else {
2133                body += "Content-Disposition: form-data; name=\""+ field[0] +"\";\r\n\r\n";
2134                body += field[1] + "\r\n";
2135            }
2136        });
2137        body += "--" + boundary +"--";
2138        return body;
2139    }
2140    w.FormData = FormData;
2141})(window);

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.